fl2440串口编程

来源:互联网 发布:制作淘宝无缝拼接主图 编辑:程序博客网 时间:2024/06/04 19:20

竞渡深悲千载冤,忠魂一去讵能还。国亡身殒今何有,只留离骚在世间。——张耒《和端午》

内核版本:3.0.54

  串口通信是我们常见的一种通信,在很多开发中不可缺少,这篇文章主要讲如何设置我们的串口,以便后续开发。

前面介绍UART的时候已经概述,我们主要用到三根针来传输数据,即RXD,TXD,GND。具体的连接前面有说明,大家可前往查看。

串口的配置

1.波特率:为了两者信号流能同步,因此收发双方的波特率应该一致。
2.数据位:几位数据封装成一帧,因为数据以帧为单位传输,所以这里要设置。
3.结束位:数据在传输时需要判断什么时候结束,因此结束位能够保证接收方获得有效数据。
4.奇偶校验:检验数据的一种有效方法,需要板子和模块同时开启。

Linux中的串口参数在/dev下,我们板子的串口为/dev/ttyS0,/dev/ttyS1,这里出于不可抗拒因素,我们的这两个串口我都没有使用,我用的是USB接口来连接我们的串口,即ttyUSB0。

当然,要是用USB接口,那就得移植USB驱动咯,这里推荐一篇好的文章:http://blog.csdn.net/edroid1530/article/details/70186871

除了这篇文章上的东东,我们还需要在内核中添加我们的USB转串口的内容:

export TERM=vt100make menuconfigDevice Drivers ——>        [*] USB support ——>                <*>   Support for Host-side USB                [*]   USB device filesystem (DEPRECATED)                  [*]   USB device class-devices (DEPRECATED)                <*>   USB Monitor                <*>   OXU210HP HCD support                <*>   OHCI HCD support                <*>   USB Mass Storage support                [*]   The shared table of common (or usual) storage devices                <*>   USB Serial Converter support  --->                                    <*>   USB Winchiphead CH341 Single Port Serial Driver                                    <*>   USB CP210x family of UART Bridge Controllers                                    <*>   USB FTDI Single Port Serial Driver                                    <*>   USB Prolific 2303 Single Port Serial Driver后面部分主要是对串口的设置。

在Linux下,一切皆文件,串口也不例外,我们对他的操作也是read、write、等等。

串口结构体

struct termios{      tcflag_t  c_iflag;  //input flags      tcflag_t  c_oflag;  //output flags      tcflag_t  c_cflag;  //control flags      tcflag_t  c_lflag;  //local flags      cc_t      c_cc[NCCS]; //control characters

其中c_cflag是最重要的,波特率、数据位、校验位以及停止位都在这里设置。

关于c_cflag:

CCTS_OFLOW 输出的CTS流控制 CIGNORE 忽略控制标志 CLOCAL 忽略解制-解调器状态行 CREAD 启用接收装置 CRTS_IFLOW 输入的RTS流控制 CSIZE 字符大小屏蔽 CSTOPB 送两个停止位,否则为1位 HUPCL 最后关闭时断开 MDMBUF 经载波的流控输出 PARENB 进行奇偶校验 PARODD 奇校验,否则为默认偶校验

关于c_iflag

BRKINT 接到BREAK时产生SIGINT ICRNL 将输入的CR转换为NL IGNBRK 忽略BREAK条件 IGNCR 忽略CR IGNPAR 忽略奇偶错字符 IMAXBEL 在输入队列空时振铃 INLCR 将输入的NL转换为CR INPCK 打开输入奇偶检验 ISTRIP 剥除输入字符的第8位 IUCLC 将输入的大写字符转换成小写字符 IXANY 使任一字符都重新启动输出 IXOFF 使启动/停止输入控制流起作用 IXON 使启动/停止输出控制流起作用 PARMRK 标记奇偶错

串口的控制函数:

Tcgetattr 取属性(termios结构) Tcsetattr 设置属性(termios结构) cfgetispeed 得到输入速度 Cfgetospeed 得到输出速度 Cfsetispeed 设置输入速度 Cfsetospeed 设置输出速度 Tcdrain 等待所有输出都被传输 tcflow 挂起传输或接收 tcflush 刷清未决输入和/或输出 Tcsendbreak 送BREAK字符 tcgetpgrp 得到前台进程组ID tcsetpgrp 设置前台进程组ID
配置流程

1.保存原先串口配置,tcgetattr(fd,&oldtio)函数:

struct termios newtio,oldtio;tcgetattr(fd,&oldtio);

2.激活选项:CLOCAL和CREAD,用于本地连接和接收使用

 newtio.c_cflag | = CLOCAL | CREAD;

3.设置波特率:cfsetispeed、cfsetospeed,数字前面加个’B’。

 cfsetispeed(&newtio,B115200); cfsetospeed(&newtio,B115200); 

4.设置数据位,需用掩码

newtio.c_cflag &= ~CSIZE; newtio.c_cflag |= CS8;

5.设置奇偶校验位,使用c_cflag和c_iflag

奇校验:newtio.c_cflag |= PARENB;newtio.c_cflag |= PARODD;newtio.c_iflag |= (INPCK | ISTRIP);偶校验:newtio.c_iflag |= (INPCK|ISTRIP);newtio.c_cflag |= PARENB;newtio.c_cflag |= ~PARODD;

6.设置停止位,通过激活c_cflag中的CSTOPB实现。若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB。

newtio.c_cflag &= ~CSTOPB;

7.设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时,可设为0

newtio.c_cc[VTIME] = 0;newtio.c_cc[VMIN]  = 0;

8.处理要写入的引用对象
tcflush函数刷清(抛弃)输入缓存(终端驱动程序已接收到,但用户程序尚未读)或输出缓存(用户程序已经写,但尚未发送)

 int tcflush(int filedes,int quene)

其中quene: *TCIFLUSH 刷清输入队列、*TCOFLUSH 刷清输出队列、 *TCIOFLUSH 刷清输入、输出队列。

ex:tcflush(fd,TCIFLUSH);

9.激活配置。在完成配置后,需要激活配置使其生效。使用tcsetattr()函数:

int tcsetattr(int filedes,int opt,const struct termios *termptr);

opt使我们可以指定在什么时候新的终端属性才起作用
*TCSANOW:更改立即发生
*TCSADRAIN:发送了所有输出后更改才发生。若更改输出参数则应使用此选项
*TCSAFLUSH:发送了所有输出后更改才发生。更进一步,在更改发生时未读的所有输入数据都被删除(刷清)

ex: tcsetattr(fd,TCSANOW,&newtio);

串口的使用

1.打开串口
fd = open(“/dev/ttyUSB0”, O_RDWR | O_NOCTTY | O_NDELAY);
参数:
O_NOCTTY:通知linux系统,这个程序不会成为这个端口的控制终端
O_NDELAY:通知linux系统不关心DCD信号线所处的状态(端口的另一端是否激活或者停止)

然后恢复串口的状态为阻塞状态,用于等待串口数据的读入,用fcntl函数:

 fcntl(fd,F_SETFL,0);  //F_SETFL:设置文件flag为0,即默认,即阻塞状态

接着测试打开的文件描述符是否应用一个终端设备,以进一步确认串口是否正确打开

 isatty(STDIN_FILENO);

读写串口这里就不详细说了,就是操作文件一样:

 read(fd,buff,8); write(fd,buff,8);

下面给一个通用的设置串口的程序:

/*********************************************************************************    *      Copyright:  (C) 2017 tangyanjun<519656780@qq.com>    *                  All rights reserved.    *    *       Filename:  serial.c    *    Description:  This file     *                     *        Version:  1.0.0(05/28/2017)    *         Author:  tangyanjun <519656780@qq.com>   *      ChangeLog:  1, Release initial version on "05/28/2017 11:12:13 AM"   *                    ********************************************************************************/#include <stdio.h>#include <errno.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <unistd.h>/************************************************************************************** *  Description: 串口参数配置 *  Input Args: fd:open打开的文件描述符 nspeed:波特率 nBits:数据位数 nEvent:奇偶校验 nStop:停止位 *  Output Argtingzhis: 串口参数设置失败返回-1 * Return Value: *************************************************************************************/int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop){    struct termios newttyUSB0, oldttyUSB0;    if(tcgetattr(fd, &oldttyUSB0) != 0)         //保存原先串口配置    {        perror("Setupserial 1");        return -1;    }bzero(&newttyUSB0, sizeof(newttyUSB0));       //将一段内存区域的内容全清为零newttyUSB0.c_cflag |= (CLOCAL | CREAD );       //CREAD 开启串行数据接收,CLOCAL并打开本地连接模式   newttys1.c_cflag &= ~CSIZE;              //设置数据位数switch(nBits)     //选择数据位   {        case 7:                newttyUSB0.c_cflag |=CS7;                break;        case 8:                newttyUSB0.c_cflag |=CS8;                break; }switch( nEvent )    //设置校验位   {   case '0':       //奇校验             newttyUSB0.c_cflag |= PARENB;             //开启奇偶校验             newttyUSB0.c_iflag |= (INPCK | ISTRIP);   //INPCK打开输入奇偶校验;ISTRIP去除字符的第八个比特             newttyUSB0.c_cflag |= PARODD;             //启用奇校验(默认为偶校验)             break;  case 'E' :       //偶校验             newttyUSB0.c_cflag |= PARENB;             //开启奇偶校验             newttyUSB0.c_iflag |= ( INPCK | ISTRIP);  //打开输入奇偶校验并去除字符第八个比特             newttyUSB0.c_cflag &= ~PARODD;            //启用偶校验;             break;  case 'N':     //关闭奇偶校验           newttyUSB0.c_cflag &= ~PARENB;           break;   }     switch( nSpeed )        //设置波特率       {        case 2400:                 cfsetispeed(&newttyUSB0, B2400);           //设置输入速度                 cfsetospeed(&newttyUSB0, B2400);           //设置输出速度                 break;        case 4800:                 cfsetispeed(&newttyUSB0, B4800);                 cfsetospeed(&newttyUSB0, B4800);                 break;        case 9600:                 cfsetispeed(&newttyUSB0, B9600);                 cfsetospeed(&newttyUSB0, B9600);                 break;        case 115200:                 cfsetispeed(&newttyUSB0, B115200);                 cfsetospeed(&newttyUSB0, B115200);                 break;        default:                 cfsetispeed(&newttyUSB0, B9600);                 cfsetospeed(&newttyUSB0, B9600);                 break;     }     if( nStop == 1)                      //设置停止位;若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB。       {        newttyUSB0.c_cflag &= ~CSTOPB;      //默认为送一位停止位;       }     else if( nStop == 2)     {        newttyUSB0.c_cflag |= CSTOPB;       //CSTOPB表示送两位停止位;       }     //设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时     newttyUSB0.c_cc[VTIME] = 0;        //非规范模式读取时的超时时间;       newttyUSB0.c_cc[VMIN]  = 0;        //非规范模式读取时的最小字符数;       tcflush(fd ,TCIFLUSH);           //tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来      // 在完成配置后,需要激活配置使其生效     if((tcsetattr( fd, TCSANOW, &newttyUSB0)) != 0) //TCSANOW不等数据传输完毕就立即改变属性       {         perror("com set error");         return -1;     }    return 0;} /* ----- End of if()  ----- */