fl2440串口编程

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

内核版本: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=vt100
make menuconfig

Device 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()  ----- */
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值