mirror of
http://180.163.74.83:13000/zhangzhenghao/AP05.git
synced 2025-12-12 15:04:29 +00:00
407 lines
11 KiB
C
407 lines
11 KiB
C
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <unistd.h>
|
||
#include <sys/types.h>
|
||
#include <sys/stat.h>
|
||
#include <fcntl.h>
|
||
#include <termios.h>
|
||
#include <string.h>
|
||
#include <sys/select.h>
|
||
|
||
#include "read_utils.h"
|
||
#include "uart_utils.h"
|
||
#define PRINT_TIME_TAG
|
||
#define DBG_TAG "uart_utils"
|
||
#define DBG_LVL DBG_INFO
|
||
#include "debug_print.h"
|
||
|
||
#define STRING(x) #x
|
||
#define TO_STRING(x) STRING(x)
|
||
|
||
#define S(x) X(x,B##x,TO_STRING(x))
|
||
#define VALID_TERMINAL_SPEED_TABLE \
|
||
S(0)\
|
||
S(50)\
|
||
S(75)\
|
||
S(110)\
|
||
S(134)\
|
||
S(150)\
|
||
S(200)\
|
||
S(300)\
|
||
S(600)\
|
||
S(1200)\
|
||
S(1800)\
|
||
S(2400)\
|
||
S(4800)\
|
||
S(9600)\
|
||
S(19200)\
|
||
S(38400)\
|
||
S(57600)\
|
||
S(115200)\
|
||
S(230400)\
|
||
S(460800)\
|
||
S(500000)\
|
||
S(576000)\
|
||
S(921600)\
|
||
S(1000000)\
|
||
S(1152000)\
|
||
S(1500000)\
|
||
S(2000000)\
|
||
S(2500000)\
|
||
S(3000000)\
|
||
S(3500000)\
|
||
S(4000000)
|
||
|
||
/*************************************************************
|
||
* 功能: 打开串口设备文件
|
||
* 参数: 串口设备文件名
|
||
* 返回值: 串口设备文件描述符
|
||
**************************************************************/
|
||
int uart_open(uart_utils_t *uart, char *dev_name)
|
||
{
|
||
int uart_fd;
|
||
|
||
uart_fd = open(dev_name, O_RDWR|O_NOCTTY);
|
||
if(uart_fd < 0)
|
||
{
|
||
LOG_I("uart_open FATAL\n");
|
||
}
|
||
if(uart != NULL)
|
||
{
|
||
uart->uart_fd = uart_fd;
|
||
uart->saved = 0;
|
||
}
|
||
return uart_fd;
|
||
}
|
||
|
||
void uart_print_attr(struct termios *options)
|
||
{
|
||
int i;
|
||
|
||
LOG_I("c_iflag = 0%o\n", options->c_iflag);
|
||
LOG_I("c_oflag = 0%o\n", options->c_oflag);
|
||
LOG_I("c_cflag = 0%o\n", options->c_cflag);
|
||
LOG_I("c_lflag = 0%o\n", options->c_lflag);
|
||
for(i=VINTR;i<=VEOL2;i++)
|
||
{
|
||
LOG_I("c_cc[%d] = %d\n", i, options->c_cc[i]);
|
||
}
|
||
}
|
||
|
||
/*************************************************************
|
||
* 功能: 串口默认属性
|
||
* 参数: 无
|
||
* 返回值: 无
|
||
**************************************************************/
|
||
static struct termios *uart_default_attr(void)
|
||
{
|
||
struct termios *options = NULL;
|
||
|
||
options = (struct termios *)calloc(1, sizeof(struct termios));
|
||
if(options == NULL)
|
||
{
|
||
LOG_I("uart_default_attr calloc\n");
|
||
goto exit;
|
||
}
|
||
/*
|
||
cfmakeraw() sets the terminal to something like the "raw" mode of the old Version 7 terminal driver:
|
||
input is available character by character, echoing is disabled, and all special processing of terminal input
|
||
and output characters is disabled. The terminal attributes are set as follows:
|
||
*/
|
||
cfmakeraw(options);
|
||
/* Ignore break characters */
|
||
options->c_iflag = IGNBRK;
|
||
/* Enable receiver. */
|
||
options->c_cflag |= CREAD;
|
||
/* Ignore modem status lines. */
|
||
options->c_cflag |= CLOCAL;
|
||
/* Number of bits per byte (mask). */
|
||
options->c_cflag &= ~CSIZE;
|
||
/* Minimum number of bytes read at once [!ICANON]. */
|
||
options->c_cc[VMIN] = 1;
|
||
/* Time-out value (tenths of a second) [!ICANON]. */
|
||
options->c_cc[VTIME] = 0;
|
||
exit:
|
||
return options;
|
||
}
|
||
|
||
static inline const char* valid_terminal_speeds(void)
|
||
{
|
||
#define X(x,y,z) "\n\t " z
|
||
return VALID_TERMINAL_SPEED_TABLE;
|
||
#undef X
|
||
}
|
||
|
||
static inline speed_t check_speed_parameter(int requested_speed)
|
||
{
|
||
switch(requested_speed)
|
||
{
|
||
#define X(x,y,z) case x: return y;
|
||
VALID_TERMINAL_SPEED_TABLE
|
||
default:
|
||
LOG_I("invalid speed parameters, valid values are %s\n", valid_terminal_speeds());
|
||
return B9600;
|
||
#undef X
|
||
}
|
||
}
|
||
|
||
/*************************************************************
|
||
* 功能: 设置串口属性结构体
|
||
* 参数:
|
||
speed:串口波特率(可选2400、4800、9600、115200。可自己酌情修改程序添加支持)
|
||
data_bits:数据位宽(可选5、6、7、8)
|
||
stop_bits:停止位(可选1、2)
|
||
check:奇偶校验位(可选'N'、'O'、'E';分别应着无奇偶校验、奇校验、偶校验)
|
||
flow_ctrl:硬件流控制(0为OFF,1为ON)
|
||
options:串口属结构体,
|
||
* 返回值: 串口属性结构体
|
||
**************************************************************/
|
||
struct termios *uart_set_attr(
|
||
int speed,
|
||
int data_bits,
|
||
int stop_bits,
|
||
int check,
|
||
int flow_ctrl,
|
||
struct termios *options)
|
||
{
|
||
speed_t baud_rate = 0;
|
||
|
||
if(options == NULL)
|
||
{
|
||
options = uart_default_attr();
|
||
}
|
||
switch(data_bits)
|
||
{
|
||
case 5:
|
||
options->c_cflag |= CS5;
|
||
break;
|
||
case 6:
|
||
options->c_cflag |= CS6;
|
||
break;
|
||
case 7:
|
||
options->c_cflag |= CS7;
|
||
break;
|
||
case 8:
|
||
options->c_cflag |= CS8;
|
||
break;
|
||
default:
|
||
options->c_cflag |= CS8;
|
||
break;
|
||
}
|
||
/****************校验位选择****************/
|
||
switch(check)
|
||
{
|
||
case 'O':
|
||
options->c_cflag |= PARENB;//允许输出产生奇偶信息以及输入的奇偶校验
|
||
options->c_cflag |= PARODD;//奇校验
|
||
options->c_iflag |= (INPCK|ISTRIP);//INPCK:启用输入奇偶检测;ISTRIP:去掉第八位(传输时只传7位)
|
||
break;
|
||
case 'E':
|
||
options->c_cflag |= PARENB;//允许输出产生奇偶信息以及输入的奇偶校验
|
||
options->c_cflag &= ~PARODD;//输入和输出是偶校验(ECC)
|
||
options->c_iflag |= (INPCK|ISTRIP);
|
||
break;
|
||
case 'N':
|
||
options->c_cflag &= ~PARENB;//无奇偶校验位
|
||
}
|
||
/****************硬件流控制****************/
|
||
switch (flow_ctrl)
|
||
{
|
||
case '0'://OFF
|
||
options->c_cflag &= ~CRTSCTS;
|
||
options->c_iflag &= ~(IXON|IXOFF|IXANY);
|
||
break;
|
||
case '1'://ON
|
||
options->c_cflag |= CRTSCTS;
|
||
options->c_iflag |= IXON|IXOFF|IXANY;
|
||
break;
|
||
default://OFF
|
||
options->c_cflag &= ~CRTSCTS;
|
||
options->c_iflag &= ~(IXON|IXOFF|IXANY);
|
||
break;
|
||
}
|
||
/****************停止位选择****************/
|
||
if(stop_bits == 1)
|
||
{
|
||
options->c_cflag &= ~CSTOPB;
|
||
}
|
||
else if(stop_bits ==2)
|
||
{
|
||
options->c_cflag |= CSTOPB;
|
||
}
|
||
else
|
||
{
|
||
options->c_cflag &= ~CSTOPB;
|
||
}
|
||
/****************波特率选择****************/
|
||
baud_rate = check_speed_parameter(speed);
|
||
cfsetispeed(options, baud_rate);
|
||
cfsetospeed(options, baud_rate);
|
||
return options;
|
||
}
|
||
|
||
/*************************************************************
|
||
* 功能: 设置回显
|
||
* 参数: 串口设备文件名
|
||
echo:回显(0为关,1为开)
|
||
* 返回值: 无
|
||
**************************************************************/
|
||
void uart_set_echo(uart_utils_t *uart, int echo)
|
||
{
|
||
struct termios options;
|
||
|
||
if (uart != NULL)
|
||
{
|
||
tcgetattr(uart->uart_fd, &options); /* 获取串口属性 */
|
||
if(echo == 0)
|
||
{
|
||
options.c_lflag &= ~ECHO; /* 关回显 */
|
||
}
|
||
else if(echo == 1)
|
||
{
|
||
options.c_lflag |= ECHO; /* 开回显 */
|
||
}
|
||
else
|
||
{
|
||
options.c_lflag &= ~ECHO; /* 关回显 */
|
||
}
|
||
tcsetattr(uart->uart_fd, TCSANOW, &options); /* 设置串口属性 */
|
||
}
|
||
}
|
||
|
||
/*************************************************************
|
||
* 功能: 设置阻塞
|
||
* 参数: 串口设备文件名
|
||
block:阻塞(0为不阻塞,1为阻塞)
|
||
* 返回值: 无
|
||
**************************************************************/
|
||
void uart_set_block(uart_utils_t *uart, int block)
|
||
{
|
||
if (uart != NULL)
|
||
{
|
||
if(block == 0)
|
||
{
|
||
fcntl(uart->uart_fd, F_SETFL, O_NONBLOCK); //read时不阻塞
|
||
}
|
||
else if(block == 1)
|
||
{
|
||
fcntl(uart->uart_fd, F_SETFL, 0); //read时阻塞
|
||
}
|
||
else
|
||
{
|
||
fcntl(uart->uart_fd, F_SETFL, O_NONBLOCK); //read时不阻塞
|
||
}
|
||
}
|
||
}
|
||
|
||
/*************************************************************
|
||
* 功能: 串口初始化程序
|
||
* 参数: 串口设备文件名
|
||
speed:串口波特率(可选2400、4800、9600、115200。可自己酌情修改程序添加支持)
|
||
data_bits:数据位宽(可选5、6、7、8)
|
||
stop_bits:停止位(可选1、2)
|
||
check:奇偶校验位(可选'N'、'O'、'E';分别应着无奇偶校验、奇校验、偶校验)
|
||
flow_ctrl:硬件流控制(0为OFF,1为ON)
|
||
* 返回值: 串口设备文件描述符
|
||
**************************************************************/
|
||
int uart_init(uart_utils_t *uart,
|
||
int speed,
|
||
int data_bits,
|
||
int stop_bits,
|
||
int check,
|
||
int flow_ctrl)
|
||
{
|
||
struct termios *options;
|
||
|
||
if(uart == NULL)
|
||
{
|
||
goto exit;
|
||
}
|
||
if(uart->saved == 0)
|
||
{
|
||
uart->saved = 1;
|
||
tcgetattr(uart->uart_fd, &uart->option_back); //保存串口属性
|
||
}
|
||
|
||
//uart_print_attr(&uart->option_back);
|
||
options = uart_set_attr(speed, data_bits, stop_bits, check, flow_ctrl, NULL);
|
||
tcflush(uart->uart_fd, TCIFLUSH);
|
||
//uart_print_attr(options);
|
||
tcsetattr(uart->uart_fd, TCSANOW, options); /* 设置串口属性 */
|
||
if(options != &uart->option_back){
|
||
free(options);
|
||
}
|
||
return uart->uart_fd;
|
||
exit:
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
* 功能: 串口反初始化程序
|
||
* 参数: 串口设备文件描述符
|
||
* 返回值: 无
|
||
**************************************************************/
|
||
void uart_uninit(uart_utils_t *uart)
|
||
{
|
||
if(uart == NULL)
|
||
{
|
||
return;
|
||
}
|
||
if(uart->saved == 1)
|
||
{
|
||
uart->saved = 0;
|
||
tcgetattr(uart->uart_fd, &uart->option_back); //保存串口属性
|
||
}
|
||
/*关闭串口*/
|
||
close(uart->uart_fd);
|
||
}
|
||
|
||
/*************************************************************
|
||
* 功能: 串口发送字符串
|
||
* 参数: uart_fd:串口设备文件描述符
|
||
str:待发送的字符
|
||
* 返回值: 无
|
||
**************************************************************/
|
||
void uart_send_str(int uart_fd, char *str)
|
||
{
|
||
int ret;
|
||
|
||
ret = write(uart_fd, str, strlen(str));
|
||
if(ret < 0)
|
||
{
|
||
LOG_I("uart write");
|
||
}
|
||
}
|
||
|
||
/*************************************************************
|
||
* 功能: 读一串至截止字符的字符串,在设定的时间内读不到数据则函数返回
|
||
* 参数: uart_fd:串口设备文件描述符
|
||
buffer:存放数据的内存的首地址
|
||
len:存放数据的内存空间的大小
|
||
until:截止字符
|
||
timeout_ms:超时时间(单位:ms)
|
||
* 返回值:
|
||
成功:实际读到的字符数
|
||
失败:-1
|
||
**************************************************************/
|
||
int uart_read_until_char(int uart_fd, char *buffer, int len, unsigned char until, int timeout_ms)
|
||
{
|
||
return read_data_until_char(uart_fd, buffer, len, until, timeout_ms, timeout_ms);
|
||
}
|
||
|
||
/*************************************************************
|
||
* 功能: 设定的时间内读取数据
|
||
* 参数: uart_fd:串口设备文件描述符
|
||
buffer:存放数据的内存的首地址
|
||
len:存放数据的内存空间的大小
|
||
timeout_ms:超时时间(单位:ms)
|
||
* 返回值:
|
||
成功:实际读到的字符数
|
||
失败:-1
|
||
**************************************************************/
|
||
int uart_read_until_time(int uart_fd, char *buffer, int len, int timeout_first, int timeout_interval)
|
||
{
|
||
return read_data_until_time(uart_fd, buffer, len, timeout_first, timeout_interval);
|
||
}
|
||
|