概述
serialcode.c
/*******************************************************************************
* @file serialcode.c
* @copyright 2022
* @author
* @date 2022-6-14
* caption:
*******************************************************************************/
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/kernel.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include "serialcode.h"
unsigned char Write_RingBuff(unsigned char data);
unsigned char Read_RingBuff(unsigned char *rData);
pthread_mutex_t mutex ;
int uart_fd;
Uart_RingBuff_t RingBuff;
int Set_Com_Config(int fd, int baud_rate, int data_bits, char parity, int stop_bits)
{
struct termios new_cfg, old_cfg;
int speed;
/*保存并测试现有串口参数设置,在这里如果串口号等出错,会有相关出错信息*/
if(tcgetattr(fd, &old_cfg) != 0) /*该函数得到fd指向的终端配置参数,并将它们保存到old_cfg变量中,成功返回0,否则-1*/
{
perror("tcgetttr");
return -1;
}
/*设置字符大小*/
new_cfg = old_cfg;
cfmakeraw(&new_cfg); /*配置为原始模式*/
new_cfg.c_cflag &= ~CSIZE; /*用位掩码清空数据位的设置*/
/*设置波特率*/
switch(baud_rate)
{
case 2400:
speed = B2400;
break;
case 4800:
speed = B4800;
break;
case 9600:
speed = B9600;
break;
case 19200:
speed = B19200;
break;
case 38400:
speed = B38400;
break;
default:
case 115200:
speed = B115200;
break;
}
cfsetispeed(&new_cfg, speed); //设置输入波特率
cfsetospeed(&new_cfg, speed); //设置输出波特率
/*设置数据长度*/
switch(data_bits)
{
case 5:
new_cfg.c_cflag &= ~CSIZE;//屏蔽其它标志位
new_cfg.c_cflag |= CS5;
break;
case 6:
new_cfg.c_cflag &= ~CSIZE;//屏蔽其它标志位
new_cfg.c_cflag |= CS6;
break;
case 7:
new_cfg.c_cflag &= ~CSIZE;//屏蔽其它标志位
new_cfg.c_cflag |= CS7;
break;
default:
case 8:
new_cfg.c_cflag &= ~CSIZE;//屏蔽其它标志位
new_cfg.c_cflag |= CS8;
break;
}
/*设置奇偶校验位*/
switch(parity)
{
default:
case 'n':
case 'N': //无校验
{
new_cfg.c_cflag &= ~PARENB;
new_cfg.c_iflag &= ~INPCK;
}
break;
case 'o': //奇校验
case 'O':
{
new_cfg.c_cflag |= (PARODD | PARENB);
new_cfg.c_iflag |= INPCK;
}
break;
case 'e': //偶校验
case 'E':
{
new_cfg.c_cflag |= PARENB;
new_cfg.c_cflag &= ~PARODD;
new_cfg.c_iflag |= INPCK;
}
break;
}
/*设置停止位*/
switch(stop_bits)
{
default:
case 1:
new_cfg.c_cflag &= ~CSTOPB;
break;
case 2:
new_cfg.c_cflag |= CSTOPB;
break;
}
/*设置等待时间和最小接收字符*/
new_cfg.c_cc[VTIME] = 1; /* 读取一个字符等待1*(1/10)s */
new_cfg.c_cc[VMIN] = 0; /* 读取字符的最少个数为1 */
/*处理未接收字符*/
tcflush(fd, TCIFLUSH); //溢出数据可以接收,但不读
/* 激活配置 (将修改后的termios数据设置到串口中)
* TCSANOW:所有改变立即生效
*/
if((tcsetattr(fd, TCSANOW, &new_cfg))!= 0)
{
perror("tcsetattr");
return -1;
}
return 0;
}
int Uart_Send(int fd, char *data, int data_len)
{
int len = 0;
len = write(fd, data, data_len);
if(len > 0){
#if 0
printf("Tx: ");
for(int i=0;i<len;i++)
{
printf("%02x ",data[i]);
}
printf("n");
#endif
}
if(len == data_len) {
return len;
} else {
tcflush(fd, TCOFLUSH); //TCOFLUSH刷新写入的数据但不传送
return -1;
}
}
int Uart_Recv(int fd, char *rev_buf, int data_len)
{
int len, fs_sel;
fd_set fs_read;
struct timeval tv_timeout;
FD_ZERO(&fs_read); //清空集合
FD_SET(fd,&fs_read); // 将一个给定的文件描述符加入集合之中
tv_timeout.tv_sec = 0;
tv_timeout.tv_usec = 5000;
//使用select实现串口的多路通信
fs_sel = select(fd + 1, &fs_read, NULL, NULL, &tv_timeout); //如果select返回值大于0,说明文件描述符发生了变化
//printf("fs_sel = %dn",fs_sel); //如果返回0,代表在描述符状态改变前已超过timeout时间,错误返回-1
if(fs_sel)
{
len = read(fd, rev_buf, data_len);
//printf("len = %d, fs_sel = %dn", len, fs_sel);
return len;
}
else
{
return 0;
}
}
int Uart_Set(int fd, int speed, int databits, int parity, int stopbits)
{
//设置串口数据帧格式
if (Set_Com_Config(fd, speed, databits, parity, stopbits) == 0)
{
return 0;
}
else
{
return -1;
}
}
/*数据接收到缓冲区*/
int Uart_Receive_thread(void)
{
int len,ret;
char Rxbuf[1];
while(1)
{
pthread_mutex_lock(&mutex);//加锁
len = Uart_Recv(uart_fd, Rxbuf, 1);
pthread_mutex_unlock(&mutex);//解锁
if(len)
ret=uart_recv_protocal(Rxbuf[0],len);//数据解析
// ret=Write_RingBuff(Rxbuf[0]);
else
usleep(5000);
}
}
bool ReplyFlag=0;
/*从缓冲区读取数据,解析*/
void Uart_Handle_thread(void)
{
int ret;
char rev[1];
uint8_t s_count = 0;
while(1)
{
if(ReplyFlag==1)
{
pthread_mutex_lock(&mutex);
s_count = Uart_Send(uart_fd, uart_Tx.data, uart_Tx.len);
pthread_mutex_unlock(&mutex);
ReplyFlag=0;
}
else
{
usleep(5000);
}
// ret=Read_RingBuff(rev);
// if(ret)
// uart_recv_protocal(rev[0],ret);
// else
// usleep(5000);
}
}
void pthread()
{
pthread_t id_Uart_Receive,id_Uart_Handle;
int ret1,ret2;
pthread_mutex_init(&mutex,NULL); /*互斥锁*/
ret1 = pthread_create(&id_Uart_Receive, NULL, (void *) Uart_Receive_thread, NULL);
ret2 = pthread_create(&id_Uart_Handle, NULL, (void *) Uart_Handle_thread, NULL);
if(ret1!=0){
printf ("Create Uart_Receive_thread error!n");
close(uart_fd);
exit (1);
}
if(ret2!=0){
printf ("Create Uart_Handle_thread error!n");
exit (1);
}
printf("Create pthreadn");
}
int Uart_init(SerialInfo* info)
{
uart_fd=open(&info->dev_name, O_RDWR | O_NOCTTY);
printf("串口设备名%sn",&info->dev_name);
printf("串口初始化 %dn",uart_fd);
if (uart_fd< 0) return FALSE;
Uart_Set( uart_fd, 9600, 8, 0, 1); //串口设备,波特率,数据位,奇偶性,停止位
return uart_fd;
}
#if 1
/*******************************************************************************
* @FunctionName: Write_RingBuff
* @Author:
* @DateTime: 2022年6月14日
* @Purpose: 向缓冲区的末尾存储一个字节
* @param: data
* @return:
*******************************************************************************/
unsigned char Write_RingBuff(unsigned char data)
{
if(RingBuff.Length >= RINGBUFF_LEN) //判断缓冲区是否已满
{
printf("缓冲区已满!!! RingBuff.Length==%dn",RingBuff.Length);
return false;
}
RingBuff.Ring_Buff[RingBuff.Tail] = data;
RingBuff.Tail = (RingBuff.Tail+1)%RINGBUFF_LEN;//防止越界非法访问
RingBuff.Length++;
return true;
}
/*******************************************************************************
* @FunctionName: Read_RingBuff
* @Author:
* @DateTime: 2022年6月14日
* @Purpose: 读取缓冲区一个字节
* @param: rData
* @return:
*******************************************************************************/
unsigned char Read_RingBuff(unsigned char *rData)
{
if(RingBuff.Length == 0)//判断非空
{
return false;
}
*rData = RingBuff.Ring_Buff[RingBuff.Head];//先进先出FIFO,从缓冲区头出
RingBuff.Head = (RingBuff.Head+1)%RINGBUFF_LEN;//防止越界非法访问
RingBuff.Length--;
return true;
}
void RingBuff_Init(void)
{
//初始化相关信息
RingBuff.Head = 0;
RingBuff.Tail = 0;
RingBuff.Length = 0;
memset(RingBuff.Ring_Buff,0,sizeof(RingBuff.Ring_Buff));
printf("RingBuff_Initn");
}
#endif
serialcode.h
#ifndef SERIALCODE_H
#define SERIALCODE_H
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#define TRUE 0
#define FALSE -1
typedef struct Serial_Info {
char* dev_name;
int baudrate;
int databit;
int stopbit;
char parity;
int vtime;
int vmin;
} SerialInfo;
int set_serial_attr(int fd, SerialInfo* serialinfo);
int serial_init(SerialInfo* info);
int serial_send(int fd, char* send_buf, int data_len);
int Uart_Set(int fd, int speed, int databits, int parity, int stopbits);
int Uart_init(SerialInfo* info);
int Uart_Send(int fd, char *data, int data_len) ;
int Uart_Recv(int fd, char *rev_buf, int data_len);
void pthread();
int uart_fd;
pthread_mutex_t mutex ;
#define RINGBUFF_LEN 1024 //串口缓冲区大小
typedef struct
{
unsigned short Head;
unsigned short Tail;
unsigned short Length;
unsigned char Ring_Buff[RINGBUFF_LEN];
}Uart_RingBuff_t;
extern Uart_RingBuff_t RingBuff;
void RingBuff_Init(void);
#endif
最后
以上就是无辜眼神为你收集整理的Uart 配置的全部内容,希望文章能够帮你解决Uart 配置所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复