linux 下基于特定通信协议利用多线程同步通信机制实现的串口通信

</pre><pre name="code" class="cpp">/**
 *@Title:利用多线程同步通信机制实现串口通信
 *@Introduce:主要完成根据特定的通信协议实现串口与PC上特定串口
 *	通信软件的通信。测试版,只是完成主要框架,没有完全将协议的
 *	所有通信方式方法做完。
 *	其中包含的测试功能有:监听主机(PC上的软件)发送的特定请求,
 *	能够识别类型,并解析包含里面的信息,并且自动回复,所写的根
 *	据协议要求的固定消息结构体。
 *	实现原理:多线程,同步,通信。
 *	其中一个线程专门读取串口中从主机传递的信号,并通过识别出来	
 *	的长度(length),将一个完整的包截取下来,利用识别出来的类
 *	型(type)将包以字符串缓存形式发往特定的处理线程。
 *	特定的线程按操作分,有两类,一类主动发出请求信号等待主机回
 *	应;另一类,等待主机发送请求,然后根据指令回应相关信息
 *	说明:在这里,因为只是为了做功能测试,所以所有的解析并根据
 *	相应信息内容做处理的操作统一简化为将内容打印出来显示。
 *@Attention:主要难点代码中也有注释,这边稍微记录我的错误提醒
 *	在这个同步通信机制中,不同线程通过一个全局的指针list_head
 *	m_req_list作为机制,所有需要的线程中传递的结构体都挂在它下
 *	面,然后传递信息的结构体也有通用格式GeneralReqT,根据里面
 *	type参量确定不同类型,buffer存储需要传递的字符串信息。
 *@Explain:包含的文件名有:dev_com_main.c(主函数所在文件)
 *			   dev_com_main.h(主函数的头文件)
 *	list.h(特殊的list_head结构体的说明和相关函数宏的说明文件)
 *	crc16.c,crc16.h(CRC16校验码生成的函数体文件和头文件)
 *	linux下交叉编译试例:
 *  确保上述文件都放在当前文件夹下,输入:
 *  #gcc -o dev dev_com_main.c crc16.c -I ./ -lpthread
 *  交叉编译,更换gcc便好。
 *@Author:wanney	
 *@Date:2014-10-25
 *@e-Mail:wanney216@gmail.com
 *@长江不择细流,泰山不辞抔土。
 */

#include "dev_com_main.h"
#include <pthread.h>
#include <malloc.h> 
#define SHOWCHAR 1
#define SHOWHEX  0
#define HEADLOGO 0xaa55

//对于静态分配的互斥量, 可以把它设置为PTHREAD_MUTEX_INITIALIZER, 
//或者调用pthread_mutex_init
static pthread_mutex_t m_mutex = PTHREAD_MUTEX_INITIALIZER;
//形成一个闭环,是当前结构体的前节点和后节点都指向本身。
static struct list_head m_req_list = {&m_req_list, &m_req_list};
//串口打开的初始化
//参数:串口设备的路径名 dev,设置整型的波特率(注意格式匹配)
//设备路径名出错会报错,波特率输出默认为:9600
//其他参数设默认值:数据位:8位,校验位:无,停止位:1位
int  uart_open (char *dev, int baud)
{
	struct termios tio;
    int fd;
	int baud_flags;

	fd = open(dev, O_RDWR);
	if(fd == -1) {
	//	fprintf(stdout, "open %s error!\n", dev);
		return -1;
	}

	if(tcgetattr(fd, &tio) < 0) {
	//	fprintf(stdout, "tcgetattr error!\n");
		close(fd);
		return -1;
	}

	switch (baud) {
	case 115200:
		baud_flags = B115200;
		break;
	case 57600:
		baud_flags = B57600;
		break;
	case 38400:
		baud_flags = B38400;
		break;
	case 19200:
		baud_flags = B19200;
		break;
	case 9600:
		baud_flags = B9600;
		break;
	case 2400:
		baud_flags = B2400;
		break;
	case 4800:
		baud_flags = B4800;
		break;
	default:
		baud_flags = B9600;
		break;
	}

	fcntl(fd, F_SETFL,O_NONBLOCK);    
	tio.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG | ECHOE);
	tio.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON | BRKINT);
	tio.c_iflag &= ~(CSIZE | PARENB | CSTOPB);
	tio.c_oflag &= ~(OPOST);
	tio.c_cflag = CS8 | baud_flags | CLOCAL | CREAD;
	tio.c_cc[VMIN] = 0;
	tio.c_cc[VTIME] = 0;

	tcflush(fd, TCIFLUSH);
	if(tcsetattr(fd, TCSAFLUSH, &tio) < 0) {
	//	fprintf(stdout,"tcsetattr error!\n");
		close(fd);
		return -1;
	}

	printf("open uart:%s, baud:%d", dev, baud);
	return fd;
}

//初始化:从机参数查询消息的应答消息
void initAnsCheckInfoC(unsigned char * buf,pAnsCheckInfoC p_ans_check_info){
		unsigned char buf_[26] ;
		WORD crc16;
		int i;
		memset(buf_,0x00,sizeof(buf_));		
		p_ans_check_info->infohead.logo = HEADLOGO;
    p_ans_check_info->infohead.type = 0x7006;
    p_ans_check_info->infohead.length = 0x0e;
    p_ans_check_i
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值