步骤:
1、打开设备述符。
#define UART_PATH_NAME "/dev/ttyPS0" // 根据实际修改 fd = open(UART_PATH_NAME,O_RDWR | O_NOCTTY | O_NDELAY);
2、设置串口波特率
int set_baud_ratet(struct termios *serial_Setting, int baud_rate) { int i = 0; //支持波特率的列表 int speed_array[] = {B460800, B115200, B19200, B9600, B4800, B2400, B1200, B300}; int name_array[] = {460800, 115200, 19200, 9600, 4800, 2400, 1200, 300}; if (serial_Setting == NULL) { printf("The serial_Setting is NULL. \n"); return -1; } //设置串口输入波特率和输出波特率 for ( i= 0; i < sizeof(speed_array) / sizeof(int); i++) { if (baud_rate == name_array[i]) { cfsetispeed(serial_Setting, speed_array[i]); cfsetospeed(serial_Setting, speed_array[i]); break; } } return 0; }
3、设置数据位
int set_nBits(struct termios *serial_Setting, int nBits) { if (serial_Setting == NULL) { printf("The serial_Setting is NULL. \n"); return -1; } //屏蔽其他标志位 serial_Setting->c_cflag &= ~CSIZE; switch( nBits ) { case 7: serial_Setting->c_cflag |= CS7; break; case 8: serial_Setting->c_cflag |= CS8; break; } return 0; }
4、设置校验位
int set_nEvent(struct termios *serial_Setting, int nEvent) { if (serial_Setting == NULL) { printf("The serial_Setting is NULL. \n"); return -1; } switch( nEvent ) { case 'o': case 'O': serial_Setting->c_cflag |= PARENB; serial_Setting->c_cflag |= PARODD; serial_Setting->c_iflag |= (INPCK | ISTRIP); break; case 'e': case 'E': serial_Setting->c_iflag |= (INPCK | ISTRIP); serial_Setting->c_cflag |= PARENB; serial_Setting->c_cflag &= ~PARODD; break; case 'n': case 'N': serial_Setting->c_cflag &= ~PARENB; break; } return 0; }
5、设置停止位
int set_nStop(struct termios *serial_Setting, int nStop) { if (serial_Setting == NULL) { printf("The serial_Setting is NULL. \n"); return -1; } if( nStop == 1 ) serial_Setting->c_cflag &= ~CSTOPB; else if ( nStop == 2 ) serial_Setting->c_cflag |= CSTOPB; return 0; }
6、设置流控制
void flow_ctrl(struct termios *serial_Setting, int ctrl) { //设置数据流控制 switch(ctrl) { //不使用流控制 case 0 : serial_Setting->c_cflag &= ~CRTSCTS; break; //使用硬件流控制 case 1 : serial_Setting->c_cflag |= CRTSCTS; break; //使用软件流控制 case 2 : serial_Setting->c_cflag |= IXON | IXOFF | IXANY; break; } }
完整连接代码
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h> /* thread */
#include <termios.h> /* POSIX Terminal Control Definitions */
#include <signal.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <time.h>
#include <sys/ioctl.h>
#define UART_PATH_NAME "/dev/ttyPS0" // 根据实际修改
#define UART_BAUD_RATE 115200
#define UART_BITE 8
#define UART_EVENT 'N'
#define UART_STOP 1
int fd;
/****************************************************************************************************
* set_baud_ratet() set seriol setting baud rate.
*
* @Param
* serial_Setting is the struct of termios, baud_rate is the baud rate.
*
* @Return
* If succeed return 0.
****************************************************************************************************/
int set_baud_ratet(struct termios *serial_Setting, int baud_rate)
{
int i = 0;
//支持波特率的列表
int speed_array[] = {B460800, B115200, B19200, B9600, B4800, B2400, B1200, B300};
int name_array[] = {460800, 115200, 19200, 9600, 4800, 2400, 1200, 300};
if (serial_Setting == NULL) {
printf("The serial_Setting is NULL. \n");
return -1;
}
//设置串口输入波特率和输出波特率
for ( i= 0; i < sizeof(speed_array) / sizeof(int); i++)
{
if (baud_rate == name_array[i])
{
cfsetispeed(serial_Setting, speed_array[i]);
cfsetospeed(serial_Setting, speed_array[i]);
break;
}
}
return 0;
}
/****************************************************************************************************
* set_nBits() set seriol setting data bits.
*
* @Param
* serial_Setting is the struct of termios, nBites is the data bits.
*
* @Return
* If succeed return 0.
****************************************************************************************************/
int set_nBits(struct termios *serial_Setting, int nBits)
{
if (serial_Setting == NULL) {
printf("The serial_Setting is NULL. \n");
return -1;
}
//屏蔽其他标志位
serial_Setting->c_cflag &= ~CSIZE;
switch( nBits )
{
case 7:
serial_Setting->c_cflag |= CS7;
break;
case 8:
serial_Setting->c_cflag |= CS8;
break;
}
return 0;
}
/****************************************************************************************************
* set_uEvent() set seriol setting of mode.
*
* @Param
* serial_Setting is the struct of termios, nStop is the mode.
*
* @Return
* If succeed return 0.
****************************************************************************************************/
int set_nEvent(struct termios *serial_Setting, int nEvent)
{
if (serial_Setting == NULL) {
printf("The serial_Setting is NULL. \n");
return -1;
}
switch( nEvent )
{
case 'o':
case 'O':
serial_Setting->c_cflag |= PARENB;
serial_Setting->c_cflag |= PARODD;
serial_Setting->c_iflag |= (INPCK | ISTRIP);
break;
case 'e':
case 'E':
serial_Setting->c_iflag |= (INPCK | ISTRIP);
serial_Setting->c_cflag |= PARENB;
serial_Setting->c_cflag &= ~PARODD;
break;
case 'n':
case 'N':
serial_Setting->c_cflag &= ~PARENB;
break;
}
return 0;
}
/****************************************************************************************************
* set_nStop() set seriol setting of stop bit.
*
* @Param
* serial_Setting is the struct of termios, nStop is stop bit.
*
* @Return
* If succeed return 0.
****************************************************************************************************/
int set_nStop(struct termios *serial_Setting, int nStop)
{
if (serial_Setting == NULL) {
printf("The serial_Setting is NULL. \n");
return -1;
}
if( nStop == 1 )
serial_Setting->c_cflag &= ~CSTOPB;
else if ( nStop == 2 )
serial_Setting->c_cflag |= CSTOPB;
return 0;
}
void flow_ctrl(struct termios *serial_Setting, int ctrl)
{
//设置数据流控制
switch(ctrl)
{
//不使用流控制
case 0 : serial_Setting->c_cflag &= ~CRTSCTS;
break;
//使用硬件流控制
case 1 : serial_Setting->c_cflag |= CRTSCTS;
break;
//使用软件流控制
case 2 : serial_Setting->c_cflag |= IXON | IXOFF | IXANY;
break;
}
}
int uart_init(int uart_fd, int baud_rate, int nBits, int nEvent, int nStop)
{
struct termios serial_Setting;
bzero( &serial_Setting, sizeof( serial_Setting ) ); // 设置SerialPortSetting所有字节为0
tcflush(uart_fd, TCIFLUSH);
/* tcgetattr(serialFd,&options)得到与fd指向对象的相关参数,并将它们保存于options,
该函数还可以测试配置是否正确,该串口是否可用等。
若调用成功,函数返回值为0,若调用失败,函数返回值为1. */
if (0 != tcgetattr(uart_fd, &serial_Setting))
{
printf("Setup Serial Error \n");
return -1;
}
// set baud rate
if ( set_baud_ratet(&serial_Setting, baud_rate) != 0)
return -1;
//修改控制模式,保证程序不会占用串口 (CLOCAL:忽略任何调制解调器状态)
serial_Setting.c_cflag |= CLOCAL;
//修改控制模式,使得能够从串口中读取输入数据 (CREAD:启动接收器)
serial_Setting.c_cflag |= CREAD;
serial_Setting.c_oflag &= ~(ONLCR | OCRNL);
serial_Setting.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
serial_Setting.c_iflag &= ~(ICRNL | INLCR);
serial_Setting.c_iflag &= ~(IXON | IXOFF | IXANY);
flow_ctrl(&serial_Setting, 0); // 设置数据流控制
serial_Setting.c_cflag &= ~CSIZE; // Clears the mask for setting the data size
// set data bits
if ( set_nBits(&serial_Setting, nBits) != 0)
return -1;
// set the mode
if ( set_nEvent(&serial_Setting, nEvent) != 0)
return -1;
// set stop bit
if ( set_nStop(&serial_Setting, nStop) != 0)
return -1;
serial_Setting.c_oflag &= ~OPOST; // No Output Processing raw format output (Output)
serial_Setting.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Non Cannonical mode (Input)
// serial_Setting.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable XON/XOFF flow control both i/p and o/p
// Setting Time outs
serial_Setting.c_cc[VTIME] = 5; // (单位100ms)
serial_Setting.c_cc[VMIN] = 1; // 最少读xx个
tcflush(uart_fd,TCIFLUSH);
if((tcsetattr(uart_fd,TCSANOW,&serial_Setting))!=0)
{
printf("Com set error \n");
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
fd = open(UART_PATH_NAME,O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0){
printf("bd uart open faild \n");
return -1;
}
//设置串口为阻塞状态
if(fcntl(fd,F_SETFL,0)<0) {
printf("fcntl failed\n");
}
//测试是否为终端设备
if(0 == isatty(fd))
{
printf("Standard input is not a terminal device\n");
return -1;
}
//设置参数
if((uart_init(fd, UART_BAUD_RATE, UART_BITE, UART_EVENT, UART_STOP))<0){
return -1;
}
return 0;
}
创建接收线程
pthread_t tid_uart_rcv; fd_uart_rcv = pthread_create(&tid_uart_rcv, NULL, (void *)&threat_uart_rcv, "Uart rcv thread"); if (fd_uart_rcv < 0) { printf("Create thread of uart receive failed. "); }
接收函数
#define READ_BUFF_LENGTH 500 int exit_flag = 0; void threat_uart_rcv() { int ret = 0; u32 rcv_len = 0; // 接收buff长度 u8 buf_tmp[READ_BUFF_LENGTH] = {0}; // 临时缓存区 fd_set rcv_fd_set; // fd集合 struct timeval timeout; // 超时时长 printf("Create thread of uart_receive secceed. \n"); while (!exit_flag) { FD_ZERO(&rcv_fd_set); FD_SET(fd, &rcv_fd_set); // 设置等待超时时长 timeout.tv_sec = 3; // 秒 timeout.tv_usec = 1; // 微妙 ret = select(fd + 1,&rcv_fd_set,NULL,NULL,&timeout); if (ret <= 0) { continue; } if( FD_ISSET(fd,&rcv_fd_set) ){ // 检测fd在集合rcv_fd_set的状态是否变化,变化为true,否则,为false memset(buf_tmp, 0, sizeof(buf_tmp)); // 清空缓存 rcv_len = read(fd,&buf_tmp,sizeof(buf_tmp)); // 读取buffer if (rcv_len == 0) { continue; } // Printf receive buffer. printf("\n\n rcv_len: %d Line: %d \n", rcv_len, __LINE__); int i = 0; for (i=0; i<rcv_len; i++) { printf("0x%02x ", buf_tmp[i]); } printf("\n"); } } return ; }