i am working with AVR controller atmega16 having 16kb of flash and 1kb of Sram.i have stored data in an static array i.e static char raw_data[15361];and trying to send it over usart using following function:
void USART_TxChar( char data) /* Data transmitting function */
{
UDR = data; /* Write data to be transmitting in UDR */
while (!(UCSRA & (1<<UDRE))); /* Wait until data transmit and buffer get empty */
}
void USART_SendString( char *str) /* Send string of USART data function */
{
int i=0;
while (str[i]!=0)
{
USART_TxChar(str[i]); /* Send each char of string till the NULL */
i++;
}
}
my issue is when ever i put my array in usart it is showing memory full. USART_SendString(raw_data);.i searched online and find out that my function is loading all of the array to RAM hence leading to an error.i found there is a way though which you can send data stored in flash over usart using PROGMEM attribute but it works only for const string type.
so how should i send my data stored in flash memory over usart without leading to memory full error??
static does not mean PROGMEM. You need to place & access them in/from the flash memory. From gcc 4.8 you can use named address spaces
const __flash char raw_data[15361];
and
void USART_SendString(const __flash char *str)
Related
I need to transfer a string between 2 Arduino Uno, using serial communication without functions(just manipulating registers, such as UDR0).
I am able to send a string using
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1
void USART_Init(unsigned int ubrr)
{
UBRR0H=(unsigned char)(ubrr>>8);
UBRR0L=(unsigned char)ubrr;
UCSR0B=(1<<RXEN0)|(1<<TXEN0);
UCSR0C=(1<<USBS0)|(3<<UCSZ00);
}
void USART_Transmit(unsigned char data)
{
while(!(UCSR0A&(1<<UDRE0)));
UDR0=data;
}
void SendString(char *StringPtr)
{
while(*StringPtr !=0x00)
{
USART_Transmit(*StringPtr);
StringPtr++;
}
}
void setup()
{
USART_Init(MYUBRR);
}
void loop()
{
SendString("123456");
delay(1000);
}
but I have no idea how to copy the content of the UDR0 register at the other end. The function should be something like:
unsigned char USART_Receive(void)
{
while(!(UCSR0A&(1<<RXC0)))
return UDR0;
}
But I don't know how to actually use it; I need to save all those chars from the serial to a string, then show the string on a LCD connected to the second Arduino Uno, but every time when I attempt to receive more that one char it's all working very bad(blank spaces, a lot of zeros, invalid characters).
I read that if I have an LCD connected to the second arduino, it's much better to not use the USART_Receive() function, and implement it as an interrupt, but I don't know how to do that either.
Do you have any idea how to transfer the string to the other Arduino?
Perhaps try to put all the chars in an big array and then send that array to your LCD. That way, the time between reading one char and the next one is minimized. (UART is asynchronous, so if you're too slow, you miss the requested data).
I am writing a C program on Eclipse to communicate from my ARM Cortex M4-F microcontroller in I2C with its master, another MCU.
In my I2C library, I use a static global variable to store all the parameters of the communication (address, lenghts, data buffers). The issue is that a part (an array containing the data to be transmitted, which are 8 bits integers) of this variable gets modified when the interrupt (Start condition followed by the slave's address on the I2C bus) happens, even before executing the code I put the handler. It gets assigned to 8, whatever the initial value.
I tried to put breakpoints basically everywhere, and a watchpoint on the variable, the changes arises seemingly from nowhere, not in the while loop, and before the call to my_I2C_Handler(), so the interrupt is the cause apparently.
I also tried setting the variable as volatile, but that changed nothing.
I noticed one interesting thing: putting a printf of the array's data during my_I2C_Init() or my_SlaveAsync(), like so:
printf("%d\n", req.tx_data[0]);
corrects this problem, but why? I want to remove all prints after debugging.
#include <stdint.h>
#include "my_i2c.h"
void I2C1_IRQHandler(void)
{
printf("\nI2C Interrupt\n");
my_I2C_Handler(MXC_I2C1); // MXC_I2C1 is a macro for the registry used
}
int main(void)
{
int error = 0;
printf("\nStarting I2C debugging\n");
// Setup the I2C
my_I2C_Shutdown(MXC_I2C1);
my_I2C_Init(MXC_I2C1);
NVIC_EnableIRQ(I2C1_IRQn); // Enable interrupt
my_I2C_SlaveAsync(MXC_I2C1); // Prepare to receive communication
while (1)
{
LED_On(0);
LED_Off(0);
}
printf("\nDone testing\n");
return 0;
}
The structure of the request containing the parameters of the communication is like this:
typedef struct i2c_req i2c_req_t;
struct i2c_req {
uint8_t addr; // I2C 7-bit Address
unsigned tx_len; // Length of tx data
unsigned rx_len; // Length of rx
unsigned tx_num; // Number of tx bytes sent
unsigned rx_num; // Number of rx bytes sent
uint8_t *tx_data; // Data for mater write/slave read
uint8_t *rx_data; // Data for master read/slave write
};
Is declared like so in the beginning of the file:
static i2c_req_t req;
and assigned this way in my_I2C_Init():
uint8_t rx[1] = {0};
uint8_t tx[1] = {12};
req.addr = 0xAA;
req.tx_data = tx;
req.tx_len = 1;
req.rx_data = rx;
req.rx_len = 1;
req.tx_num = 0;
req.rx_num = 0;
Many thanks for your help
I am receiving/reading data from a GPS module sent via USART3 to the STM32F091.
The data gets there just fine which I confirm by sending it to my PC COM3 port and feeding it to 'u-center' (GPS evaulation software).
My problem is that I want to evaluate the data myself in my C program, and for that purpose I feed it into a Ring Buffer, however, every character of the GPS signal is written multiple times to the buffer, instead of one by one.
For example
GGGGGGGPPPPPPPPSSSSSSSS instead of GPS
I am unsure what I'm doing wrong, maybe it's something really obvious I'm overlooking after staring at this code so long.
Here's the relevant code.
stm32f0xx_it.c
#include <main.h>
void USART3_8_IRQHandler(void)
{
if (USART_FLAG_RXNE != RESET)
{
uint16_t byte = 0;
/* Data reception */
/* Clear Overrun Error Flag, necessary when RXNE is used */
USART_GetITStatus(USART3, USART_IT_ORE);
/* Read from Receive Data Register and put into byte */
byte = USART_ReceiveData(USART3);
(*pRXD3).wr = ((*pRXD3).wr + 1) % (*pRXD3).max;
(*pRXD3).Buffer[(*pRXD3).wr] = byte;
/* Send Data to PC, and reset Transmission Complete Flag */
USART_GetITStatus(USART1, USART_IT_TC);
USART_SendData(USART1, byte);
return;
}
return;
}
uartGPS.h
....
struct GPSuart
{
BYTE Buffer[255];
WORD max;
WORD re;
WORD wr;
};
....
main.h
....
extern volatile BYTE B_ser_txd_3[255];
extern volatile BYTE B_ser_rxd_3[255];
extern volatile struct GPSuart TXD_uart_3;
extern volatile struct GPSuart RXD_uart_3;
extern volatile struct GPSuart *pRXD3;
extern volatile struct GPSuart *pTXD3;
....
Let me know if I should provide additional information.
This:
if (USART_FLAG_RXNE != RESET)
does not test a flag, that code is inspecting the flag constant itself, which is not what you meant.
You need more code, to access the UART's status register and check the flag:
if (USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) != RESET)
I'm currently developing a system which involves sending a request string to a sensor device connected via UART to an Atmel SAML21 Xplained Pro board. I'm testing with an Arduino board as the "sensor device", but eventually, it'll be for a Rotronic HC-2 sensor.
The process goes something like this:
MCU sends string { 99RDD} over UART to sensor
-> delay of up to 500ms
-> Response string of 99 bytes sent back via UART
-> Response transmitted to virtual com port on embedded debugger
My issue is that for some reason, I'm either not getting anything sent back, or it's sending back the variable request_msg
I know that the response from the sensor should be 99 bytes of ASCII, and I've tested both the actual sensor, and the Arduino test board over serial connectors to ensure that the readings are coming back correctly.
The software is using Atmel ASF v4.0, which is great when it works, but the documentation is fairly flaky, so I was hoping someone with more experience could point me as to where I'm going wrong in the code.
I have the following code for my main application:
#include "atmel_start.h"
#include "atmel_start_pins.h"
#include <string.h>
static uint8_t example_hello_world[14] = "Hello World!\n";
static uint8_t example_error_msg[13] = "UART Error!\n";
static uint8_t request_msg[24] = "Sending Sensor Request\n";
static uint8_t rotronic_ascii[8] = "{ 99RDD}";
volatile static uint32_t data_arrived = 0;
volatile static uint32_t reading_received = 0;
static void tx_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr)
{
/* Transfer completed */
gpio_toggle_pin_level(LED0);
}
static void rx_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr)
{
/* Receive completed */
data_arrived = 1;
}
static void err_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr)
{
/* error handle */
io_write(&EDBG_COM.io, example_error_msg, 13);
}
static void tx_cb_COM1(const struct usart_async_descriptor *const io_descr)
{
/* Transfer completed */
gpio_toggle_pin_level(LED0);
}
static void rx_cb_COM1(const struct usart_async_descriptor *const io_descr)
{
/* Receive completed */
reading_received = 1;
}
static void err_cb_COM1(const struct usart_async_descriptor *const io_descr)
{
/* error handle */
io_write(&COM1.io, example_error_msg, 13);
}
int main(void)
{
volatile uint8_t recv_char[99];
atmel_start_init();
// Setup the EDBG Serial Port
usart_async_register_callback(&EDBG_COM, USART_ASYNC_TXC_CB, tx_cb_EDBG_COM);
usart_async_register_callback(&EDBG_COM, USART_ASYNC_RXC_CB, rx_cb_EDBG_COM);
usart_async_register_callback(&EDBG_COM, USART_ASYNC_ERROR_CB, err_cb_EDBG_COM);
usart_async_enable(&EDBG_COM);
// Send a test string to ensure EDBG Serial is working
io_write(&EDBG_COM.io, example_hello_world, 14);
// Setup the Rotronic [Arduino] Serial Port
usart_async_register_callback(&COM1, USART_ASYNC_TXC_CB, tx_cb_COM1);
usart_async_register_callback(&COM1, USART_ASYNC_RXC_CB, rx_cb_COM1);
usart_async_register_callback(&COM1, USART_ASYNC_ERROR_CB, err_cb_COM1);
usart_async_enable(&COM1);
while (1) {
if (reading_received == 0)
{
// Delay for a Bit
delay_ms(5000);
// Notify the EDBG COM Port
io_write(&EDBG_COM.io, request_msg, 24);
// Send the Rotronic ASCII
io_write(&COM1.io, rotronic_ascii, 8);
}
// Check if Reading has been Received
if (reading_received == 1)
{
while (io_read(&COM1.io, &recv_char, 99) == 99)
{
// Write what's on the buffer from the receiver
io_write(&EDBG_COM.io, recv_char, 99);
}
// Reset the flag
reading_received = 0;
}
}
}
You seem to be coding for ASFv3 - v4 will trigger your receive callback for any incoming bytes, not only once when your buffer is full (and you have received every 99 characters).
That means that io_read will most probably never return 99 (because it was only a partial read of your message) and you will most probably never send anything back.
Note the docs say (Scroll down to "different read function behavior..."):
In ASFv4 a data reception type callback in a driver with a ring buffer is triggered for every received data.
The UART apparently is a driver with a ring buffer.
You need to repeatedly call io_read and sum up the number of received bytes until you have got 99. Only then proceed. The ASF docs have an example for that. Make sure you copy code from there that fits your version.
I am using this code to capture data over the USB. The top code crashes the program once a character is received. The bottom works just fine, although I cannot save the data as I want. The top crashes (endless loop) even before calling CDC_Receive_FS()...which is never called. The bottom calls CDC_Receive_FS() as expected.
For the life of me, I cannot see what is wrong with how I am calling my struct that holds an array of buffers that I loop through.
/* Send Data over USB CDC are stored in this buffer */
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
#define MAX_COMMANDS_IN_BUFFER 10 //max commands that can be received and saved without overwriting. Each command has a max size of APP_RX_DATA_SIZE
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
#define APP_RX_DATA_SIZE 256
#define APP_TX_DATA_SIZE 256
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
static struct
{
uint32_t Buffer_Number_Receiving, Buffer_Number_Processing; //Buffer_Number_Receiving is the current position in buffer to receive incoming data. Buffer_Number_Processing is the index of buffer which is being processed.
uint8_t IsCommandDataReceived; // > 0 , data were received. 0 means no data is available
uint8_t UserRxBufferFS[MAX_COMMANDS_IN_BUFFER][APP_RX_DATA_SIZE];//it could save <MaxCommandsInBuffer> number of commands
uint8_t CommandsLens[MAX_COMMANDS_IN_BUFFER]; //save the len of each command
} s_RxBuffers;
static int8_t CDC_Init_FS(void)
{
hUsbDevice_0 = &hUsbDeviceFS;
/* USER CODE BEGIN 3 */
/* Set Application Buffers */
USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, 0);
USBD_CDC_SetRxBuffer(hUsbDevice_0, s_RxBuffers.UserRxBufferFS[s_RxBuffers.Buffer_Number_Receiving] );//Set the buffer to receive incoming data
USBD_CDC_ReceivePacket(hUsbDevice_0);
return (USBD_OK);
/* USER CODE END 3 */
}
This does not:
/* Received Data over USB are stored in this buffer */
uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
static int8_t CDC_Init_FS(void)
{
hUsbDevice_0 = &hUsbDeviceFS;
/* USER CODE BEGIN 3 */
/* Set Application Buffers */
USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, 0);
USBD_CDC_SetRxBuffer(hUsbDevice_0, UserRxBufferFS);
USBD_CDC_ReceivePacket(hUsbDevice_0);
return (USBD_OK);
}
Loop
The line here (the use of this buffer) seems to be the culprit:
USBD_CDC_SetRxBuffer(hUsbDevice_0, s_RxBuffers.UserRxBufferFS[s_RxBuffers.Buffer_Number_Receiving] );//Set the buffer to receive incoming data
Any help/insight would be greatly appreciated.
I would make the Rx_Buffer monodimensional and handle the command history separatly.
static struct
{
uint32_t Buffer_Number_Receiving, Buffer_Number_Processing; //Buffer_Number_Receiving is the current position in buffer to receive incoming data. Buffer_Number_Processing is the index of buffer which is being processed.
uint8_t IsCommandDataReceived; // > 0 , data were received. 0 means no data is available
uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
uint8_t CommandsLens[MAX_COMMANDS_IN_BUFFER]; //save the len of each command
} s_RxBuffers;
Apart from this, since you are usinc a struct (s_RxBuffers type), I think you are not passing the buffer as a pointer in the right way to your function.
I think you should do something like this:
USBD_CDC_SetRxBuffer(hUsbDevice_0, &s_RxBuffers.UserRxBufferFS[0] );//Set the buffer to receive incoming data