Linux串口编程

    串口编程流程:(串口发送部分)

int set_opt(int,int,int,char,int);
void main()
{
    int fd,wr_static,i=10;
    char *uart3 = "/dev/ttySAC3";
    char *buffer = "hello world!\n";
    
    printf("\r\nitop4412 uart3 writetest start\r\n");
    
    if((fd = open(uart3, O_RDWR|O_NOCTTY|O_NDELAY))<0){//打开串口
        printf("open %s is failed",uart3);
    }
    else{
        printf("open %s is success\n",uart3);
        set_opt(fd, 115200, 8, 'N', 1); //串口配置
        while(i--)
        {
            wr_static = write(fd,buffer, strlen(buffer));//串口发送
            if(wr_static<0)
                printf("write failed\n");
            else{
                printf("wr_static is %d\n",wr_static);
            }
            sleep(1);
        }
    }
    close(fd);
}

  串口的初始化程序,基本上是通用的:

    内核中关于串口初始化的结构体   arch/arm/include/asm/termios.h    

    termio 结构体:

        #define NCC 8
        struct termio {
            unsigned short c_iflag;         /* input mode flags */
            unsigned short c_oflag;         /* output mode flags */
            unsigned short c_cflag;         /* control mode flags */
            unsigned short c_lflag;         /* local mode flags */
            unsigned char c_line;           /* line discipline */
            unsigned char c_cc[NCC];        /* control characters */
            };    

  串口初始化步骤是:
    – 读取当前参数
    – 修改参数
    – 配置参数

  tcgetattr 函数      读取当前参数函数

      man 3 tcgetattr 

        int tcgetattr(int fd, struct termios *termios_p);
  获取当前波特率函数 
            speed_t cfgetispeed(const struct termios *termios_p);
            speed_t cfgetospeed(const struct termios *termios_p);
                – *termios_p:前面介绍的结构体
                – 失败返回-1;成功返回波特率                                       

   波特率设置函数 

         int cfsetispeed(struct termios *termios_p, speed_t speed);
         int cfsetospeed(struct termios *termios_p, speed_t speed);
        – 参数*termios_p:前面介绍的结构体。
        – 参数speed:speed 波特率,常用的B2400,B4800,B9600,B115200,
    B460800 等等。
        – 执行成功返回0,失败返回-1  

    清空串口BUFFER中的数据函数

         int tcflush(int fd, int queue_selector);
            – 参数1:fd 是open 返回的文件句柄。
            – 参数2:控制tcflush 的操作。有三个常用数值,TCIFLUSH 清除正收到的数
        据,且不会读取出来;TCOFLUSH 清除正写入的数据,且不会发送至终
        端;TCIOFLUSH 清除所有正在发生的I/O 数据。
            – 执行成功返回0,失败返回-1    

    设置串口参数函数

        int tcsetattr(int fd, int optional_actions,const struct termios *termios_p);
        – 参数fd:open 返回的文件句柄。
        – 参数optional_actions:参数生效的时间。有三个常用的值:TCSANOW:
        不等数据传输完毕就立即改变属性;TCSADRAIN:等待所有数据传输结束
            才改变属性;TCSAFLUSH:清空输入输出缓冲区才改变属性。
        – 参数*termios_p :在旧的参数基础上修改的后的参数。
        – 返回值:执行成功返回0,失败返回-1
        – 一般在初始化最后会使用这个函数    

   完整的串口初始化程序:

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
    struct termios newtio,oldtio;
    if  ( tcgetattr( fd,&oldtio)  !=  0)  //读取当前串口参数到名为oldtio的 termio 类型结构体中
  { 
        perror("SetupSerial 1");
        return -1;
    }
    bzero( &newtio, sizeof( newtio ) );  //bzero() 会将内存块(字符串)的前n个字节清零
    newtio.c_cflag  |=  CLOCAL | CREAD;  //控制模式
    newtio.c_cflag &= ~CSIZE;

    switch( nBits )  //判断 bits
    {
    case 7:
        newtio.c_cflag |= CS7; //CS5 CS6
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }

    switch( nEvent )  //奇偶校验
    {
    case 'O':
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case 'E': 
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case 'N':  
        newtio.c_cflag &= ~PARENB;
        break;
    }

    switch( nSpeed )    //波特率
    {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    case 460800:
        cfsetispeed(&newtio, B460800);
        cfsetospeed(&newtio, B460800);
        break;
    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }
    if( nStop == 1 )    //停止位
        newtio.c_cflag &=  ~CSTOPB;
    else if ( nStop == 2 )
    newtio.c_cflag |=  CSTOPB;
    newtio.c_cc[VTIME]  = 0;
    newtio.c_cc[VMIN] = 0;
    tcflush(fd,TCIFLUSH); //清空Buffer中的数据
    if((tcsetattr(fd,TCSANOW,&newtio))!=0) //写入新的结构体
    {
        perror("com set error");
        return -1;
    }
//    printf("set done!\n\r");
    return 0;
}

   串口接收部分

int set_opt(int,int,int,char,int);
//"/dev/ttySAC3"是con2,靠近耳机接口的串口
void main()
{
    int fd,nByte;
    char *uart3 = "/dev/ttySAC3";
    char buffer[512];
    char *uart_out = "please input\r\n";
    memset(buffer, 0, sizeof(buffer));
    if((fd = open(uart3, O_RDWR|O_NOCTTY))<0)
        printf("open %s is failed",uart3);
    else{
        set_opt(fd, 115200, 8, 'N', 1);
        write(fd,uart_out, strlen(uart_out));
        while(1){
            while((nByte = read(fd, buffer, 512))>0){
                buffer[nByte+1] = '\0';            
                write(fd,buffer,strlen(buffer));
                memset(buffer, 0, strlen(buffer));
                nByte = 0;
            }
        }
    }
}
View Code
原文地址:https://www.cnblogs.com/hkyst/p/7608367.html