Guide-Vest/src/uart-ctrl.cpp

230 lines
6.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/times.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include<iostream>
#define TIMEOUT_SEC(buflen,baud) (buflen*20/baud+2) //接收超时
#define TIMEOUT_USEC 0
#include "../include/dyp-a05/uart-ctrl.h"
/*******************************************
* 波特率转换函数(请确认是否正确)
********************************************/
static int convBaudRate(unsigned long int baudrate)
{
switch(baudrate){
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;
default:
return B9600;
}
}
/*******************************************
* Setup serial attr
* fdcom: 串口文件描述符pportinfo: 待设置的端口信息(请确认)
*
********************************************/
int uart_set(int fdcom, const pPortInfo_t pportinfo)
{
struct termios termios_old, termios_new;
int baudrate, tmp;
char databit, stopbit, parity, fctl;
bzero(&termios_old, sizeof(termios_old));
bzero(&termios_new, sizeof(termios_new));
cfmakeraw(&termios_new);
tcgetattr(fdcom, &termios_old); //get the serial port attributions
/*------------设置端口属性----------------*/
//baudrates
baudrate = convBaudRate(pportinfo -> baudrate);
cfsetispeed(&termios_new, baudrate); //填入串口输入端的波特率
cfsetospeed(&termios_new, baudrate); //填入串口输出端的波特率
termios_new.c_cflag |= CLOCAL; //控制模式,保证程序不会成为端口的占有者
termios_new.c_cflag |= CREAD; //控制模式,使能端口读取输入的数据
// 控制模式flow control
fctl = pportinfo-> fctl;
switch(fctl){
case 0:{
termios_new.c_cflag &= ~CRTSCTS; //no flow control
}break;
case 1:{
termios_new.c_cflag |= CRTSCTS; //hardware flow control
}break;
case 2:{
termios_new.c_iflag |= IXON | IXOFF |IXANY; //software flow control
}break;
}
//控制模式data bits
termios_new.c_cflag &= ~CSIZE; //控制模式,屏蔽字符大小位
databit = pportinfo -> databit;
switch(databit){
case 5:
termios_new.c_cflag |= CS5;
case 6:
termios_new.c_cflag |= CS6;
case 7:
termios_new.c_cflag |= CS7;
default:
termios_new.c_cflag |= CS8;
}
//控制模式 parity check
parity = pportinfo -> parity;
switch(parity){
case 0:{
termios_new.c_cflag &= ~PARENB; //no parity check
}break;
case 1:{
termios_new.c_cflag |= PARENB; //odd check
termios_new.c_cflag &= ~PARODD;
}break;
case 2:{
termios_new.c_cflag |= PARENB; //even check
termios_new.c_cflag |= PARODD;
}break;
}
//控制模式stop bits
stopbit = pportinfo -> stopbit;
if(stopbit == 2){
termios_new.c_cflag |= CSTOPB; //2 stop bits
}
else{
termios_new.c_cflag &= ~CSTOPB; //1 stop bits
}
//other attributions default
termios_new.c_oflag &= ~OPOST; //输出模式,原始数据输出
termios_new.c_cc[VMIN] = 1; //控制字符, 所要读取字符的最小数量
termios_new.c_cc[VTIME] = 5; //控制字符, 读取第一个字符的等待时间 unit: (1/10)second
tcflush(fdcom, TCIFLUSH); //溢出的数据可以接收,但不读
tmp = tcsetattr(fdcom, TCSANOW, &termios_new); //设置新属性TCSANOW所有改变立即生效 tcgetattr(fdcom, &termios_old);
return(tmp);
}
/*******************************************
* Open serial port
* tty: 端口号 ttyS0, ttyS1, ....
* 返回值为串口文件描述符
********************************************/
int uart_init(const char* dev)
{
return(open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK));
}
/*******************************************
* Close serial port
********************************************/
void uart_deinit(int fdcom)
{
close(fdcom);
}
/********************************************
* send data
* fdcom: 串口描述符data: 待发送数据datalen: 数据长度
* 返回实际发送长度
*********************************************/
int uart_txd(int fdcom, const unsigned char *data, int datalen)
{
int len = 0;
len = write(fdcom, data, datalen);
if(len == datalen){
return (len);
}
else{
tcflush(fdcom, TCOFLUSH);
return -1;
}
}
/*******************************************
* receive data
* 返回实际读入的字节数
*
********************************************/
int uart_rxd(int fdcom, unsigned char *data, int datalen, int baudrate)
{
int readlen, fs_sel;
fd_set fs_read;
struct timeval tv_timeout;
FD_ZERO(&fs_read);
FD_SET(fdcom, &fs_read);
tv_timeout.tv_sec = TIMEOUT_SEC(datalen, baudrate);
tv_timeout.tv_usec = TIMEOUT_USEC;
fs_sel = select(fdcom+1, &fs_read, NULL, NULL, &tv_timeout);
if(fs_sel){
// tcflush(fdcom, TCIFLUSH);
// ms
usleep(300000);
readlen = read(fdcom, data, datalen);
// unsigned char bit = data[0];
return readlen;
}
else{
return (-1);
}
// return -1
return (readlen);
}
#ifdef TEST
int fdcom = 0;
/**
* @brief
* @param
* @retval
*/
int main(int argc, char**argv)
{
fdcom = uart_init("/dev/COM0");
if(fdcom > 0)
{
PortInfo_t portinfo = {115200, 8, 2, 0, 1, 0};
uart_set(fdcom, &portinfo);
printf("[PARAM]: 115200, 8, 2, 0, 1, 0\n");
}
else
{
printf("[ERROR]: open serial port error.\n");
}
uart_deinit(fdcom);
return 0;
}
#endif