CCS News

Tech Note: Notifications From the Serial Library on Data Reception

Tuesday 01 September, 2020

The CCS C Compiler provides an extremely flexibly serial library; it has the ability to use the hardware peripheral or bit bang the pins, to control and monitor flow control, to specify parity, to use a one wire bus, and more. One feature it has is the ability to specify a receive buffer, and the library will automatically use the receive interrupt to buffer incoming characters. Here is an example of creating a stream called STREAM_UART1 on the UART1 hardware peripheral with a 16 byte receive buffer:

#use rs232(UART1, baud=9600, receive_buffer=16, stream=STREAM_UART1)


Essentially the stream works like a file handle that can be used with C standard I/O functions like fputc, fgetc, etc. Using the stream created above, here is a simple loop that echoes data received on the UART back to the UART:

while (kbhit(STREAM_UART1))
{
fputc(fgetc(STREAM_UART1), STREAM_UART1);
}

This example shows the flexibility of the #use rs232() library provided by CCS. The 'receive_buffer' option creates an interrupt on the UART receive to buffer incoming characters and kbhit() and fgetc() accesses that buffer, but if the 'receive_buffer' was removed from the #use rs232(), then kbhit() and fgetc() would instead check for any received data being held by the UART.

The 'receive_buffer' example as shown above has no way of notifying the users software that data is available, except by polling the receive buffer status with kbhit(). The 5.095 version of the CCS C Compiler adds a new option called 'callback' that allows the user to specify a function to be called when the receive buffer goes from empty to not empty. This could be used to mark a semaphore or enable a routine to start parsing data in the receive buffer. Here is an example of adding this new option:

#use rs232(UART1, baud=9600, receive_buffer=16, stream=STREAM_UART1, \
callback=Uart1On

As stated earlier, this example will call the 'Uart1OnRx' function whenever the receive buffer goes from empty to not empty. Here is how the earlier echo example can be changed to use an RTOS with a semaphore to mark when the receive buffer is ready:

#use rtos(timer=0)

int uart_sem = 0;

static void Uart1OnRx(void) {
rtos_signal(uart_sem);
}

#task(rate=10ms)
static void Uart1Task(void) {
for(;;) {
rtos_wait(uart_sem);

while(kbhit(STREAM_UART1)) {
fputc(fgetc(STREAM_UART1), STREAM_UART1);
}
}
}

Alternatively, a function for parsing data in the receive buffer can be queued for execution with the timeouts library:

#include <timeouts.c>

void Uart1OnxTimeout(void* pArgs) {
while(kbhit(STREAM_UART1)) {
putc(getc(STREAM_UART1), STREAM_UART1);
}
}

static void Uart1OnRx(void) {
TimeoutsAdd(Uart1OnxTimeout, NULL, 0);
}



Like us on Facebook. Follow us on Twitter.

About CCS:

CCS is a leading worldwide supplier of embedded software development tools that enable companies to develop premium products based on Microchip PIC® MCU and dsPIC® DSC devices. Complete proven tool chains from CCS include a code optimizing C compiler, application specific hardware platforms and software development kits. CCS' products accelerate development of energy saving industrial automation, wireless and wired communication, automotive, medical device and consumer product applications. Established in 1992, CCS is a Microchip Premier 3rd Party Partner. For more information, please visit https://www.ccsinfo.com.

PIC® MCU, MPLAB® IDE, MPLAB® ICD2, MPLAB® ICD3 and dsPIC® are registered trademarks of Microchip Technology Inc. in the U.S. and other countries.