版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、linux环境下C语言实现非阻塞方式读取字符串数据的串口测试程序,即串口工具的编写一、前言1.1 关于串口测试工具,网上已经有集成好的应用程序提供大家使用,但其只提供功能接口,内部具体怎么实现的还需要自己去探索; 1.2 关于串口通信的测试程序在网上已经是数见不鲜,但也不排除很多是直接“参考”别人的(ctrl+c),而且很多代码没有相关注释,从而某些细节性的问题就被忽略; 1.3 本例程序不需全部读完,分为3大部分,设置通信协议、读写字符串函数编写、通信的测试函数,测试函数自己选取看两个典型的就OK;如果哪有说的有误,希望大家指正,多交流共同进步; 1.4 要点:本文提供了设置串口通讯的接口,
2、方便大家对程序的复用,感觉还是面向对象的语言更方便呀;在给模块发送指令后需要读取模块返回的数据时,保险起见采用阻塞式读取,且串口一次只能读取8位byte数据,注意读取数据的调用函数;注意在读写命令中存在0x00(零)的16进制的数据时的方式;通信成功,但恰遇到模块总返回操作失败的代码的问题。二、串口测试程序的实现2.1 要实现串口通信的操作,首先是找到需要操作的对象,即具体的串口设备,一般都在Linux嵌入式设备的/dev/路径下有很多串口设备,找到自己所要操作的串口设备,例如本例程所操作的是/dev/ttySAC0, ttySAC0为串口设备名称;2.2 模块的串口通信协议,不同的模块之间有
3、细微差别,自己作相应的改动就好。本例程的通信协议:波特率9600bps, 8位数据位,1位起始位,一位停止位,无奇偶校验。通信成功时,返回的是操作成功或者操作失败的代码,PS:操作失败并不是说的是通信失败,因为去访问模块时,模块给了应答,表明通信是成功的,只能说明是硬件本身操作失败。发送的指令中存在CS,其值为0减去前面CS前面所有16进制的相加-例:80 06 05 01 CS, CS为:0-(80+06+05+01)=74 ,即需要发送的代码为80 06 05 01 74;2.3 源码如下:#include#include#include#include#include#include#i
4、nclude#include#include#define TRUE 1#define FALSE -1#define BUFF_MAXSIZE 2048#define FREQUENCY_00 0 /设定的频率为0#define FREQUENCY_05 5 /设定的频率为5#define FREQUENCY_10 10 /设定的频率为10#define FREQUENCY_20 20 /设定的频率为20#define RESOLUTION_ONE_MM 1 /1表示选择设定的分辨率为1mm#define RESOLUTION_Z_P_ONE_MM 2 /2表示选择设定的分辨率为0.1mm#
5、define MEASURING_POWER_ON 1 /1表示上电即测开启 #define MEASURING_POWER_OFF 0 /0表示上电即测关闭typedef unsigned char un_char;/初始化设置,即设置通信协议int OpenDev(char *dev);/打开串口设备文件int set_speed(int fd, int speed, struct termios* newtio);/设置波特率int Set_Parity(int fd, int databits, int stopbits, int parity);/设置数据位、停止位、校验位/数据读写
6、函数int Write_Data(int fd, void *buf, int len);/发送命令代码函数int Read_Data(int fd, char *buff);/接收命令代码函数/模块的功能函数int Open_LaserModule(int fd);/模块的打开int Close_LaserModule(int fd);/模块的关闭int Set_Address(int fd);/设置地址un_char* Read_Parameter(int fd, un_char* device_parameter);/读取参数un_char* Read_Device_Num(int fd
7、, un_char* device_num);/读取机器号int Distance_Modification(int fd, int decrease_or_increase, int distance_int);/距离修改,参数decrease_or_increase表示修正可选为取负或者取正,参数distance表示要修正的距离int Mea_Interval(int fd, int interval_time_int);/连续测量时设置数据返回时间间隔,参数interval_time_int表示要设定的时间间隔为interval_time_int秒int Distance_StartSt
8、op(int fd, int position_int);/设置距离起止点,参数position_int的值(1顶端算起;0加上模块长度+上面的距离修正)int Set_MeasuringRange(int fd, int range);/设定量程,range表示要设定的量程大小05, 10, 30, 50, 80int Set_Frequency(int fd, int freg);/设定频率,freg表示要设定的频率大小,00,05,10,20int Set_Resolution(int fd, int mode);/设定分辨率,当mode=1表示设定的分辨率为1mm,当mode=2表示设
9、定的分辨率为0.1mmint Measuring_Power(int fd, int on_off);/设定上电即测,on_off=1表示开启该功能,on_off=0表示关闭该功能int Single_Measurement_Broadcast(int fd);/单次测量(广播命令,返回结果存入模块缓存)un_char* Read_Cache(int fd, un_char* cache_data);/读取缓存un_char* Single_Measurement(int fd, un_char* single_mea);/单次测量un_char* Continuous_Measurement
10、(int fd, un_char* continuous_mea);/连续测量int speed_arr=B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300;int name_arr=115200, 38400, 19200, 9600, 4800, 2400, 1200, 300, 115200, 38400, 19200, 9600, 4800, 2400, 1200, 300;int main(int argc, char *
11、argv) int fd; un_char Buff_data_deviceBUFF_MAXSIZE = 0;/我只是测试用,就在栈分配的空间,正式编写一般需要自己分配动态内存 struct termios oldtio, newtio; /打开串口 char *dev = /dev/ttySAC0; fd = OpenDev(dev); tcgetattr(fd, &oldtio); if(fd 0) set_speed(fd, 9600, &newtio);/设置9600bps波特率 else printf(Cant Open Serial Port!/n); exit(0); if(Se
12、t_Parity(fd, 8, 1, S) = FALSE)/调用设置8位数据位,1位停止位及无校验位 printf(Set Parityu Error!/n); exit(1); /测试函数的调用 Open_LaserModule(fd); Set_Resolution(fd, RESOLUTION_Z_P_ONE_MM); Measuring_Power(fd, MEASURING_POWER_ON); Set_Frequency(fd, FREQUENCY_05); Set_MeasuringRange(fd, RANGE_80); sleep(5); Read_Parameter(fd
13、, Buff_data_device); Set_Address(fd); Distance_Modification(fd, DISTANCE_IN, 2); Mea_Interval(fd, 5); Distance_StartStop(fd, 0); sleep(5); Read_Cache(fd, Buff_data_device); sleep(5); Single_Measurement(fd, Buff_data_device); sleep(5); Continuous_Measurement(fd, Buff_data_device); Close_LaserModule(f
14、d); close(fd);/打开文件设备int OpenDev(char *dev) int fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY); if(fd = -1) printf(Cant Open Serial Port!n); return FALSE; else return fd;/设置波特率int set_speed(int fd, int speed, struct termios* newtio) int i; int status; struct termios* Opt = newtio; tcgetattr(fd, Opt);
15、for(i = 0; i sizeof(speed_arr)/sizeof(int); i+) if(speed = name_arri) tcflush(fd, TCIOFLUSH); cfsetispeed(Opt, speed_arri); cfsetospeed(Opt, speed_arri); status = tcsetattr(fd, TCSANOW, Opt); if(status != 0) printf(tcsetattr failed!n); return FALSE; tcflush(fd, TCIOFLUSH); return TRUE;/设置fd的数据位、停止位、
16、奇偶检验位int Set_Parity(int fd, int databits, int stopbits, int parity) struct termios options; if(tcgetattr(fd, &options) != 0) printf(Setup Serial 1 error!n); return FALSE; /对options的起始地址开始的termios结构体内存置零 bzero(&options,sizeof(options); options.c_cflag &= CSIZE; /选择数据位 switch(databits) case 7:options.
17、c_cflag |= CS7; break; case 8:options.c_cflag |= CS8; break; default:printf(Unsupported data size!/n); return FALSE; /选择奇偶校验 switch(parity) case n: case N: options.c_cflag &= (PARENB); options.c_cflag &= (INPCK); break; case o:/偶校验 case O: options.c_cflag |= (PARODD | PARENB); options.c_cflag |= INP
18、CK; break; case e:/偶校验 case E: options.c_cflag |= PARENB; options.c_cflag &= (PARODD); options.c_cflag |= INPCK; break; case s:/无奇偶校验 case S: options.c_cflag &= (PARENB); options.c_cflag &= (CSTOPB); break; default: printf(Unsupported parity!/n); return FALSE; /选择停止位 switch(stopbits) case 1: options
19、.c_cflag &= (CSTOPB); break; case 2: options.c_cflag |= CSTOPB; break; default: printf(Unsupported stop bits!/n); return FALSE; if(parity != n) /修改控制模式,保证程序不会占用串口 options.c_cflag |= CLOCAL; /修改控制模式,使得能够从串口中读取输入数据 options.c_cflag |= CREAD; options.c_lflag &= (ICANON | ECHO | ECHOE); options.c_iflag &
20、= (IXON | IXOFF | IXANY); options.c_lflag &= (ICANON | ECHO | ECHOE | ISIG); /*Input*/ options.c_oflag &= OPOST; /有字符处理或经过TIME个0.1秒后返回 options.c_ccVTIME = 0; options.c_ccVMIN = 0; /如果发生数据溢出,接收数据,但是不再读取 tcflush(fd, TCIFLUSH); /激活配置 (将修改后的termios数据设置到串口中) if(tcsetattr(fd, TCSANOW, &options) != 0) prin
21、tf(Setup Serial error!n); return FALSE; return 0;/写数据函数int Write_Data(int fd, void *buf, int len) int m_fd = fd; int write_count = 0; int nwrite = 0; if(m_fd 0) nwrite = write(fd, (char*)buf + write_count, len); if(nwrite 1) printf(Write Datda Fail!n); break; write_count += nwrite; len -= nwrite; /
22、清除所有正在发生的I/O数据 tcflush(fd, TCIOFLUSH); return write_count;/读取数据int Read_Data(int fd, char* buff) int nread = 0; int fd_max; int nselect; fd_set readfds; FD_ZERO(&readfds); FD_SET(fd,&readfds); fd_max = fd+1; nselect = select(fd_max, &readfds, NULL, NULL, NULL); memset(buff, 0, sizeof(buff); if(nsele
23、ct 0) nread = read(fd, buff, 8); buffnread = 0; int j = 0; while(buffj != 0) printf(the readable data is 0x%xn, buffj); j+; return nread;/开启模块 int Open_LaserModule(int fd) un_char Buff_OpenBUFF_MAXSIZE = 0x80, 0x06, 0x05, 0x01, 0x74; un_char Open_SucceededBUFF_MAXSIZE = 0x80, 0x06, 0x85, 0x01, 0xF4;
24、 un_char Open_FailedBUFF_MAXSIZE = 0x80, 0x06, 0x85, 0x00, 0xF5; Write_Data(fd, Buff_Open, strlen(Buff_Open); Read_Data(fd, Buff_Open); if(strcmp(Buff_Open, Open_Succeeded) = 0) printf(Open_LaserModule Succeeded!n); else if(strcmp(Buff_Open, Open_Failed) = 0) printf(Open_LaserModule Failed, Please T
25、ry Again!n); else printf(NGn); return FALSE; return TRUE;/关闭模块 int Close_LaserModule(int fd) un_char Buff_CloseBUFF_MAXSIZE = 0x80, 0x06, 0x05, 0x00, 0x75; un_char Close_SucceededBUFF_MAXSIZE = 0x80, 0x06, 0x85, 0x01, 0xF4; un_char Close_FailedBUFF_MAXSIZE = 0x80, 0x06, 0x85, 0x00, 0xF5; /要写的数据中间有0x
26、00,因此把要的数据长度指定为5个字节,而不用strlen()函数计算长度 Write_Data(fd, Buff_Close, 5); Read_Data(fd, Buff_Close); if(strcmp(Buff_Close, Close_Succeeded) = 0) printf(Close_LaserModule Succeeded!n); else if(strcmp(Buff_Close, Close_Failed) = 0) printf(Close_LaserModule Failed, Please Try Again!n); else printf(NGn); ret
27、urn FALSE; return TRUE;/读取参数un_char* Read_Parameter(int fd, un_char* device_parameter) un_char Buff_Read_ParameterBUFF_MAXSIZE = 0xFA, 0x06, 0x01, 0xFF; Write_Data(fd, Buff_Read_Parameter, strlen(Buff_Read_Parameter); Read_Data(fd, Buff_Read_Parameter); printf(*The parameter have read!*n); strcpy(de
28、vice_parameter, Buff_Read_Parameter); return device_parameter;/读取机器号,由于串口每次只能读取8个字节,而读取机器号的返回代码有20个字节,所以读取三次数据un_char* Read_Device_Num(int fd, un_char* device_num) int nread = 0; un_char Buff_Read_DeviceNumBUFF_MAXSIZE = 0xFA, 0x06, 0x04, 0xFC; un_char Buff_read_backBUFF_MAXSIZE = 0; un_char *Buff_b
29、p = Buff_read_back; Write_Data(fd, Buff_Read_DeviceNum, strlen(Buff_Read_DeviceNum); nread = Read_Data(fd, Buff_Read_DeviceNum); memcpy(Buff_bp, Buff_Read_DeviceNum, nread); Buff_bp += nread; nread = Read_Data(fd, Buff_Read_DeviceNum); memcpy(Buff_bp, Buff_Read_DeviceNum, nread); Buff_bp += nread; n
30、read = Read_Data(fd, Buff_Read_DeviceNum); strcpy(Buff_bp, Buff_Read_DeviceNum); strcpy(device_num, Buff_read_back); return device_num;/设置地址int Set_Address(int fd) un_char Buff_AddressBUFF_MAXSIZE = 0xFA, 0x04, 0x01, 0x80, 0x81; un_char Address_SucceededBUFF_MAXSIZE = 0xFA, 0x04, 0x81, 0x81; un_char
31、 Address_FailedBUFF_MAXSIZE = 0xFA, 0x84, 0x81, 0x02, 0xFF; Write_Data(fd, Buff_Address, strlen(Buff_Address); Read_Data(fd, Buff_Address); if(strcmp(Buff_Address, Address_Succeeded) = 0) printf(Set_Address Succeeded!n); else if(strcmp(Buff_Address, Address_Failed) = 0) printf(Set Address Error, Ple
32、ase Write Again!n); else printf(NGn); return FALSE; return TRUE;/距离修改,参数decrease_or_increase表示修正可选为取负或者取正,参数distance表示要修正的距离int Distance_Modification(int fd, int decrease_or_increase, int distance_int) un_char decrease_increase = (un_char)decrease_or_increase; un_char distance_ch = (un_char)distance
33、_int; int c_s = -250 - 4 - 6 - decrease_or_increase - distance_int;/十进制250表示十六进制0xFA un_char cs = (un_char)c_s; un_char Buff_Distance_MoBUFF_MAXSIZE = 0; Buff_Distance_Mo0 = 0xFA; Buff_Distance_Mo1 = 0x04; Buff_Distance_Mo2 = 0x06; Buff_Distance_Mo3 = decrease_increase; Buff_Distance_Mo4 = distance_
34、ch; Buff_Distance_Mo5 = cs; Buff_Distance_Mo6 = 0; un_char Distance_ModificationSdBUFF_MAXSIZE =0xFA, 0x04, 0x8B, 0x77; un_char Distance_ModificationFdBUFF_MAXSIZE =0xFA, 0x84, 0x8B, 0x01, 0xF6; Write_Data(fd, Buff_Distance_Mo, strlen(Buff_Distance_Mo); Read_Data(fd, Buff_Distance_Mo); if(strcmp(Buf
35、f_Distance_Mo, Distance_ModificationSd) = 0) if(decrease_or_increase = 43) printf(Distance_Increase_Modification_Succeededn); else printf(Distance_Decrease_Modification_Succeededn); else if(strcmp(Buff_Distance_Mo, Distance_ModificationFd) = 0) if(decrease_or_increase = 43) printf(Distance_Increase_
36、Modification_Failedn); else printf(Distance_Decrease_Modification_Failedn); else printf(NGn); return FALSE; return TRUE;/连续测量时设置数据返回时间间隔,参数interval_time_int表示要设定的时间间隔为interval_time_int秒int Mea_Interval(int fd, int interval_time_int) int c_s = -250 - 4 - 5 - interval_time_int;/十进制250表示十六进制0xFA un_cha
37、r cs = (un_char)c_s; un_char interval_ch = (un_char)interval_time_int; un_char Buff_Mea_IntervalBUFF_MAXSIZE = 0; Buff_Mea_Interval0 = 0xFA; Buff_Mea_Interval1 = 0x04; Buff_Mea_Interval2 = 0x05; Buff_Mea_Interval3 = interval_ch; Buff_Mea_Interval4 = cs; Buff_Mea_Interval5 = 0; un_char Mea_IntervalSd
38、BUFF_MAXSIZE = 0xFA, 0x04, 0x85, 0x7D; un_char Mea_IntervalFdBUFF_MAXSIZE = 0xFA, 0x84, 0x85, 0x01, 0xFC; un_char Write_IntervalErrBUFF_MAXSIZE = 0xFA, 0x84, 0x85, 0x01, 0xFA; Write_Data(fd, Buff_Mea_Interval, strlen(Buff_Mea_Interval); Read_Data(fd, Buff_Mea_Interval); if(strcmp(Buff_Mea_Interval,
39、Mea_IntervalSd) = 0) printf(Mea_Interval_Succeededn); else if(strcmp(Buff_Mea_Interval, Mea_IntervalFd) = 0) printf(Mea_Interval_Failed, Please Try Again!n); else if(strcmp(Buff_Mea_Interval, Write_IntervalErr) = 0) printf(Mea_Interval_Errorn); else printf(NGn); return FALSE; return TRUE;/设置距离起止点,参数
40、position_int的值(1顶端算起;0加上模块长度+上面的距离修正)int Distance_StartStop(int fd, int position_int) int c_s = -250 - 4 - 8 - position_int;/十进制250表示十六进制0xFA un_char cs = (un_char)c_s; un_char position_ch = (un_char)position_int; un_char Buff_StartStopBUFF_MAXSIZE = 0; Buff_StartStop0 = 0xFA; Buff_StartStop1 = 0x04
41、; Buff_StartStop2 = 0x08; Buff_StartStop3 = position_ch; Buff_StartStop4 = cs; Buff_StartStop5 = 0; un_char Mea_Distance_StartStopSdBUFF_MAXSIZE = 0xFA, 0x04, 0x88, 0x7A; un_char Mea_Distance_StartStopFdBUFF_MAXSIZE = 0xFA, 0x84, 0x88, 0x01, 0xF9; /要写的数据中间有0x00,因此把要的数据长度指定为5个字节,而不用strlen()函数计算长度 if(Buff_StartStop3 = 0x00) Write_Data(fd, Buff_StartStop, 5); else Write_Data(fd, Buff_StartStop, strlen(Buff_StartStop); Read_Data(fd, Buff_StartStop); if(strcmp(Buff_StartStop, Mea_Distance_StartStopSd) = 0) printf(Mea_Distance_StartStop_Succeeded!n); else if(strcmp(Buff_StartStop,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 乡镇宿舍改造合同范例
- 代办陪护服务合同范例
- 兼职总工合同范例
- l安装合同范例
- 全款抵押车买卖合同范例
- 润滑购销合同范例
- 关于项目转让合同范例
- 中药制剂技术练习题库及答案
- 静疗练习题含答案
- 2025年庆阳货运运输驾驶员从业资格证考试试题
- 山东省青岛市2024-2025学年七年级上学期11月期中英语试题
- 2024年贵阳新春灯会元宵彩灯策划方案
- 刘润年度演讲2024:进化的力量
- 2024-2030年全球及中国环境健康与安全(EHS)行业市场现状供需分析及市场深度研究发展前景及规划可行性分析研究报告
- 2024年印刷厂管理规章制度范例(三篇)
- 材料工程管理人员个人年终工作总结范文
- ☆问题解决策略:直观分析 教案 2024-2025学年北师大版七年级数学上册
- 养老服务与安全管理作业指导书
- 2024年新人教版七年级上册数学教学课件 第六章 几何图形初步 综合与实践 设计学校田径运动会比赛场地
- GB/T 18385-2024纯电动汽车动力性能试验方法
- 期末+(试题)+-2024-2025学年人教PEP版英语六年级上册
评论
0/150
提交评论