Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1330533
  • 博文数量: 124
  • 博客积分: 5772
  • 博客等级: 大校
  • 技术积分: 1647
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-27 10:39
文章分类

全部博文(124)

文章存档

2020年(1)

2019年(1)

2018年(5)

2017年(2)

2016年(17)

2015年(3)

2014年(7)

2013年(11)

2012年(13)

2011年(30)

2010年(34)

分类: LINUX

2016-12-07 11:23:00

开发环境:

开发环境如下图所示:



开发PC:开发PC上运行超级终端,编写、编译串口程序

Tiny6410:运行串口程序,其中/dev/ttySAC0通过串口线与开发PC相连接,/dev/ttySAC3通过串口线与测试PC相连接

测试PC:测试PC上运行串口调试工具,进行串口数据的收发

程序功能描述:Tiny6410通过/dev/ttySAC3串口与测试PC进行串口数据的收发。这个程序是在友善之臂提供的串口应用程序的基础上精简来的。原来的程序看起来有些复杂,初学者读起来有一定难度。经过精简之后,只保留了串口收发数据的关键部分。

源代码

  1. /*==========================================================================
  2. *Name: uart_S3C6410.c
  3. *Desc: 友善之臂开发板串口收发程序,根据友善之臂提供的串口程序精简而来
  4. * 在超级终端输入要发送的字符,通过串口发送;串口接收的数据由超级
  5. * 终端显示出来。交叉编译后,下载到开发板,执行./uart_S3C6410
  6. *Parameter:
  7. *Return:
  8. *Author: yoyoba(stuyou@126.com)
  9. *Date: 2016-11-03
  10. *Modify: 2016-12-07
  11. *=========================================================================*/

  12. # include <stdio.h>
  13. # include <stdlib.h>
  14. # include <termio.h>
  15. # include <unistd.h>
  16. # include <fcntl.h>
  17. # include <getopt.h>
  18. # include <time.h>
  19. # include <errno.h>
  20. # include <string.h>

  21. //错误消息提示函数
  22. static void Error(const char *Msg)
  23. {
  24.     fprintf (stderr, "%s\n", Msg);
  25.     fprintf (stderr, "strerror() is %s\n", strerror(errno));
  26.     exit(1);
  27. }

  28. //警告消息提示函数
  29. static void Warning(const char *Msg)
  30. {
  31.     fprintf (stderr, "Warning: %s\n", Msg);
  32. }

  33. //使用select监视FD是否可写
  34. static inline void WaitFdWriteable(int Fd)
  35. {
  36.     fd_set WriteSetFD;
  37.     FD_ZERO(&WriteSetFD);
  38.     FD_SET(Fd, &WriteSetFD);
  39.     if (select(Fd + 1, NULL, &WriteSetFD, NULL, NULL) < 0) {
  40.      Error(strerror(errno));
  41.     }
  42. }

  43. int main()
  44. {    
  45.     int UART_fd, tty_fd;
  46.     struct termios TtyAttr;
  47.     struct termios BackupTtyAttr;
  48.         
  49.     UART_fd = open("/dev/ttySAC3", O_RDWR, 0);//打开ttySAC3串口
  50.     if (UART_fd < 0)
  51.          Error("Unable to open device");
  52.     if (fcntl(UART_fd, F_SETFL, O_NONBLOCK) < 0)//设置串口为非阻塞
  53.      Error("Unable set to NONBLOCK mode");
  54.          
  55.     memset(&TtyAttr, 0, sizeof(struct termios));//清空ttyattr
  56.     //配置串口:
  57.     TtyAttr.c_iflag = IGNPAR; //忽略校验
  58.     TtyAttr.c_cflag = B115200 | HUPCL | CS8 | CREAD | CLOCAL;//115200波特率,数据位8,启用接收
  59.     TtyAttr.c_cc[VMIN] = 1; //最小可读取字符数
  60.     if (tcsetattr(UART_fd, TCSANOW, &TtyAttr) < 0)//配置串口
  61.         Warning("Unable to set comm port");
  62.         
  63.     tty_fd = open("/dev/tty", O_RDWR | O_NDELAY, 0); //打开终端/dev/tty,当前shell终端
  64.     if (tty_fd < 0)
  65.         Error("Unable to open tty");
  66.     TtyAttr.c_cflag = B115200 | HUPCL | CS8 | CREAD | CLOCAL;//和开发板超级终端属性的配置一致,否则会有问题
  67.     if (tcgetattr(tty_fd, &BackupTtyAttr) < 0)//把终端属性保存在BackupTtyAttr,程序退出时恢复终端使用
  68.         Error("Unable to get tty");
  69.     if (tcsetattr(tty_fd, TCSANOW, &TtyAttr) < 0)//设置终端属性
  70.         Error("Unable to set tty");

  71.      //启动循环,串口接收和发送数据
  72.     while(1){
  73.         unsigned char buf = 0;
  74.             fd_set ReadSetFD;

  75.         //select监控串口和终端是否可读
  76.         FD_ZERO(&ReadSetFD);
  77.         FD_SET(UART_fd, &ReadSetFD);
  78.         FD_SET( tty_fd, &ReadSetFD);
  79.         #define max(x,y) ( ((x) >= (y)) ? (x) : (y) )
  80.         if (select(max(UART_fd, tty_fd) + 1, &ReadSetFD, NULL, NULL, NULL) < 0) {
  81.             Error(strerror(errno));
  82.         }
  83.         #undef max

  84.         //如果串口可读
  85.         if (FD_ISSET(UART_fd, &ReadSetFD)){
  86.             while (read(UART_fd, &buf, 1) == 1) {
  87.                 WaitFdWriteable(tty_fd);//等待终端可写
  88.                 if (write(tty_fd, &buf, 1) < 0) {//把从串口读取的字符输出到终端显示
  89.                      Error(strerror(errno));
  90.                 }
  91.             }
  92.         }

  93.         //如果终端可读,在终端中输入发送的数据
  94.         if (FD_ISSET(tty_fd, &ReadSetFD)) {
  95.             while (read(tty_fd, &buf, 1) == 1) {//读取终端中输入的字符
  96.                 static int EscKeyCount = 0;//统计按下ESC键的次数,如果连续按下三次ESC键,则退出程序
  97.                 WaitFdWriteable(UART_fd);//如果串口可写,就通过串口发送
  98.                 if (write(UART_fd, &buf, 1) < 0) {
  99.                      Error(strerror(errno));
  100.                 }
  101.         if(buf != '\x1b')//如果输入的不是ESC键,则在超级终端显示输入的字符
  102.             fwrite((char*)&buf, 1, 1, stderr);//如果不执行这句,超级终端看不到输入的字符
  103.     
  104.          if (buf == '\x1b') {
  105.                             EscKeyCount ++;
  106.                             if (EscKeyCount >= 3)
  107.                             goto ExitLabel;
  108.                    // 跳出到退出label
  109.                     } else
  110.                         EscKeyCount = 0;
  111.             }
  112.           }
  113.     }
  114.     ExitLabel:
  115.         if (tcsetattr(tty_fd, TCSANOW, &BackupTtyAttr) < 0)//退出程序之前,恢复超级终端的配置
  116.             Error("Unable to set tty");

  117.         return 0;
  118. }

编译

在开发PC上对串口程序进行交叉编译:arm-linux-gcc -o uart_S3C6410 uart_S3C6410.c

运行测试

把开发PC上编译好的uart_S3C6410下载到开发板,并添加执行权限:chmod +x uart_S3C6410,

执行:./uart_S3C6410

1.接收测试:在测试PC的串口调试工具中,发送数据,在开发PC的超级终端中可以看到接收的数据;

2.发送测试:在开发PC的超级终端中输入要发送的数据,在测试PC的串口调试工具中看到接收的数据

3.退出程序:在开发PC超级终端中连续输入三个“ESC”键,则退出程序。



阅读(1246) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~