Skip to content

Instantly share code, notes, and snippets.

@ultramcu
Last active February 17, 2024 22:53
Show Gist options
  • Save ultramcu/cbdc598bbc1fcd0e5f8a to your computer and use it in GitHub Desktop.
Save ultramcu/cbdc598bbc1fcd0e5f8a to your computer and use it in GitHub Desktop.
C Library for Raspberry Pi Send/Receive Serial
/*************************
* UART For Raspberry Pi (2014/10/10)
* gcc version 4.6.3 (Debian 4.6.3-14+rpi1)
*
* copyright ultra_mcu@msn.com
* www.appstack.in.th
* https://github.com/ultramcu/AppStackUART
* ***********************/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/select.h>
#include <string.h>
#include <time.h>
#include <glob.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "app_stack_uart.h"
int32_t uart_begin(st_uart *s_uart,char *device,int32_t baudrate,int32_t (*callback)(void *))
{
struct termios termOptions;
struct termios options;
int32_t br = 0;
if(callback != NULL)
{
s_uart->callback_function = callback;
}
if(baudrate >= 1200 && baudrate <= 230400)
{
br = convert_baudrate(baudrate);
}
else
{
printf ("Error : baudrate must be 1200 - 230400\r\n");
return _FALSE_;
}
s_uart->serial_fd = -1;
s_uart->serial_fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
if (s_uart->serial_fd == -1)
{
printf ("Error : open serial device: %s\r\n",device);
perror("OPEN");
return _FALSE_;
}
tcgetattr(s_uart->serial_fd, &options);
options.c_cflag = br | CS8 | CLOCAL | CREAD; //<Set baud rate
options.c_iflag = IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
tcflush(s_uart->serial_fd, TCIFLUSH);
if( tcsetattr(s_uart->serial_fd, TCSANOW, &options) < 0)
{
printf("ERROR : Setup serial failed\r\n");
return _FALSE_;
}
if (pthread_create(&s_uart->th_recv, NULL, (void *)th_serial_recv, (void *)(s_uart)) != _TRUE_)
{
printf("ERROR : initial thread receive serial failed\r\n");
return _FALSE_;
}
return _TRUE_;
}
int32_t serial_send(st_uart *s_uart,char *data)
{
if(strlen(data) < _UART_BUFFER_SIZE_)
{
memset(s_uart->send_buff,0,sizeof(s_uart->send_buff));
sprintf(s_uart->send_buff,"<%s>",data);
return write(s_uart->serial_fd, s_uart->send_buff, strlen(s_uart->send_buff));
}
return -1;
}
int32_t th_serial_recv(void *arg)
{
st_uart *s_uart = (st_uart *)arg;
fd_set rset;
struct timeval tv;
int32_t count = 0;
uint8_t state = 0;
uint8_t i = 0;
while(1)
{
FD_ZERO(&rset);
FD_SET(s_uart->serial_fd, &rset);
tv.tv_sec = 30;
tv.tv_usec = 0;
count = select(s_uart->serial_fd + 1, &rset, NULL, NULL, &tv);
if(count > 0)
{
memset(s_uart->recv_temp,0,_UART_BUFFER_SIZE_);
s_uart->recv_temp_cnt = read(s_uart->serial_fd, (void*)s_uart->recv_temp, _UART_BUFFER_SIZE_);
for(i = 0; i < s_uart->recv_temp_cnt; i++)
{
switch(state)
{
case 0: //check header <
if(s_uart->recv_temp[i] == _UART_PROTO_HEADER_)
{
state = 1;
s_uart->recv_buff_cnt = 0;
}
break;
case 1: //copy data to buffer
if(s_uart->recv_temp[i] == _UART_PROTO_HEADER_)
{
s_uart->recv_buff_cnt = 0;
}
else if(s_uart->recv_temp[i] == _UART_PROTO_FOOTER_)
{
memset(s_uart->data.data,0,_UART_BUFFER_SIZE_);
memcpy(s_uart->data.data,s_uart->recv_buff,s_uart->recv_buff_cnt);
s_uart->data.count = s_uart->recv_buff_cnt;
state = 0;
memset(s_uart->recv_buff,0,_UART_BUFFER_SIZE_);
if(s_uart->callback_function != NULL)
{
(*s_uart->callback_function)(&s_uart->data);
}
}
else
{
s_uart->recv_buff[s_uart->recv_buff_cnt++] = s_uart->recv_temp[i];
}
break;
}
//printf("Out State = %d, char = %c\r\n",state,s_uart->recv_temp[i]);
}
}
else
{
if(s_uart->serial_fd < 0)
{
//close serial
close(s_uart->serial_fd);
}
}
}
}
int32_t convert_baudrate(int32_t baudrate)
{
switch(baudrate)
{
case 1200: return B1200;
case 2400: return B2400;
case 4800: return B4800;
case 9600: return B9600;
case 19200: return B19200;
case 38400: return B38400;
case 57600: return B57600;
case 115200: return B115200;
case 230400: return B230400;
}
return B9600;
}
/*************************
* UART For Raspberry Pi (2014/10/10)
* gcc version 4.6.3 (Debian 4.6.3-14+rpi1)
*
* copyright ultra_mcu@msn.com
* www.appstack.in.th
* https://github.com/ultramcu/AppStackUART
* ***********************/
#ifndef APP_STACK_UART_H
#define APP_STACK_UART_H
#include <pthread.h>
#include <stdint.h>
#define _UART_BUFFER_SIZE_ 255
#define _UART_PROTO_HEADER_ '<'
#define _UART_PROTO_FOOTER_ '>'
#define _TRUE_ 0
#define _FALSE_ -1
typedef struct
{
uint32_t count;
char data[_UART_BUFFER_SIZE_];
}st_uart_data;
typedef struct
{
uint32_t serial_fd;
pthread_t th_recv;
int32_t recv_temp_cnt;
int32_t recv_buff_cnt;
char recv_temp[_UART_BUFFER_SIZE_];
char recv_buff[_UART_BUFFER_SIZE_];
char send_buff[_UART_BUFFER_SIZE_ + 2];
int32_t (*callback_function)(void *);
st_uart_data data;
}st_uart;
int32_t serial_send(st_uart *s_uart,char *data);
int32_t uart_begin(st_uart *s_uart,char *device,int32_t baudrate,int32_t (*callback)(void *));
int32_t convert_baudrate(int32_t baudrate);
int32_t th_serial_recv(void *arg);
#endif // APP_STACK_UART_H
/*************************
* UART For Raspberry Pi (2014/10/10)
* gcc version 4.6.3 (Debian 4.6.3-14+rpi1)
*
* copyright ultra_mcu@msn.com
* www.appstack.in.th
* https://github.com/ultramcu/AppStackUART
* ***********************/
#include <stdint.h>
#include <stdio.h>
#include "app_stack_uart.h"
#define _SERIAL_DEV_ "/dev/ttyACM0"
st_uart MY_UART;
int32_t my_uart_callback_function(void *arg)
{
st_uart_data *data = (st_uart_data *)arg;
printf("Received %2d Bye, Data : %s\r\n",data->count,data->data);
}
int main(void)
{
system("clear");
printf("********************************\r\n");
printf("* Raspberry Pi UART library *\r\n");
printf("* *\r\n");
printf("* www.appstack.in.th *\r\n");
printf("* (2014/10/10) *\r\n");
printf("********************************\r\n");
printf("\r\n");
if(uart_begin(&MY_UART,_SERIAL_DEV_,9600,&my_uart_callback_function) != _TRUE_)
{
printf("Error : uart_begin failed\r\n");
return 0;
}
while(1)
{
serial_send(&MY_UART,"Hello send from Raspberry Pi.");
serial_send(&MY_UART,"A");
sleep(1);
serial_send(&MY_UART,"www.appstack.in.th");
serial_send(&MY_UART,"B");
sleep(1);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment