利用线程的互斥实现串口多线程收发数据从而达到流水灯的效果。多线程串口编程主要分为三步,第一部分,连接串口及开发板,确定设备号;第二部分为串口参数的设置;第三部分为多线程数据的收发。下方有完整代码实现。
目录
一、设置设备号及头文件
在连接好串口与开发板,确定接入linux下后,可输入如下命令查询当前设备号并设置设备号。
二、串口参数设置及串口收发函数
三、多线程部分(此处仅以一个线程为例)
buff数组存放应以具体协议为准:如0x3d,0x11,0x11,0x22,0x00,0x21可以亮灯1。
这里不涉及具体协议。
四、整体思路
五、具体实现代码
/*********************************************************************************
* Copyright: (C) 2019 zyjin
* All rights reserved.
*
* Filename: main.c
* Description: 多线程互斥锁点灯,一次只能亮一个,前提是M3板子要有对应的协议及程序
* Multi-threaded mutex lock lights, only one light at a time, provided that
* the M3 board has a corresponding protocol and program
*
* Created by zyjin on 19-7-9.
*
* Version: 1.0.0(2019年7月9日)
* Author: zyjin <jzy2410723051@163.com><zzzzyjin@foxmail.com>
* ChangeLog: 1, Release initial version on "2019年7月9日 10时27分00秒"
*
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <time.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/types.h>
#include <pthread.h>
#define UART_DEVICE "/dev/ttyUSB0"
static int init_ttyS(int fd_com1)
{
struct termios newtio; //termios结构体
bzero(&newtio, sizeof(newtio));//将此区域置0
tcgetattr(fd_com1, &newtio);//保存原先串口设置
cfsetispeed(&newtio, B115200);//设置波特率
cfsetospeed(&newtio, B115200);//设置波特率
newtio.c_cflag |= (CLOCAL | CREAD);//激活本地连接和接受使能
newtio.c_cflag &= ~PARENB;//设置奇偶校验位
newtio.c_cflag &= ~CSTOPB;//设置停止位
newtio.c_cflag &= ~CSIZE;//设置字符大小
newtio.c_cflag |= CS8;//设置字符大小
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
newtio.c_oflag &= ~(OPOST);
newtio.c_cc[VTIME] = 0;//设置等待时间
newtio.c_cc[VMIN] = 0;//设置最小字符
tcflush(fd_com1, TCIFLUSH);//刷新收到的数据但是不读
tcsetattr(fd_com1,TCSANOW,&newtio);//激活配置,使改变的配置立即生效
return 0;
}
pthread_mutex_t mutex;
int fd_com1;
int uart_send(int fd_com1,unsigned char * bufp, unsigned int bufsize)
{
int r = write(fd_com1, bufp, bufsize);
if(r > 0)
{
printf("%s\r\n","send success");
}
else perror("error to write fd_com1");
return 0;
}
int uart_read(int fd_com1,unsigned char * bufp, unsigned int bufsize)
{
if(read(fd_com1, bufp, bufsize)>0)
{
printf("receive:%s\r\n",bufp);
}
else perror("error to read fd_com1");
return 0;
}
void *s1(char *buff)
{
while(1)
{
sleep(1);
pthread_mutex_lock(&mutex);
buff[1] = 0X11;
buff[2] = 0X22;
buff[3] = 0X11;
uart_send(fd_com1,buff,6);
pthread_mutex_unlock(&mutex);
sleep(3);
}
}
void *s2(char *buff)
{
while(1)
{
sleep(2);
pthread_mutex_lock(&mutex);
buff[1] = 0X22;
buff[2] = 0X11;
buff[3] = 0X11;
uart_send(fd_com1,buff,6);
pthread_mutex_unlock(&mutex);
sleep(2);
}
}
void *s3(char *buff)
{
while(1)
{
sleep(3);
pthread_mutex_lock(&mutex);
buff[1] = 0X22;
buff[2] = 0X22;
buff[3] = 0X22;
uart_send(fd_com1,buff,6);
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main(int argc,char ** argv)
{
fd_com1 = open(UART_DEVICE, O_CREAT | O_APPEND |O_RDWR);//打开串口
if(!fd_com1)
{
return 0;
}
init_ttyS(fd_com1);
pthread_t id1,id2,id3;
char buff[6] = {0x3d,0x11,0x11,0x22,0x00,0x21};
pthread_mutex_init(&mutex,NULL);
/*创建线程一*/
if(pthread_create(&id1,NULL,(void *)s1,(void*) &buff))
{
printf("Create pthread error!\n");
exit(1);
}
/*创建线程2*/
if(pthread_create(&id2,NULL,(void *)s2,(void*) &buff))
{
printf ("Create pthread error!\n");
exit (1);
}
/*创建线程3*/
if(pthread_create(&id3,NULL,(void *)s3,(void*) &buff))
{
printf ("Create pthread error!\n");
exit (1);
}
pthread_join(id1,NULL);
pthread_join(id2,NULL);
pthread_join(id3,NULL);
pthread_mutex_destroy(&mutex);
close(fd_com1);
return 0;
}
六、注意
1)如已经在头文件中包含了线程的头文件<pthread.h>,可是编译的时候却显示对pthread_create等未定义的引用,则需使用libpthread.a库,在CMakeList.txt中加入target_link_libraries(projectname pthread),即链接线程库。
2)此处我用的是stm32f103zet6,且在板子中有对应的代码,即接收到对应的数据,做出什么反应,但此处不涉及这块内容。
3)新手小白,不喜勿喷,如有哪个地方出了错,请指出,代码中有邮箱,也可通过邮箱联系。