linux下UART的应用层编程及测试小程序

来源:互联网 发布:fliqlo mac 编辑:程序博客网 时间:2024/06/16 02:57
  1. //串口相关的头文件    
  2. #include<stdio.h>      /*标准输入输出定义*/    
  3. #include<stdlib.h>     /*标准函数库定义*/    
  4. #include<unistd.h>     /*Unix 标准函数定义*/    
  5. #include<sys/types.h>     
  6. #include<sys/stat.h>       
  7. #include<fcntl.h>      /*文件控制定义*/    
  8. #include<termios.h>    /*PPSIX 终端控制定义*/    
  9. #include<errno.h>      /*错误号定义*/    
  10. #include<string.h>    
  11.      
  12.      
  13. //宏定义    
  14. #define FALSE  -1    
  15. #define TRUE   0    
  16.      
  17. /*******************************************************************  
  18. * 名称:                  UART0_Open  
  19. * 功能:                打开串口并返回串口设备文件描述  
  20. * 入口参数:        fd    :文件描述符     port :串口号(ttyS0,ttyS1,ttyS2)  
  21. * 出口参数:        正确返回为1,错误返回为0  
  22. *******************************************************************/    
  23. int UART0_Open(int fd,char* port)    
  24. {    
  25.        
  26.     fd = open( port, O_RDWR|O_NOCTTY|O_NDELAY);    
  27.     if (FALSE == fd)    
  28.     {    
  29.         perror("Can't Open Serial Port");    
  30.         return(FALSE);    
  31.     }    
  32.     //恢复串口为阻塞状态                                   
  33.     if(fcntl(fd, F_SETFL, 0) < 0)    
  34.     {    
  35.         printf("fcntl failed!\n");    
  36.         return(FALSE);    
  37.     }         
  38.     else    
  39.     {    
  40.         printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));    
  41.     }    
  42.     //测试是否为终端设备        
  43.     if(0 == isatty(STDIN_FILENO))    
  44.     {    
  45.         printf("standard input is not a terminal device\n");    
  46.         return(FALSE);    
  47.     }    
  48.     else    
  49.     {    
  50.         printf("isatty success!\n");    
  51.     }                  
  52.     printf("fd->open=%d\n",fd);    
  53.     return fd;    
  54. }    
  55. /*******************************************************************  
  56. * 名称:                UART0_Close  
  57. * 功能:                关闭串口并返回串口设备文件描述  
  58. * 入口参数:        fd    :文件描述符     port :串口号(ttyS0,ttyS1,ttyS2)  
  59. * 出口参数:        void  
  60. *******************************************************************/    
  61.      
  62. void UART0_Close(int fd)    
  63. {    
  64.     close(fd);    
  65. }    
  66.      
  67. /*******************************************************************  
  68. * 名称:                UART0_Set  
  69. * 功能:                设置串口数据位,停止位和效验位  
  70. * 入口参数:        fd        串口文件描述符  
  71. *                              speed     串口速度  
  72. *                              flow_ctrl   数据流控制  
  73. *                           databits   数据位   取值为 7 或者8  
  74. *                           stopbits   停止位   取值为 1 或者2  
  75. *                           parity     效验类型 取值为N,E,O,,S  
  76. *出口参数:          正确返回为1,错误返回为0  
  77. *******************************************************************/    
  78. int UART0_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity)    
  79. {    
  80.        
  81.     int   i;    
  82.     int   status;    
  83.     int   speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300};    
  84.     int   name_arr[] = {115200,  19200,  9600,  4800,  2400,  1200,  300};    
  85.              
  86.     struct termios options;    
  87.        
  88.     /*tcgetattr(fd,&options)得到与fd指向对象的相关参数,并将它们保存于options,该函数还可以测试配置是否正确,该串口是否可用等。若调用成功,函数返回值为0,若调用失败,函数返回值为1.  
  89.     */    
  90.     if( tcgetattr( fd,&options)  !=  0)    
  91.     {    
  92.         perror("SetupSerial 1");        
  93.         return(FALSE);     
  94.     }    
  95.       
  96.     //设置串口输入波特率和输出波特率    
  97.     for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)    
  98.     {    
  99.         if  (speed == name_arr[i])    
  100.         {                 
  101.             cfsetispeed(&options, speed_arr[i]);     
  102.             cfsetospeed(&options, speed_arr[i]);      
  103.         }    
  104.     }         
  105.        
  106.     //修改控制模式,保证程序不会占用串口    
  107.     options.c_cflag |= CLOCAL;    
  108.     //修改控制模式,使得能够从串口中读取输入数据    
  109.     options.c_cflag |= CREAD;    
  110.       
  111.     //设置数据流控制    
  112.     switch(flow_ctrl)    
  113.     {    
  114.           
  115.         case 0 ://不使用流控制    
  116.               options.c_cflag &= ~CRTSCTS;    
  117.               break;       
  118.           
  119.         case 1 ://使用硬件流控制    
  120.               options.c_cflag |= CRTSCTS;    
  121.               break;    
  122.         case 2 ://使用软件流控制    
  123.               options.c_cflag |= IXON | IXOFF | IXANY;    
  124.               break;    
  125.     }    
  126.     //设置数据位    
  127.     //屏蔽其他标志位    
  128.     options.c_cflag &= ~CSIZE;    
  129.     switch (databits)    
  130.     {      
  131.         case 5    :    
  132.                      options.c_cflag |= CS5;    
  133.                      break;    
  134.         case 6    :    
  135.                      options.c_cflag |= CS6;    
  136.                      break;    
  137.         case 7    :        
  138.                  options.c_cflag |= CS7;    
  139.                  break;    
  140.         case 8:        
  141.                  options.c_cflag |= CS8;    
  142.                  break;      
  143.         default:       
  144.                  fprintf(stderr,"Unsupported data size\n");    
  145.                  return (FALSE);     
  146.     }    
  147.     //设置校验位    
  148.     switch (parity)    
  149.     {      
  150.         case 'n':    
  151.         case 'N'//无奇偶校验位。    
  152.                  options.c_cflag &= ~PARENB;     
  153.                  options.c_iflag &= ~INPCK;        
  154.                  break;     
  155.         case 'o':      
  156.         case 'O'://设置为奇校验        
  157.                  options.c_cflag |= (PARODD | PARENB);     
  158.                  options.c_iflag |= INPCK;                 
  159.                  break;     
  160.         case 'e':     
  161.         case 'E'://设置为偶校验      
  162.                  options.c_cflag |= PARENB;           
  163.                  options.c_cflag &= ~PARODD;           
  164.                  options.c_iflag |= INPCK;          
  165.                  break;    
  166.         case 's':    
  167.         case 'S'//设置为空格     
  168.                  options.c_cflag &= ~PARENB;    
  169.                  options.c_cflag &= ~CSTOPB;    
  170.                  break;     
  171.         default:      
  172.                  fprintf(stderr,"Unsupported parity\n");        
  173.                  return (FALSE);     
  174.     }     
  175.     // 设置停止位     
  176.     switch (stopbits)    
  177.     {      
  178.         case 1:       
  179.                  options.c_cflag &= ~CSTOPB; break;     
  180.         case 2:       
  181.                  options.c_cflag |= CSTOPB; break;    
  182.         default:       
  183.                        fprintf(stderr,"Unsupported stop bits\n");     
  184.                        return (FALSE);    
  185.     }    
  186.        
  187.     //修改输出模式,原始数据输出    
  188.     options.c_oflag &= ~OPOST;    
  189.       
  190.     options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);    
  191.     //options.c_lflag &= ~(ISIG | ICANON);    
  192.        
  193.     //设置等待时间和最小接收字符    
  194.     options.c_cc[VTIME] = 1; /* 读取一个字符等待1*(1/10)s */      
  195.     options.c_cc[VMIN] = 1; /* 读取字符的最少个数为1 */    
  196.        
  197.     //如果发生数据溢出,接收数据,但是不再读取 刷新收到的数据但是不读    
  198.     tcflush(fd,TCIFLUSH);    
  199.        
  200.     //激活配置 (将修改后的termios数据设置到串口中)    
  201.     if (tcsetattr(fd,TCSANOW,&options) != 0)      
  202.     {    
  203.         perror("com set error!\n");      
  204.         return (FALSE);     
  205.     }    
  206.     return (TRUE);     
  207. }    
  208. /*******************************************************************  
  209. * 名称:                UART0_Init()  
  210. * 功能:                串口初始化  
  211. * 入口参数:        fd       :  文件描述符     
  212. *               speed  :  串口速度  
  213. *                              flow_ctrl  数据流控制  
  214. *               databits   数据位   取值为 7 或者8  
  215. *                           stopbits   停止位   取值为 1 或者2  
  216. *                           parity     效验类型 取值为N,E,O,,S  
  217. *                        
  218. * 出口参数:        正确返回为1,错误返回为0  
  219. *******************************************************************/    
  220. int UART0_Init(int fd, int speed,int flow_ctrl,int databits,int stopbits,int parity)    
  221. {    
  222.     int err;    
  223.     //设置串口数据帧格式    
  224.     if (UART0_Set(fd,19200,0,8,1,'N') == FALSE)    
  225.     {                                                             
  226.         return FALSE;    
  227.     }    
  228.     else    
  229.     {    
  230.         return  TRUE;    
  231.     }    
  232. }    
  233.      
  234. /*******************************************************************  
  235. * 名称:                  UART0_Recv  
  236. * 功能:                接收串口数据  
  237. * 入口参数:        fd                  :文件描述符      
  238. *                              rcv_buf     :接收串口中数据存入rcv_buf缓冲区中  
  239. *                              data_len    :一帧数据的长度  
  240. * 出口参数:        正确返回为1,错误返回为0  
  241. *******************************************************************/    
  242. int UART0_Recv(int fd, char *rcv_buf,int data_len)    
  243. {    
  244.     int len,fs_sel;    
  245.     fd_set fs_read;    
  246.        
  247.     struct timeval time;    
  248.        
  249.     FD_ZERO(&fs_read);    
  250.     FD_SET(fd,&fs_read);    
  251.        
  252.     time.tv_sec = 10;    
  253.     time.tv_usec = 0;    
  254.        
  255.     //使用select实现串口的多路通信    
  256.     fs_sel = select(fd+1,&fs_read,NULL,NULL,&time);    
  257.     printf("fs_sel = %d\n",fs_sel);    
  258.     if(fs_sel)    
  259.     {    
  260.         len = read(fd,rcv_buf,data_len);    
  261.         printf("I am right!(version1.2) len = %d fs_sel = %d\n",len,fs_sel);    
  262.         return len;    
  263.     }    
  264.     else    
  265.     {    
  266.         printf("Sorry,I am wrong!");    
  267.         return FALSE;    
  268.     }         
  269. }    
  270. /********************************************************************  
  271. * 名称:                  UART0_Send  
  272. * 功能:                发送数据  
  273. * 入口参数:        fd                  :文件描述符      
  274. *                              send_buf    :存放串口发送数据  
  275. *                              data_len    :一帧数据的个数  
  276. * 出口参数:        正确返回为1,错误返回为0  
  277. *******************************************************************/    
  278. int UART0_Send(int fd, char *send_buf,int data_len)    
  279. {    
  280.     int len = 0;    
  281.        
  282.     len = write(fd,send_buf,data_len);    
  283.     if (len == data_len )    
  284.     {    
  285.         printf("send data is %s\n",send_buf);  
  286.         return len;    
  287.     }         
  288.     else       
  289.     {    
  290.                    
  291.         tcflush(fd,TCOFLUSH);    
  292.         return FALSE;    
  293.     }    
  294.        
  295. }    
  296.      
  297.      
  298. int main(int argc, char **argv)    
  299. {    
  300.     int fd;                            //文件描述符    
  301.     int err;                           //返回调用函数的状态    
  302.     int len;                            
  303.     int i;    
  304.     char rcv_buf[100];           
  305.     //char send_buf[20]="tiger john";    
  306.     char send_buf[20]="tiger john";  
  307.     if(argc != 3)    
  308.     {    
  309.         printf("Usage: %s /dev/ttySn 0(send data)/1 (receive data) \n",argv[0]);    
  310.         return FALSE;    
  311.     }    
  312.     fd = UART0_Open(fd,argv[1]); //打开串口,返回文件描述符    
  313.     do  
  314.     {    
  315.         err = UART0_Init(fd,19200,0,8,1,'N');    
  316.         printf("Set Port Exactly!\n");    
  317.     }while(FALSE == err || FALSE == fd);    
  318.        
  319.     if(0 == strcmp(argv[2],"0"))    
  320.     {    
  321.         for(i = 0;i < 10;i++)    
  322.         {    
  323.             len = UART0_Send(fd,send_buf,10);    
  324.             if(len > 0)    
  325.                 printf(" %d time send %d data successful\n",i,len);    
  326.             else    
  327.                 printf("send data failed!\n");    
  328.                               
  329.             sleep(2);    
  330.         }    
  331.         UART0_Close(fd);                 
  332.     }    
  333.     else    
  334.     {                                          
  335.         while (1) //循环读取数据    
  336.         {      
  337.             len = UART0_Recv(fd, rcv_buf,99);    
  338.             if(len > 0)    
  339.             {    
  340.                 rcv_buf[len] = '\0';    
  341.                 printf("receive data is %s\n",rcv_buf);    
  342.                 printf("len = %d\n",len);    
  343.             }    
  344.             else    
  345.             {    
  346.                 printf("cannot receive data\n");    
  347.             }    
  348.             sleep(2);    
  349.         }                
  350.         UART0_Close(fd);     
  351.     }    
  352. }    
原创粉丝点击