6395|11

2144

帖子

3

TA的资源

五彩晶圆(中级)

楼主
 

helper2416_linux串口编程_与Qt串口调试助手通讯 [复制链接]

本帖最后由 lyzhangxiang 于 2014-8-7 22:41 编辑

我无语了,编辑好了,帖子乱码,真心辛苦,求发帖方法,用什么软件编辑好,贴进来可以么?

最新回复

楼主能共享下源码吗  详情 回复 发表于 2015-6-17 14:23
点赞 关注
个人签名电工

回复
举报

241

帖子

4

TA的资源

纯净的硅(初级)

沙发
 
先把文字部分在word中编辑好…然后复制进入……再添加图片和代码什么的

点评

谢谢你,没办法,只恢复了一部分文字,草率编辑下发帖睡觉,没兴趣了。。。。  详情 回复 发表于 2014-8-7 22:52
 
 

回复

2144

帖子

3

TA的资源

五彩晶圆(中级)

板凳
 
1、linux下串口编程,实现两个文件ttyS.c和ttyS.h文件。说白了也就是read和write,不过需要注意一些termios的参数配置。
  1. /*
  2.          * 非标准模式
  3.          * ICANON---代表规范化方式
  4.          * ISIG---代表CTRL+C,否则0x03不能显示
  5.          * ICRNL和IGNCR----会导致0x0D变成0x0A
  6.          * 最后一个设置避免0x13丢失
  7.          */
  8.         options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  9.         options.c_iflag &= ~(ICRNL|IGNCR);
  10.        
  11.         options.c_iflag &= ~(BRKINT | INPCK | ISTRIP | IXON);
复制代码
  1. /*
  2.          * 设置等待时间和最小接收字符
  3.          *
  4.          * VTIME定义要求等待的时间量(取值不能大于cc_t)
  5.          * VMIN定义了要求等待的最小字节数
  6.          * options.c_cc[VTIME] = X;           //设置从获取到1个字节后开始计时的超时时间
  7.          * options.c_cc[VMIN]  = Y;             //设置要求等待的最小字节数
  8.          *
  9.          * 在原始模式下对read()函数的影响:
  10.          * X=0        Y!=0        函数read()只有在读取了Y个字节的数据或者收到一个信号的时候才返回
  11.          * X!=0        Y=0                即使没有数据可以读取,read()函数等待X时间量后返回
  12.          * X!=0        Y!=0        第一个字节数据到时开始,最先满足收到Y个字节或达超时时间X任意一个条件,read()返回
  13.          * X=0        Y=0                即使读取不到任何数据,函数read也会立即返回
  14.          */
  15.         options.c_cc[VTIME] = 0;       
  16.         options.c_cc[VMIN]         = 1;
复制代码
基本上就这些比较重要吧,其他的都很简单,纯c操作。


2、开始分析程序,也学学坛友的好习惯,代码详细贴出来分析,其实我还是不大习惯,以前基本上只是说重点,明白人一看就懂,好比这个帖子,有用的就前面这一点点东西,当然老鸟除外。

1)主程序,算是一个test程序吧,测试串口接收和发送
  1. /**
  2. * brief  main
  3. * note   测试
  4. * param  none
  5. * retval none
  6. */
  7. int main(int argc, char **argv)
  8. {
  9.         char ttyDev[20];
  10.         int  ttysFD = -1;
  11.        
  12.         if (argc == 2) {       
  13.                 strcpy(ttyDev, argv[1]);
  14.         } else {
  15.                 strcpy(ttyDev, "/dev/ttyATH0");
  16.         }
  17.        
  18.         ttyS_dbgLOG("#TTYS\n");
  19.         ttysFD = ttyS_Open(ttyDev);
  20.         if (ttysFD == -1) {
  21.                 ttyS_dbgLOG("ttyDev Open Failure\n");
  22.         }

  23.         if ( ttyS_Init(ttysFD, 115200, 'N', 8, 1, 'N') == FALSE ) {
  24.                 ttyS_dbgLOG("ttyDev Init Failure\n");
  25.         } else {
  26.                 ttyS_dbgLOG("ttyDev Init Success\n");
  27.         }

  28.         ttyS_Send( ttysFD, "ttyDev OK", strlen("ttyDev OK") );
  29.        
  30.         while (1) {
  31.                 bzero(&ttyRX, TTYS_BUF_MAX);
  32.                 ttyS_Receive( ttysFD, ttyRX, TTYS_BUF_MAX );
  33.         }
  34.        
  35.         ttyS_Close(ttysFD);
  36.         return 1;
  37. }
复制代码

基本上按流程走,打开、初始化、初始化好发送字符来测试发送,接收采用超时接收,非阻塞方式(后面会详细介绍)。

2)打印调试函数,采用宏方式,在后面可以直接通过宏关闭。
  1. /**
  2. * brief  ttyS_dbgHEX
  3. * note   ttyS调试打印HEX
  4. * param  None
  5. * retval None
  6. */
  7. void ttyS_dbgHEX(char *txBuf, int Len)
  8. {
  9.         int i;
  10.         if (Len >= 8) {
  11.                 for ( i=0; i<Len/8; i++ ) {
  12.                         ttyS_dbgLOG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
  13.                                         txBuf[8*i+0],
  14.                                         txBuf[8*i+1],
  15.                                         txBuf[8*i+2],
  16.                                         txBuf[8*i+3],
  17.                                         txBuf[8*i+4],
  18.                                         txBuf[8*i+5],
  19.                                         txBuf[8*i+6],
  20.                                         txBuf[8*i+7] );

  21.                 }
  22.         }
  23.         if (Len%8 > 0) {
  24.                 for ( i=(Len/8)*8; i<Len; i++ ) {
  25.                         ttyS_dbgLOG("0x%02x ", txBuf[i]);
  26.                 }
  27.                 ttyS_dbgLOG("\n");
  28.         }
  29. }
复制代码

后面调试会用到这个函数,当然建议大家有良好的调试习惯。

3)ttyS_Open打开相应PORT的串口,使用类似/dev/ttySAC1的名字。
  1. /**
  2. * brief  ttyS_Open
  3. * note   ttyS打开函数
  4. * param  None
  5. * retval None
  6. */
  7. int ttyS_Open(char* Port)
  8. {
  9.         #define ENABLE_TERMINAL_ISATTY                        0
  10.        
  11.         int fd;
  12.         fd = open( Port, O_RDWR | O_NOCTTY | O_NDELAY);

  13.         if ( FALSE == fd ) {
  14.                 ttyS_dbgLOG("Open ttyS failure\n");
  15.                 return(FALSE);
  16.         }

  17.         /* 判断串口的状态是否为阻塞状态
  18.          * 注意非阻塞设置方式:fcntl(fd, F_SETFL, 0)
  19.          * 注意阻塞设置方式:fcntl(fd, F_SETFL, FNDELAY)
  20.          */
  21.         if ( fcntl(fd, F_SETFL, 0) < 0 ) {
  22.                 ttyS_dbgLOG("Fcntl ttyS failure\n");
  23.                 return(FALSE);
  24.         }
  25.        
  26.         /* 测试是否为终端设备 */
  27. #if ENABLE_TERMINAL_ISATTY
  28.         if ( 0 == isatty(STDIN_FILENO) ) {
  29.                 ttyS_dbgLOG("Isatty failure\n");
  30.                 return(FALSE);
  31.         } else {
  32.                 ttyS_dbgLOG("Isatty success\n");
  33.         }
  34. #endif

  35.         ttyS_dbgLOG("Open ttyS fd = %d\n", fd);
  36.         return fd;
  37. }
复制代码

主要涉及到串口打开open中的flag,需要注意O_RDWR | O_NOCTTY | O_NDELAY。
O_RDWR :串口可读写,也就是收发允许。
O_NOCTTY:不想成为“控制终端”控制的程序,不说明这个标志的话,任何输入都会影响你的程序。
O_NDELAY:不关心DCD信号线状态,即其他端口是否运行,不说明这个标志的话,该程序就会在DCD信号线为低电平时停止。

还有一点需要注意的是:可以在打开后使用cntl来改变串口F_SETFL属性,是否阻塞,这个关系到程序结构。


4)ttyS_Close关闭串口函数,传入参数为打开的串口句柄。
  1. /**
  2. * brief  ttyS_Close
  3. * note   ttyS关闭
  4. * param  None
  5. * retval None
  6. */
  7. int ttyS_Close(int fd)
  8. {
  9.         if ( close(fd) == -1 ) {
  10.                 return FALSE;
  11.         } else {
  12.                 return TRUE;
  13.         }
  14. }
复制代码

主要是close的用法,关闭操作。

5)ttyS_Send发送函数,主要是write写操作
  1. /**
  2. * brief  ttyS_Send
  3. * note   ttyS发送
  4. * param  None
  5. * retval None
  6. */
  7. int ttyS_Send(int fd, char *txBuf, int Len)
  8. {
  9.         int realLen = 0;
  10.         realLen = write(fd, txBuf, Len);

  11.         if ( realLen == Len ) {
  12.                 ttyS_dbgLOG("ttyS send %d\n", realLen);
  13.                 ttyS_dbgHEX(txBuf, realLen);
  14.                 return realLen;
  15.         } else {
  16.                 tcflush(fd, TCOFLUSH);
  17.                 return FALSE;
  18.         }
  19. }
复制代码

6)ttyS_Receive接收函数,使用非阻塞方式,select超时接收
  1. /**
  2. * brief  ttyS_Receive
  3. * note   ttyS接收
  4. * param  None
  5. * retval None
  6. */
  7. int ttyS_Receive(int fd, char *rxBuf, int Len)
  8. {
  9.         int realLen;
  10.        
  11.         #define ENABLE_NOBLOCK_READ                                1
  12.        
  13. #if ENABLE_NOBLOCK_READ
  14.         int fsSel;
  15.         fd_set fsRead;
  16.         struct timeval time;

  17.         FD_ZERO(&fsRead);
  18.         FD_SET (fd, &fsRead);

  19.         /* 超时时间25毫秒 */
  20.         time.tv_sec         = 0;
  21.         time.tv_usec         = 25000;
  22.         /* 使用select实现非阻塞的串口接收 */
  23.         fsSel = select( fd+1, &fsRead, NULL, NULL, &time );
  24.        
  25.         if ( FD_ISSET(fd, &fsRead) ) {
  26.                 realLen = read(fd, rxBuf, Len);
  27.                 ttyS_dbgLOG("ttyS receive %d\n", realLen);
  28.                 ttyS_dbgHEX(rxBuf, realLen);
  29.                 return realLen;
  30.         } else {
  31.                 return FALSE;
  32.         }
  33. #else
  34.         realLen = read(fd, rxBuf, Len);
  35.         ttyS_dbgLOG("ttyS receive %d\n", realLen);
  36.         ttyS_dbgHEX(rxBuf, realLen);
  37.         return realLen;
  38. #endif

  39. }
复制代码

需要注意select的使用:
机制中提供一fd_set的数据结构,实际上是一long类型的数组,每一个数组元素都能与一打开的文件句柄(不管是socket句柄,还是其他文件或命名管道或设备句柄)建立联系,建立联系的工作由用户完成,当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪一socket或文件发生了可读或可写事件。

常见用法:
  1. fd_set set;
  2. FD_ZERO(&set);      /*将set清零使集合中不含任何fd*/
  3. FD_SET(fd, &set);    /*将fd加入set集合*/
  4. FD_CLR(fd, &set);    /*将fd从set集合中清除*/
  5. FD_ISSET(fd, &set); /*在调用select()函数后,用FD_ISSET来检测fd在fdset集合中的状态是否变化返回整型,当检测到fd状态发生变化时返回真 */
复制代码


还有其他很多用法,比如select的返回值,这个在socket编程中使用的很多,后面我会分享一个socket 客户端的例子,比较详细的。说明一下,第一个fd+1这个是函数规定的,不要纠结这个,是他的机制。

好了基本上就是这一点点分析了,其实想学学不是靠我们分析的,要自己学会分析问题,不懂的man看看,还不懂在去网上找找别人的分析。其实要说开发,主要靠文档,api reference、doc、install、readme、test等等,都是最好的学习资料。不要局限网络,太杂了,没有太多参考价值。

点评

好吧贴图: 自己写的串口调试助手 [attachimg]164230[/attachimg] 可以从文件加载 [attachimg]164231[/attachimg] 程序运行 [attachimg]164232[/attachimg] 串口通讯 [attachimg]164229[/attachimg]  详情 回复 发表于 2014-8-7 22:49
 
个人签名电工
 
 

回复

2144

帖子

3

TA的资源

五彩晶圆(中级)

4
 
lyzhangxiang 发表于 2014-8-7 22:47
1、linux下串口编程,实现两个文件ttyS.c和ttyS.h文件。说白了也就是read和write,不过需要注意一些termios ...

好吧贴图:
自己写的串口调试助手


可以从文件加载


程序运行


串口通讯




源码编辑vim


点评

Makefile文件 直接用make scp拷贝到板子上运行。板子地址192.168.1.200,开启了sshd服务。  详情 回复 发表于 2014-8-7 22:51
 
个人签名电工
 
 

回复

2144

帖子

3

TA的资源

五彩晶圆(中级)

5
 
lyzhangxiang 发表于 2014-8-7 22:49
好吧贴图:
自己写的串口调试助手


Makefile文件
  1. #general Makefile

  2. #CROSS                                         := mips-openwrt-linux-
  3. CROSS                                        := arm-linux-
  4. CC                                                 := $(CROSS)gcc


  5. objects                                 := ttyS.o main.o
  6. target                                        := ttysUSB

  7. all : $(target)

  8. $(target) : $(objects)
  9.         $(CC) -o $(target) $(objects)

  10. ttyS.o :                        ttyS.h
  11. main.o :                        ttyS.h


  12. scp :
  13.         scp -P 22 ./$(target) root@192.168.1.200:/root

  14. scpdel :
  15.         ssh-keygen -f "/home/camelshoko/.ssh/known_hosts" -R [192.168.1.200]:22
  16.        
  17. .PHONY : clean

  18. clean :
  19.         -rm -rf $(target) $(objects)
复制代码


直接用make scp拷贝到板子上运行。板子地址192.168.1.200,开启了sshd服务。

 
个人签名电工
 
 

回复

43

帖子

0

TA的资源

一粒金砂(中级)

6
 
我想问问楼主ubuntu什么版本的。 14?

点评

14的,有新的我就装 哈哈  详情 回复 发表于 2014-8-7 22:53
 
 
 

回复

2144

帖子

3

TA的资源

五彩晶圆(中级)

7
 
yuanlai2010 发表于 2014-8-7 22:46
先把文字部分在word中编辑好…然后复制进入……再添加图片和代码什么的

谢谢你,没办法,只恢复了一部分文字,草率编辑下发帖睡觉,没兴趣了。。。。
 
个人签名电工
 
 

回复

2144

帖子

3

TA的资源

五彩晶圆(中级)

8
 
kctime 发表于 2014-8-7 22:51
我想问问楼主ubuntu什么版本的。 14?

14的,有新的我就装 哈哈

点评

什么显卡,,,我装14,,三分钟显卡煮鸡蛋了。。现在跳fedora了  详情 回复 发表于 2014-8-7 22:54
 
个人签名电工
 
 

回复

43

帖子

0

TA的资源

一粒金砂(中级)

9
 
lyzhangxiang 发表于 2014-8-7 22:53
14的,有新的我就装 哈哈

什么显卡,,,我装14,,三分钟显卡煮鸡蛋了。。现在跳fedora了

点评

我dell的电脑 inspiration系列的,显卡没在意,好像是a卡。这么热估计能设置好吧,driver和bios  详情 回复 发表于 2014-8-8 07:35
 
 
 

回复

2144

帖子

3

TA的资源

五彩晶圆(中级)

10
 
kctime 发表于 2014-8-7 22:54
什么显卡,,,我装14,,三分钟显卡煮鸡蛋了。。现在跳fedora了

我dell的电脑 inspiration系列的,显卡没在意,好像是a卡。这么热估计能设置好吧,driver和bios


 
个人签名电工
 
 

回复

554

帖子

0

TA的资源

版主

11
 
看来贴子编译器影响楼上的心情了。。。
 
个人签名My dreams will go on...
http://www.jyxtec.com
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

12
 
楼主能共享下源码吗
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表