• 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
  • 相关阅读:
    iOS开发系列-Category
    OC开发系列-内存管理
    OC开发系列-@property和@synthesize
    OC开发系列-成员变量的作用域
    OC开发系列-类与对象
    MySQL
    JavaWeb
    POJ1845-Sumdiv大数约数和
    poj1159 Palindrome 区间DP
    poj 2955 Brackets 区间DP
  • 原文地址:https://www.cnblogs.com/hkyst/p/7608367.html
Copyright © 2020-2023  润新知