C语言串口驱动程序

驱动层屏蔽了硬件细节,个人猜测,几乎所有移植好的系统的串口,都可以用一样的代码来操作,至少2440和树莓派是通用的。

分享代码如下:

[cpp] view plaincopy
  1. #include <sys/types.h>  
  2. #include <sys/stat.h>  
  3. #include <fcntl.h>  
  4. #include <termios.h>  
  5. #include <errno.h>  
  6. #include <ctype.h>  
  7. #include <stdio.h>  
  8. #include <stdlib.h>  
  9. #include <string.h>  
  10. #include <time.h>  
  11. #include <unistd.h>  
  12. #include"pthread.h"  
  13. #include "serial.h"  
  14.   
  15.   
  16. struct serial_config serialread;  
  17.   
  18. static int serial_fd;  
  19.   
  20. int speed_arr[] = {B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300,  
  21.            B38400, B19200, B9600, B4800, B2400, B1200, B300};  
  22.   
  23. int name_arr[] = {230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300,  
  24.           38400, 19200, 9600, 4800, 2400, 1200, 300};  
  25.   
  26. //-----------------------------------------------  
  27. //打印配置文件serial.cfg的内容  
  28. //-----------------------------------------------  
  29. void print_serialread()  
  30. {  
  31.     printf("serialread.dev is %s\n",serialread.serial_dev);  
  32.     printf("serialread.speed is %d\n",serialread.serial_speed);  
  33.     printf("serialread.databits is %d\n",serialread.databits);  
  34.     printf("serialread.stopbits is %d\n",serialread.stopbits);  
  35.     printf("serialread.parity is %c\n",serialread.parity);  
  36. }  
  37.   
  38. //-----------------------------------------------  
  39. //读取serial.cfg文件并进行配置  
  40. //-----------------------------------------------  
  41. void readserialcfg()  
  42. {  
  43.     FILE *serial_fp;  
  44.     char j[10];  
  45.       
  46.     printf("readserailcfg\n");  
  47.   
  48.     serial_fp = fopen("./serial.cfg","r");  
  49.     if(NULL == serial_fp)  
  50.     {  
  51.         printf("can't open serial.cfg");  
  52.     }  
  53.     else  
  54.     {  
  55.         fscanf(serial_fp, "DEV=%s\n", serialread.serial_dev);  
  56.   
  57.         fscanf(serial_fp, "SPEED=%s\n", j);  
  58.         serialread.serial_speed = atoi(j);  
  59.   
  60.         fscanf(serial_fp, "DATABITS=%s\n", j);  
  61.         serialread.databits = atoi(j);  
  62.   
  63.         fscanf(serial_fp, "STOPBITS=%s\n", j);  
  64.         serialread.stopbits = atoi(j);  
  65.   
  66.         fscanf(serial_fp, "PARITY=%s\n", j);  
  67.         serialread.parity = j[0];  
  68.     }  
  69.   
  70.     fclose(serial_fp);  
  71. }  
  72.   
  73. //-----------------------------------------------  
  74. //设置波特率  
  75. //-----------------------------------------------  
  76. void set_speed(int fd)  
  77. {  
  78.     int i;  
  79.     int status;  
  80.     struct termios Opt;  
  81.     struct termios oldOpt;  
  82.     tcgetattr(fd, &oldOpt);  
  83. //  printf("serialread.speed is %d\n",serialread.serial_speed);  
  84.     for( i = 0; i < sizeof(speed_arr)/sizeof(int); i++)  
  85.     {  
  86.         if(serialread.serial_speed == name_arr[i])  
  87.         {  
  88.             tcflush(fd, TCIOFLUSH);  
  89.             cfsetispeed(&Opt, speed_arr[i]);  
  90.             cfsetospeed(&Opt, speed_arr[i]);  
  91.             status = tcsetattr(fd, TCSANOW, &Opt);  
  92.             if(status != 0)  
  93.             {  
  94.                 perror("tcsetattr fd1");  
  95.                 return;  
  96.             }  
  97.             tcflush(fd, TCIOFLUSH);  
  98.         }  
  99.     }  
  100. }  
  101.   
  102.   
  103. //-----------------------------------------------  
  104. //设置其他参数  
  105. //-----------------------------------------------  
  106. int  (int fd)  
  107. {  
  108.     struct termios options;  
  109.     struct termios oldoptions;  
  110.     if(tcgetattr(fd, &oldoptions) != 0)  
  111.     {  
  112.         perror("SetupSerial 1");  
  113.         return(FALSE);  
  114.     }  
  115.   
  116.     options.c_cflag |= (CLOCAL|CREAD);  
  117.     options.c_cflag &=~CSIZE;  
  118. //  printf("serialread.databits is %d\n",serialread.databits);  
  119.     switch(serialread.databits)  
  120.     {  
  121.         case 7:  
  122.             options.c_cflag |= CS7;  
  123.             break;  
  124.         case 8:  
  125.             options.c_cflag |= CS8;  
  126.             break;  
  127.         default:  
  128.             options.c_cflag |= CS8;  
  129.             fprintf(stderr, "Unsupported data size\n");  
  130.             return(FALSE);  
  131.     }  
  132. //  printf("serialread.parity is %c\n",serialread.parity);  
  133.     switch(serialread.parity)  
  134.     {  
  135.         case 'n':  
  136.         case 'N':  
  137.             options.c_cflag &= ~PARENB;  
  138.             options.c_iflag &= ~INPCK;  
  139.             break;  
  140.         case 'o':  
  141.         case 'O':  
  142.             options.c_cflag |= (PARODD | PARENB);  
  143.             options.c_iflag |= INPCK;  
  144.             break;  
  145.         case 'e':  
  146.         case 'E':  
  147.             options.c_cflag |= PARENB;  
  148.             options.c_cflag &= ~PARODD;  
  149.             options.c_iflag |= INPCK;  
  150.             break;  
  151.         default:  
  152.             options.c_cflag &= ~PARENB;  
  153.             options.c_iflag &= ~INPCK;  
  154.             fprintf(stderr, "Unsupported parity\n");  
  155.             return(FALSE);  
  156.     }  
  157. //  printf("serialread.stopbits is %d\n",serialread.stopbits);  
  158.     switch(serialread.stopbits)  
  159.     {  
  160.         case 1:  
  161.             options.c_cflag &= ~CSTOPB;  
  162.             break;  
  163.         case 2:  
  164.             options.c_cflag |= CSTOPB;  
  165.             break;  
  166.         default:  
  167.             options.c_cflag &= ~CSTOPB;  
  168.             fprintf(stderr, "Unsupported stop bits\n");  
  169.             return(FALSE);  
  170.     }  
  171.     if(serialread.parity != 'n')  
  172.         options.c_iflag |= INPCK;  
  173.     options.c_cc[VTIME] = 0;    //150;          //15 seconds  
  174.     options.c_cc[VMIN] = 0;  
  175. #if 1  
  176.     options.c_iflag |= IGNPAR|ICRNL;  
  177.     options.c_oflag |= OPOST;   
  178.     options.c_iflag &= ~(IXON|IXOFF|IXANY);                       
  179. #endif  
  180.     tcflush(fd, TCIFLUSH);  
  181.     if(tcsetattr(fd, TCSANOW, &options) != 0)  
  182.     {  
  183.         perror("SetupSerial 3");  
  184.         return(FALSE);  
  185.     }  
  186.     return(TRUE);  
  187. }  
  188.   
  189. //-----------------------------------------------  
  190. //打开串口设备  
  191. //-----------------------------------------------  
  192. int OpenDev(char *Dev)  
  193. {  
  194.     int fd = open(Dev, O_RDWR, 0);  
  195.     if(-1 == fd)  
  196.     {  
  197.         perror("Can't Open Serial Port");  
  198.         return -1;  
  199.     }  
  200.     else  
  201.         return fd;  
  202. }  
  203.   
  204. //--------------------------------------------------  
  205. //串口初始化  
  206. //--------------------------------------------------  
  207. void serial_init()  
  208. {  
  209.     char *Dev;  
  210.   
  211.     int i;  
  212.   
  213.     readserialcfg();  
  214.     //print_serialread();  
  215.     printf("init serial\n");  
  216.   
  217.     Dev = serialread.serial_dev;  
  218.     //打开串口设备  
  219.     serial_fd = OpenDev(Dev);  
  220.   
  221.     if(serial_fd > 0)  
  222.         set_speed(serial_fd);       //设置波特率  
  223.     else  
  224.     {  
  225.         printf("Can't Open Serial Port!\n");  
  226.         exit(0);  
  227.     }  
  228.     //恢复串口未阻塞状态  
  229.     if (fcntl(serial_fd, F_SETFL, O_NONBLOCK) < 0)  
  230.     {  
  231.         printf("fcntl failed!\n");  
  232.         exit(0);  
  233.     }  
  234.     //检查是否是终端设备  
  235. #if 0   //如果屏蔽下面这段代码,在串口输入时不会有回显的情况,调用下面这段代码时会出现回显现象。  
  236.     if(isatty(STDIN_FILENO)==0)  
  237.     {  
  238.         printf("standard input is not a terminal device\n");  
  239.     }  
  240.     else  
  241.         printf("isatty success!\n");  
  242. #endif  
  243.     //设置串口参数  
  244.     if(set_Parity(serial_fd) == FALSE)  
  245.     {  
  246.         printf("Set parity Error\n");  
  247.         exit(1);  
  248.     }  
  249.   
  250. }  
  251.   
  252. int serial_write(char* cmd, int count)  
  253. {  
  254.     printf("serial write for %d bytes\n",count);  
  255.     return write(serial_fd,cmd,count);  
  256. }  
  257.   
  258. void serial_close()  
  259. {  
  260.     printf("close serial\n");  
  261.     close(serial_fd);  
  262. }  
  263.   
  264. /* 
  265. void serial_rw() 
  266. { 
  267.     int i; 
  268.     char buff[512]; 
  269.      
  270.     int nread,nwrite; 
  271.  
  272.      char buff2[] = "hello!\n"; 
  273.     nwrite = write(serial_fd,buff2,sizeof(buff2)); 
  274.     printf("nwrite=%d\n",nwrite); 
  275.     while(1) 
  276.     { 
  277.         if((nread = read(serial_fd,buff,512))>0) 
  278.         {  
  279.             buff[nread] = '\0'; 
  280. #if 1   //调用这段代码可以实现回显,如果配合上面的回显,就会出现回显两次的情况。 
  281.             write(serial_fd,buff,nread); 
  282. #endif 
  283.             printf("recv:%d\n",nread); 
  284. #if 1 
  285.             for(i=0;i<nread;i++) 
  286.             { 
  287.                 printf("%c",buff[i]); 
  288.             } 
  289.             printf("\n"); 
  290. #else 
  291.             printf("%s",buff); 
  292.             printf("\n"); 
  293. #endif 
  294.         } 
  295.     } 
  296.   
  297.  
  298.  
  299. } 
  300. */  
  301. /* 
  302. int main(int argc, char **argv) 
  303. { 
  304.     serial_init(); 
  305.  
  306.     char cmd[]={0xfc,0x01,0x01,0x02,0x01,0x00,0x03,0x01,0xcf}; 
  307.     write(serial_fd,cmd,sizeof(cmd)); 
  308.     close(serial_fd); 
  309.      
  310.     return 0; 
  311. //  close(serialread.serial_dev); 
  312. //  serial_test(telnum, telmoney); 
  313. } 
  314. */  

当然,还需要对应的头文件:

[cpp] view plaincopy
  1. #define FALSE       0  
  2. #define TRUE        1  
  3.   
  4. #define WORDLEN 32  
  5.   
  6. struct serial_config  
  7. {  
  8.     unsigned char serial_dev[WORDLEN];  
  9.     unsigned int serial_speed;  
  10.     unsigned char databits;  
  11.     unsigned char stopbits;  
  12.     unsigned char parity;  
  13. };  
  14.   
  15. void serial_init();  
  16. int serial_write(char* cmd, int count);  
  17. void serial_close();  

以及分离出来的配置文件:

[cpp] view plaincopy
  1. DEV=/dev/ttyAMA0  
  2. SPEED=9600  
  3. DATABITS=8  
  4. STOPBITS=1  
  5. PARITY=N  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401800.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows下的Qt Creator的安装

采用Qt和Qt creator分别下载和安装的方式&#xff1a;&#xff08;需要手动设置关联Qt和Qt Creator&#xff09; 一、软件下载 从http://qt-project.org/downloads分别下载Qt和Qt Creator&#xff1a; Qt使用4.7.2版本&#xff1a;qt-win-opensource-4.7.2-mingw.exe Qt Creato…

进程 、进程组、会话、控制终端之间的关系

一个进程组可以包含多个进程 进程组中的这些进程之间不是孤立的&#xff0c;他们彼此之间或者存在者父子、兄弟关系&#xff0c;或者在功能有相近的联系。 那linux为什么要有进程组呢&#xff1f;其实提供进程组就是方便管理这些进程。假设要完成一个任务&#xff0c;需要同时并…

matlab保存数据

一&#xff1a;存txt文件&#xff0c;用dlmwrite()dlmwrite 将一个矩阵写到由分隔符分割的文件中。 在保存整数到文件时使用save存为ascii文件时&#xff0c;常常是文件里都是实型格式的数据&#xff08;有小数点&#xff0c;和后面很多的0&#xff0c;看着很不方便&#xff09…

linux下串口的阻塞和非阻塞操作

有两个可以进行控制串口阻塞性&#xff08;同时控制read和write&#xff09;&#xff1a;一个是在打开串口的时候&#xff0c;open函数是否带O_NDELAY&#xff1b;第二个是可以在打开串口之后通过fcntl()函数进行控制。 阻塞的定义&#xff1a; 对于read&#xff0c;block指当串…

串口初始化配置

在基于AT91的嵌入式linux中接收串口数据时&#xff0c;发现对于接收的数据经常出现接收不完整的现象。一帧的数据可能会被当做两帧接收&#xff0c;导致对于一帧数据接收出现问题。虽然这种情况在一般情况下&#xff0c;并不是经常出现&#xff0c;但是只要数据量稍微大一些&am…

Angularjs 通过asp.net web api认证登录

Angularjs 通过asp.net web api认证登录 Angularjs利用asp.net mvc提供的asp.net identity&#xff0c;membership实现居于数据库的用户名/密码的认证登录 环境 Vs.net 2013 Asp.net mvc web api Individual user accounts Angularjs Underscore 新建一个asp.net mvc web api …

PANIC: Unreachable code reached.

为什么80%的码农都做不了架构师&#xff1f;>>> Caused by: java.lang.RuntimeException: PANIC: Unreachable code reached.at cryptix.jce.provider.cipher.BlockCipher.engineGetParameters(BlockCipher.java:244)at javax.crypto.Cipher.checkCryptoPerm(Ciphe…

Linux VTIME VMIN的作用以及使用有效的前提

前提条件 1、fdcom open(ptty, O_RDWR | O_NOCTTY); //other attributions default /*Canonical Input*/ //termios_new.c_lflag | (ICANON | ECHO | ECHOE); 2、/*Raw Input*/ //termios_new.c_lflag & ~(ICANON | ECHO | ECHOE | ISIG); 下面解释&#xff1a; op…

php中使用httpclient

下载HttpClient.phphttp://yunpan.cn/QiD93DMb6vsEH &#xff08;提取码&#xff1a;ec47&#xff09; 下载之后&#xff0c;将该文件放到项目文件目录下新建class目录下 然后在php中使用: 1 <?php2 require_once class/HttpClient.php;3 $params array(4 coords>114.3…

Hi3520d uboot uImage rootfs 移植与升级

安装、升级hi3520DDEMO板开发开发环境 # 如果您使用的hi3520D的DEMO板&#xff0c;可以按照以下步骤烧写u-boot&#xff0c;内核以及文件系统&#xff0c;以下步骤均使用网络来更新。 # 通常&#xff0c;您拿到的单板中已经有u-boot&#xff0c;如果没有的话&#xff0…

面向切面编程(转)

面向切面编程&#xff08;AOP是Aspect Oriented Program的首字母缩写&#xff09; &#xff0c;我们知道&#xff0c;面向对象的特点是继承、多态和封装。而封装就要求将功能分散到不同的对象中去&#xff0c;这在软件设计中往往称为职责分配。实际上也就是说&#xff0c;让不同…

Hi3520d uImage制作 uboot制作 rootfs制作

首次安装SDK 1、hi3520D SDK包位置 在"hi3520D_V100R001***/01.software/board"目录下&#xff0c;您可以看到一个 hi3520D_SDK_Vx.x.x.x.tgz 的文件&#xff0c; 该文件就是hi3520D的软件开发包。 2、解压缩SDK包 在linux服务器上&#xff08;或者一台装有…

[LeetCode Online Judge]系列-求二维平面内在一条直线上的最大点数

2019独角兽企业重金招聘Python工程师标准>>> Max Points on a Line Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. 题目是:在2D平面内给N个点,求最多多少个点在一个直线上. 以下是AC的解决方式: /*** Defi…

Hi3520D UART2和UART3是如何加载到内核的

Hi3520D的UART驱动位于linux-3.0.y/drivers/tty/serial/amba-pl011.c 添加UART2和UART3需要修改的文件为&#xff1a;linux-3.0.y/arch/arm/mach-hi3520d/core.c和linux-3.0.y/arch/arm/mach-hi3520d/include/mach/irqs.h两个文件&#xff1b; 首先修改 core.c文件&#xff0c;…

Linux-C实现GPRS模块发送短信

“GSM模块&#xff0c;是将GSM射频芯片、基带处理芯片、存储器、功放器件等集成在一块线路板上&#xff0c;具有独立的操作系统、GSM射频处理、基带处理并提供标准接口的功能模块。GSM模块根据其提供的数据传输速率又可以分为GPRS模块、EDGE模块和纯短信模块。短信模块只支持语…

【思科】GNS3模拟静态NAT/动态NAT

实验拓扑&#xff1a;实验目的&#xff1a;利用NAT技术&#xff0c;使C1,C2能与R2连通。实验步骤&#xff1a;如图配置好IP地址&#xff0c;为C1,C2指定网关192.168.1.1。2.在R1上配置静态NAT.假定为C1配置公网地址12.0.0.3&#xff0c;来实现与R2的连通。这样&#xff0c;静态…

Text模式和PDU模式的区别

发送短消息常用Text和PDU(Protocol Data Unit&#xff0c;协议数据单元)模式。使用Text模式收发短信代码简单&#xff0c;实现起来十分容易&#xff0c;但最大的缺点是不能收发中文短信&#xff1b;而PDU模式不仅支持中文短信&#xff0c;也能发送英文短信。PDU模式收发短信…

[家里蹲大学数学杂志]第041期中山大学数计学院 2008 级数学与应用数学专业《泛函分析》期末考试试题 A...

1 ( 10 分 ) 设 $\mathcal{X}$ 是 Banach 空间, $f$ 是 $\mathcal{X}$ 上的线性泛函. 求证: $f\in \mathcal{L}(\mathcal{X})$ 的充分必要条件是 \[ N(f)\{ x\in \mathcal{X};\ f(x)0 \} \] 是 $\mathcal{X}$ 的闭线性子空间. 证明: 必要性. 设 $N(f)\ni x_n\to x$, 则 $$\bex …

PUD编码规则

共有三种方式来发送和接收SMS信息&#xff1a;Block Mode, Text Mode和PDU Mode。其中PDU Mode被所有手机支持&#xff0c;可以使用任何字符集&#xff0c;这也是手机默认的编码方式。 发送短消息常用Text和PDU(Protocol Data Unit&#xff0c;协议数据单元)模式。使用Text模式…

xml 解析

2019独角兽企业重金招聘Python工程师标准>>> 各大数据接口大全&#xff1a;http://blog.sina.com.cn/s/articlelist_2127818045_10_1.html package com.test.junit; import static org.junit.Assert.*; import java.io.ByteArrayInputStream;import java.io.InputSt…