#include <reg51.h>
#include "_LCD_R8C.c"
#define INPUT_LENGTH 11
char input[INPUT_LENGTH]; /* The input from the serial port */
int input_pos = 0; /* Current position to write in the input buffer */
int main()
{
int i;
lcd_init();
lcd_clear();
SCON = 0x50;
TMOD = 0x20; /* timer 1, mode 2, 8-bit reload */
TH1 = 0xFD; /* reload value for 2400 baud */
TR1 = 1;
TI = 1;
RI = 1;
while (1 == 1)
{
/* read the next character from the serial port */
input[input_pos++] = getCharacter ();
/* send it back to the original sender */
for (i = 0; i <= input_pos; i++)
{
lcd_print_b(input[i]);
}
}
}
char getCharacter(void)
{
char chr[INPUT_LENGTH]; /* variable to hold the new character */
while (RI != 1) {;}
chr[input_pos++] = SBUF;
RI = 0;
return (chr);
}
I tried displaying the no's which I am receiving from rs232 which is read by the rfreader.
but I am getting the wrong value on the display i.e 002100 instead of 0016221826. but on the hyper terminal I am getting the exact correct value with a $ included at the satrting i.e $0016221826.
First of all, you really need to adopt a sane indention style, this code is very hard to read.
The problem with your code is that you read an array of user input into a local array "chr", then return the address of that array to main, instead of a character. main() does not expect an address, it expects a character. And regardless of that, the array "chr" is invalid once you have left the function anyhow.
Your printing for loop is also incorrect and doesn't make any sense. You keep printing all characters, over and over, each time you receive a new one.
There might be other issues with the hardware or MCU, I just fixed the most obvious software bugs.
#include <reg51.h>
#include "_LCD_R8C.c"
#define INPUT_LENGTH 11
int main()
{
char input[INPUT_LENGTH]; /* The input from the serial port */
int input_pos = 0; /* Current position to write in the input buffer */
lcd_init();
lcd_clear();
SCON = 0x50;
TMOD = 0x20; /* timer 1, mode 2, 8-bit reload */
TH1 = 0xFD; /* reload value for 2400 baud */
TR1 = 1;
TI = 1;
RI = 1;
while(1)
{
/* read the next character from the serial port */
if(input_pos < INPUT_LENGTH) /* check for buffer overflow */
{
input[input_pos] = getCharacter();
lcd_print_b(input[input_post]); /* only makes sense to print each character once */
input_pos++;
}
}
char getCharacter (void)
{
char chr /* variable to hold the new character */
while (RI != 1)
;
chr = SBUF;
RI = 0;
return(chr);
}
Related
I have been working through this problem for quite some time now and have succeeded in getting a partial mark. I would like to know what is wrong with the code that I have, that is preventing me from succeeding under certain conditions
I need one arduino to communicate with another one by sending a string of characters. So far I have succeeded in sending and receiving some data but think that I may be having an issue with the buffer I have set up in my uart_receive_string() function. I will provide all of the necessary information and code needed in order to test this, just let me know if any more info is required and Ill be happy to provide.
Here is a link to the tinkercad driver: https://www.tinkercad.com/things/eUZqkaIHp6J
Just click "Copy and Tinker" and hit the code button up top in order to paste the below code into it. You will need to paste the code into both ardunios by selecting them via the drop down box.
This is the criteria for the question I am working on:
This is the output I should receive in the test driver provided:
Here is the current code that I have implemented:
It is what needs to be copied into tinkercad for both arduino's
#include <stdint.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
void uart_putbyte(unsigned char data);
int uart_getbyte(unsigned char *buffer);
/*
** Define a function named uart_send_string which transmits the contents of
** a standard C string (i.e. a null-terminated char array) over UART. The
** function should iterate over the characters in the array, using a cast to
** convert each to an unsigned char, and transmitting the resulting byte via
** uart_putbyte. The end of the string should be signalled by sending a single
** null byte. That is, the number 0, not the character '0'.
**
** Param: str - string to be transmitted.
**
** Returns: Nothing.
*/
// vvvvvvv I need help with this vvvvvvv
void uart_send_string(char str[])
{
int i = 0;
char ch;
do{
ch = str[i];
uart_putbyte(ch);
i++;
}while(ch != '\0');
}
/*
** Define a function named uart_receive_string which uses uart_getbyte to fetch
** the contents of a standard C string (i.e. a null-terminated char array)
** from UART. The function should wait for characters, and must not return
** until a complete string has been retrieved.
**
** Note that uart_getbyte will return 1 if a byte is available, and zero
** otherwise. Therefore, to fetch a byte and store it in a variable named x,
** you will need to use a construct of the form:
** unsigned char x;
** while (! uart_getbyte(&x)) {
** // Do nothing.
** }
**
** Param: buffer - a char array which has capacity to store a string
** containing at most (buff_len-1) characters. If more than (buff_len-1)
** characters are received, the first (buff_len-1) of them should be
** stored consecutively in the buffer, and any others discarded. The
** string must be terminated correctly with a null terminator in all
** circumstances.
**
** Param: buff_len - an int which specifies the capacity of the buffer.
**
** Returns: Nothing. However, up to buff_len elements of buffer may have been
** overwritten by incoming data.
*/
//vvvvvvv I need help with this vvvvvvv
void uart_receive_string(char buffer[], int buff_len)
{
int i = 0;
unsigned char ch;
while(!uart_getbyte(&ch))
{
if(ch == 0)
{
break;
}
if(i < buff_len-1)
{
ch = buffer[i];
uart_putbyte(ch);
i++;
}
}
buffer[i]=0;
}
/*
***************************************************************************
** Initialise UART.
***************************************************************************
*/
void uart_init(void) {
UBRR0 = F_CPU / 16 / 9600 - 1;
UCSR0A = 0;
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
UCSR0C = (3 << UCSZ00);
}
/*
**************************************************************************
** Send one byte, protecting against overrun in the transmit buffer.
**
** Param: data - a byte to be transmitted.
**
** Returns: Nothing.
***************************************************************************
*/
#ifndef __AMS__
void uart_putbyte(unsigned char data) {
// Wait for empty transmit buffer
while (!(UCSR0A & (1 << UDRE0)));
// Send data by assigning into UDR0
UDR0 = data;
}
#endif
/*
***************************************************************************
** Attempt to receive one byte, returning immediately to sender.
**
** Param: buffer - the address of a byte in which a result may be stored.
**
** Returns: If a byte is available returns 1 and stores the incoming byte in
** location referenced by buffer. Otherwise returns 0 and makes no other
** change to the state.
***************************************************************************
*/
#ifndef __AMS__
int uart_getbyte(unsigned char *buffer) {
// If receive buffer contains data...
if (UCSR0A & (1 << RXC0)) {
// Copy received byte from UDR0 into memory location (*buffer)
*buffer = UDR0;
//
return 1;
}
else {
return 0;
}
}
#endif
/*
***************************************************************************
** Implement main event loop.
***************************************************************************
*/
void process() {
// Use two devices, as indicated in the supplied TinkerCad model. One
// device acts as the sender (is_sender = 1), the other as receiver
// (is_sender = 0). Change this to set the role accordingly.
const int is_sender = 1;
if (is_sender) {
static char * messages_to_send[] = {
"", // Empty string
"A", // String with one symbol.
"Hello from CAB202!", // Multiple symbols
"1234567890abcdefghijklmnopqrstuvwxyz", // Longer than buffer size.
NULL, // End of list
};
static int next_message = 0;
uart_send_string(messages_to_send[next_message]);
next_message ++;
if (messages_to_send[next_message] == NULL) next_message = 0;
_delay_ms(300);
}
else {
#define BUFF_SIZE 20
char buffer[BUFF_SIZE];
uart_receive_string(buffer, BUFF_SIZE);
uart_send_string(buffer);
uart_putbyte('\r');
uart_putbyte('\n');
}
}
int main(void) {
uart_init();
while (1) {
process();
}
return 0;
}
The areas of this code that I am required to work on are these:
This is needed to send the data:
void uart_send_string(char str[])
{
int i = 0;
char ch;
do{
ch = str[i];
uart_putbyte(ch);
i++;
}while(ch != '\0');
}
This is needed to receive the data:
void uart_receive_string(char buffer[], int buff_len)
{
int i = 0;
unsigned char ch;
while(!uart_getbyte(&ch))
{
if(ch == 0)
{
break;
}
if(i < buff_len-1)
{
ch = buffer[i];
uart_putbyte(ch);
i++;
}
}
buffer[i]=0;
}
I am really sorry if this is hard to understand. Ill do my best to clarify any additional information that is needed. I just need to figure out what I am doing incorrectly.
long time I try to implement FatFs module, but its gets crazy after every sd card formatting. (different errors each time). I've decided to go lower and check my SDCard drivers and I've noticed that when I read some (but ALWAYS THE SAME) of sector's field I receive garbage and I can't interpret it.
My driver's test looks like below:
#if 1 //SD Card Test
uint16_t i;
uint8_t CSD; //card capacity
uint8_t CID; //card id
uint8_t Buffer[512]; //this buffer is written to card
for(i=0; i<512;i++)
{
Buffer[i]=i;
}
SD_CardInit(); //card initialization
CSD = SD_Read_CSD(); //read capacity
CID = SD_Read_CSD(); //read ID
SD_WriteBlock(0x200, Buffer, 512); //write Buffer under 0x200 (512) address
SD_Read_Block(0x200); //read buffer from 0x200
CSD = 0;
#endif
I put breakpoint at CSD = 0; line. Here is what I get after writing and reading the same address:
Buffer is filled with numbers from 0 to 255 (two times, because of overflow).
To reduce noise I've minimized SPI frequency to minimum. Nothing changed. But in fact that wrong numbers appears ALWAYS under the same table index and with the same values suggest that is no problem with noise, but some error.
It looks like drivers works properly, because they write and read most of the fields, but always in the same it answer with garbage. I can't find any trace what could I do wrong. Do I write under some permitted address? When I read any random address I receive the same result.
I include functions: read and write (SD_Sector is a global buffer)
WRITE
// Write block of data to the SD card
// input:
// addr - start address of the block (must be power of two)
// pBuf - pointer to the buffer with data
// len - buffer length
// return: SDR_xxx
SDResult_TypeDef SD_WriteBlock(uint32_t addr, uint8_t *pBuf, uint32_t len)
{
uint32_t wait;
uint16_t CRC_loc; // Calculated CRC16 of the block
uint16_t i;
uint8_t cmdres, response, temp;
SDCard_privChipSelect();
// Calculate 16-bit CRC
CRC_loc = CRC16_buf(pBuf,len);
// SDSC card uses byte unit address and
// SDHC/SDXC cards use block unit address (1 unit = 512 bytes)
// For SDHC/SDXC card addr must be converted to block address
#if 0 //TODO: reconsider PiechotM, do not work with that line
if (SD_CardType == SD_HIGH_CAPACITY_SD_CARD) addr >>= 9;
#endif
response = SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK,addr); // CMD24
if (response != 0x00)
{
// Something wrong happened, do nothing
return response; // SD_CMD_READ_SINGLE_BLOCK command returns bad response
}
else
{
wait = 0; response = 0;
while (++wait <= 512/*0x1ff*/ && response == 0xff)
{
temp = 0xFF;
SD_Send( temp );
response = SD_Recv();
}
if (wait >= 0x1ff) return 0xff;
// Send start block token
SD_Send(SD_TOKEN_START_BLOCK);
// Send data block
for (i = 0; i < len; i++)
{
uint8_t temp;
SD_Send( *pBuf++ );
}
// Send CRC
SD_Send(CRC_loc >> 8);
SD_Send((uint8_t)CRC_loc);
}
// Get response from the SD card
cmdres = SD_Recv();
cmdres &= 0x1f;
if (cmdres != SD_TOKEN_DATA_ACCEPTED)
{
// Data block rejected by SD card for some reason
// Release SD card
SD_Send(0xff);
SDCard_privChipDeSelect();
if (cmdres & SD_TOKEN_WRITE_CRC_ERROR) return SDR_WriteCRCError;
if (cmdres & SD_TOKEN_WRITE_ERROR) return SDR_WriteErrorInternal;
return SDR_WriteError;
}
// Wait while the SD card is busy by data programming
wait = 0x7fff; // Recommended timeout is 250ms (500ms for SDXC)
do
{
cmdres = SD_Recv();
} while (cmdres == 0 && --wait);
// Provide extra 8 clocks for the card (from SanDisk specification)
SD_Send(0xff);
// Release SD card
SDCard_privChipDeSelect();
// Must send at least 74 clock ticks to SD Card
for (wait = 0; wait < 10; wait++) SD_Send(0xff);
return SDR_Success;
}
READ
// return:
// 0x00 -- read OK
// 0x01..0xfe -- error response from CMD17
// 0xff -- timeout
uint8_t SD_Read_Block(uint32_t addr)
{
uint32_t wait;
uint16_t i;
uint8_t response;
SDCard_privChipSelect();
#if 0 //TODO: reconsider PiechotM, do not work with that line
if (SD_CardType != SD_HIGH_CAPACITY_SD_CARD) addr <<= 9; // Convert block number to byte offset
#endif
response = SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK,addr); // CMD17
if (response != 0x00)
{
// Something wrong happened, fill buffer with zeroes
for (i = 0; i < 512; i++) SD_sector[i] = 0;
return response; // SD_CMD_READ_SINGLE_BLOCK command returns bad response
}
else
{
wait = 0; response = 0;
while (++wait <= 0x1ff && response != 0xfe) response = SD_Recv();
if (wait >= 0x1ff) return 0xff;
// Read 512 bytes of sector
for (i = 0; i < 512; i++) SD_sector[i] = SD_Recv();
}
// Receive 16-bit CRC (some cards demand this)
SD_CRC16_rcv = SD_Recv() << 8;
SD_CRC16_rcv |= SD_Recv();
// Calculate CRC16 of received buffer
SD_CRC16_cmp = CRC16_buf(&SD_sector[0],512);
SDCard_privChipDeSelect();
// Must send at least 74 clock ticks to SD Card
for (wait = 0; wait < 8; wait++) SD_Send(0xff);
return 0;
}
/* -------------------- WRITE SECTION ------------------------------*/
/* Lonely Wolf library imported */
/*------------------------PiechotM----------------------------------*/
// Send buffer to the SD card
// input:
// pBuf - pointer to the buffer
// len - length of the buffer
// return: last response from SD card
void SD_WriteBuf(uint8_t *pBuf, uint16_t len)
{
while (len--) SD_Send(*pBuf++);
}
I will be very thankful for your help!
Best regards,
Maks Piechota
I want to receive a string(pointer to characters) by UART using ATMEGA16. I burned this code on the kit then I used hyperterminal (realterm) and made a test to input a string ("on") and if it is received then portc (LEDS) will be set to 1 but it doesn't work ... anyone!? :D
Implementation of functions
#include <avr/io.h>
#define F_CPU 8000000UL
unsigned char *x;
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
void uartinit()
{
UCSRB |= (1 << RXEN) | (1 << TXEN);
// Turn on the transmission and reception circuitry
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
// Use 8-bit character sizes
UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value..
// into the low byte of the UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value..
// into the high byte of the UBRR register
}
void uartsend( unsigned char *data )
{
while(*data != '\0')
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) );
/* Put data into buffer, sends the data */
UDR = *data;
data++;
}
while ( !( UCSRA & (1<<UDRE)) );
UDR = *data;
}
unsigned char * uartrecieve()
{
//unsigned char i=0;
// unsigned char * x;
/* Wait for data to be received */
// char * ptr = &UDR;
while ( !(UCSRA & (1<<RXC)) );
while(UDR != '\0')
{
*x = UDR;
x++;
while ( !(UCSRA & (1<<RXC)) );
}
*x = UDR;
return x;
}
and this is main function
#include <avr/io.h>
#include "UARTInterface.h"
int main(void)
{
DDRC=0xFF;
uartinit();
while(1)
{
unsigned char *y;
y=uartrecieve();
if(strcmp(y,"on")==0)
{
PORTC=0xff;
}
//uartsend(y);
//TODO:: Please write your application code
}
}
There are a few problems with your code:
1. You're not allocating any space for the received characters. You have a global unsigned char *x (which is not initialised) that you dereference and assign values to, then increment - this is just overwriting random positions in memory.
You should instead assign some space by creating an array from the calling function (main in this case) and passing a pointer to uartreceive along with the size of the buffer
unsigned char y[20]; // in main
unsigned char len;
len = uartreceive(y, 20);
...
Then (note this is untested)
unsigned char uartrecieve(unsigned char *x, unsigned char size)
{
unsigned char i = 0;
if (size == 0) return 0; // return 0 if no space
while (i < size - 1) { // check space is available (including additional null char at end)
unsigned char c;
while ( !(UCSRA & (1<<RXC)) ); // wait for another char - WARNING this will wait forever if nothing is received
c = UDR;
if (c == '\0') break; // break on NULL character
x[i] = c; // write into the supplied buffer
i++;
}
x[i] = 0; // ensure string is null terminated
return i + 1; // return number of characters written
}
Each time you call this function, it will overwrite the previous contents of rx_buffer so make sure you are finished using it first. Read up on arrays, pointers and strings if you're not certain what's happening here.
Better yet would be to pass in a pointer to uartreceive so that the calling function can supply the area of memory
2. It is unlikely that your serial terminal software will be sending NULL terminated strings by default (i.e. with '\0' at the end), normally it would send a new-line ('\n') character. I believe realterm can do this, but it's worth checking.
3. Reading from UDR will clear the RXC flag, allowing the AVR to write another character into UDR, so reading from UDR twice in a row is probably a bad idea
UBBRL must be written AFTER UBRRH to ensure atomic operation (ie : copy full 16 bits of ubrr AT THE SAME TIME on baud rate divisor.
This is indicated on ATMega doc (for example ATMEGA16 doc http://ww1.microchip.com/downloads/en/devicedoc/doc2466.pdf page 168) :
Writing UBRRL will trigger an immediate update of the baud rate prescaler
Atmel example are written this way
void USART_Init( unsigned int ubrr){
/* Set baud rate */
UBRRH = (unsigned char)(ubrr>>8);
**UBRRL = (unsigned char)ubrr;**
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN)|(1<<TXEN);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}*
When you write the wrong order (UBRRH last), UBRRH is not updated until the next UBRRL write. Doesn't mater most of the time as UBRRH = 0 the most of the time (until BAUD > 100bit/s)
#include<reg51.h>
#include<string.h>
#include"_LCD_R8C.c"
unsigned char c[12];
unsigned char chr[11];
void serial_int (void) interrupt 4
{
if (RI==1)
{
chr[11] = SBUF;
RI = 0;
TI = 0;
}
}
int main()
{
unsigned char a[2][11]={"$0016221826","$0123456789"};
int i,j;
lcd_init();
lcd_clear();
SCON = 0x50;
TMOD = 0x20;
TH1 = 0xFD;
ET0 = 0;
TR1 = 1;
RI = 1;
ES = 1;
EA = 1;
for(j=0;j<1;j++)
{
for(i=0;i<=10;i++)
{
c[i]=chr[i];
}
c[11]='\0';
}
for(i=0;i<=1;i++)
{
j=strcmp(a[i],c); /* !!! Here is the problem !!! */
if(j==0)
{
lcd_printxy(1,1,"yes");
}
else
{
lcd_printxy(1,6,"no");
}
}
}
I am getting the display as "no", please let me know what is the problem?
the problem might be
1) the received array of characters are not converted to string, or
2) the received array of characters are converted to string but not able to compare with the available string..
please go through the program
One obvious bug for starters - change:
unsigned char a[2][11]={"$0016221826","$0123456789"};
to:
unsigned char a[2][12]={"$0016221826","$0123456789"};
(You need to allow room for the terminating '\0' in each string - I'm surprised your compiler didn't complain about this ?)
Also, this line in your interrupt handler is wrong:
chr[11] = SBUF;
Several problems with this - char only has storage for 11 chars, not 12, and you probably want to be accumulating characters from index 0 and then bumping the index, otherwise you're just overwriting the same character each time.
Looking at the rest of the code there are so many other problems that I think you may need to take a step back here and start with a simpler program - get that working first and then add to it in stages.
You might also want to get a decent introductory book on C and study it as there are lots of very basic mistakes in the code, so you might benefit from a better understanding of the language itself.
You only assign a value to chr[11], the rest of the array is uninitialized and will contain random data. You then copy this array containing random data to c (you could use e.g. memcpy here instead of looping yourself), and finally you compare the complete contents of c (which is random data) with one of the entries in a. So it's kind of natural that the result of that comparison will be that the strings are not equal.
Edit: A redesign of the program in the question
Your program has too many problems to be easily fixed, so I decided to try and rewrite it:
#include <reg51.h>
#include <string.h>
#include "_LCD_R8C.c"
#define INPUT_LENGTH 11
#define ACCEPTABLE_INPUT_COUNT 2
char input[INPUT_LENGTH]; /* The input from the serial port */
int input_pos = 0; /* Current position to write in the input buffer */
int input_done = 0; /* 0 = not done yet, 1 = all input read */
void serial_int (void) interrupt 4
{
if (!input_done && RI == 1)
{
/* Put the input at next position in the input buffer */
/* Then increase the position */
input[input_pos++] = SBUF;
RI = 0;
TI = 0;
/* Check if we have received all input yet */
if (input_pos >= INPUT_LENGTH)
input_done = 1;
}
}
int main()
{
/* Array of data that this programs thinks is acceptable */
/* +1 to the input length, to fit the terminating '\0' character */
char acceptable_inputs[ACCEPTABLE_INPUT_COUNT][INPUT_LENGTH + 1] = {
"$0016221826", "$0123456789"
};
iny acceptable_found = 0; /* Acceptable input found? */
/* Initialization */
lcd_init();
lcd_clear();
SCON = 0x50;
TMOD = 0x20;
TH1 = 0xFD;
ET0 = 0;
TR1 = 1;
RI = 1;
ES = 1;
EA = 1;
/* Wait until we have received all input */
while (!input_done)
; /* Do nothing */
/* Check the received input for something we accept */
for (int i = 0; i < ACCEPTABLE_INPUT_COUNT; i++)
{
if (memcmp(acceptable_inputs[i], input, INPUT_LENGTH) == 0)
{
/* Yes, the data received is acceptable */
acceptable_found = 1;
break; /* Don't have to check any more */
}
}
if (acceptable_found)
lcd_printxy(1, 1, "Yes");
else
lcd_printxy(1, 1, "No");
return 0;
}
I sending a string like this:
$13,-14,283,4,-4,17,6,-240,-180#
But is not showing up because the buffer is 'overloading', how can I receive the whole string or how can I clear it after each byte read?
// get a character string
char *getsU2(char *s, int len) {
char *p = s; // copy the buffer pointer
do {
*s = getU2(); // get a new character
if (( *s=='\r') || (*s=='\n')) // end of line...
break; // end the loop s++;
// increment the buffer pointer
len--;
} while (len>1); // until buffer is full
*s = '\0'; // null terminate the string
return p; // return buffer pointer
}
// get a character string
char *getsU2(char *s, int len) {
char *p = s; // copy the buffer pointer
do {
*s = getU2(); // get a new character
if (( *s=='\r') || (*s=='\n')) // end of line...
break; // end the loop
s++;
// increment the buffer pointer
len--;
} while (len>1); // until buffer is full
*s = '\0'; // null terminate the string
return p; // return buffer pointer
}
char getU2(void) {
if(U2STAbits.OERR == 1)
{ U2STAbits.OERR = 0; }
while (!U2STAbits.URXDA); // wait for new character to arrive return U2RXREG;
// read character from the receive buffer }
getsU2(buffer,sizeof(buffer));
Try using the UART receive interrupt. Code below is for a PIC24H; modify appropriately.
In your init function:
IFS0bits.U1RXIF = 0; // clear rx interrupt flag
IFS0bits.U1TXIF = 0; // clear tx interrupt flag
IEC0bits.U1RXIE = 1; // enable Rx interrupts
IPC2bits.U1RXIP = 1;
IEC0bits.U1TXIE = 1; // enable tx interrupts
IPC3bits.U1TXIP = 1;
Create an interrupt handler that places the bytes into a buffer or queue:
void __attribute__((__interrupt__, auto_psv)) _U1RXInterrupt(void)
{
char bReceived;
// Receive Data Ready
// there is a 4 byte hardware Rx fifo, so we must be sure to get all read bytes
while (U1STAbits.URXDA)
{
bReceived = U1RXREG;
// only usethe data if there was no error
if ((U1STAbits.PERR == 0) && (U1STAbits.FERR == 0))
{
// Put your data into a queue
FIFOPut(bReceived);
}
}
IFS0bits.U1RXIF = 0; // clear rx interrupt flag
}
Your queue code is along these lines:
#define FIFO_SIZE 64
char pbBuffer[FIFO_SIZE];
char *pbPut;
char *pbGet;
void FIFOInit(void)
{
pbPut = pbBuffer;
pbGet = pbBuffer;
}
void FIFOPut(char bInput)
{
*pbPut = bInput;
pbPut++;
if (pbPut >= (pbBuffer + FIFO_SIZE))
pbPut = pbBuffer;
}
char FIFOGet(void)
{
char bReturn;
bReturn = *pbGet;
pbGet++;
if (pbGet>= (pbBuffer + FIFO_SIZE))
pbGet= pbBuffer;
}
Obviously, one should beef up the FIFO functions to prevent overflow, return errors on an empty queue, etc.