imx6u-串口(UART3 基于原子开发板)linux 串口编程

记录下开发技能-linux开发点滴

1.设备树照着教程弄,编译,下载

2. linux 串口开发参考https://www.cnblogs.com/silencehuan/p/11103074.html,在此感谢

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <sys/types.h>    //定义数据类型,如 ssiz e_t off_t 等

#include <sys/stat.h>    //文件状态

#include <fcntl.h>        //文件控制定义

#include <termios.h>    //终端I/O

#include <errno.h>        //与全局变量 errno 相关的定义

#include <getopt.h>        //处理命令行参数

#include <string.h>        //字符串操作

#include <time.h>        //时间

#include <sys/select.h>    //select函数

 

 

 

 

int setOpt(int fd, int nSpeed, int nBits, int nParity, int nStop)

{

    struct termios newtio, oldtio;

 

    // 保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息

    if (tcgetattr(fd, &oldtio) != 0)

    {

        perror("SetupSerial 1");

        return -1;

    }

 

    bzero(&newtio, sizeof(newtio));        //新termios参数清零

    newtio.c_cflag |= CLOCAL | CREAD;    //CLOCAL--忽略 modem 控制线,本地连线, 不具数据机控制功能, CREAD--使能接收标志

    // 设置数据位数

    newtio.c_cflag &= ~CSIZE;    //清数据位标志

    switch (nBits)

    {

        case 7:

            newtio.c_cflag |= CS7;

        break;

        case 8:

            newtio.c_cflag |= CS8;

        break;

        default:

            fprintf(stderr, "Unsupported data size\n");

            return -1;

    }

    // 设置校验位

    switch (nParity)

    {

        case 'o':

        case 'O':                     //奇校验

            newtio.c_cflag |= PARENB;

            newtio.c_cflag |= PARODD;

            newtio.c_iflag |= (INPCK | ISTRIP);

            break;

        case 'e':

        case 'E':                     //偶校验

            newtio.c_iflag |= (INPCK | ISTRIP);

            newtio.c_cflag |= PARENB;

            newtio.c_cflag &= ~PARODD;

            break;

        case 'n':

        case 'N':                    //无校验

            newtio.c_cflag &= ~PARENB;

            break;

        default:

            fprintf(stderr, "Unsupported parity\n");

            return -1;

    }

    // 设置停止位

    switch (nStop)

    {

        case 1:

            newtio.c_cflag &= ~CSTOPB;

        break;

        case 2:

            newtio.c_cflag |= CSTOPB;

        break;

        default:

            fprintf(stderr,"Unsupported stop bits\n");

            return -1;

    }

    // 设置波特率 2400/4800/9600/19200/38400/57600/115200/230400

    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 19200:

            cfsetispeed(&newtio, B19200);

            cfsetospeed(&newtio, B19200);

            break;

        case 38400:

            cfsetispeed(&newtio, B38400);

            cfsetospeed(&newtio, B38400);

            break;

        case 57600:

            cfsetispeed(&newtio, B57600);

            cfsetospeed(&newtio, B57600);

            break;

        case 115200:

            cfsetispeed(&newtio, B115200);

            cfsetospeed(&newtio, B115200);

            break;

        case 230400:

            cfsetispeed(&newtio, B230400);

            cfsetospeed(&newtio, B230400);

            break;

        default:

            printf("\tSorry, Unsupported baud rate, set default 9600!\n\n");

            cfsetispeed(&newtio, B9600);

            cfsetospeed(&newtio, B9600);

            break;

    }

    // 设置read读取最小字节数和超时时间

    newtio.c_cc[VTIME] = 1;     // 读取一个字符等待1*(1/10)s

    newtio.c_cc[VMIN] = 1;        // 读取字符的最少个数为1

 

    tcflush(fd,TCIFLUSH);         //清空缓冲区

    if(tcsetattr(fd, TCSANOW, &newtio) != 0)    //激活新设置

    {

        perror("SetupSerial 3");

        return -1;

    }

    printf("Serial set done!\n");

    return 0;

}

 

/**@brief 串口读取函数

* @param[in]  fd         打开的串口文件句柄

* @param[in]  *rcv_buf 接收缓存指针

* @param[in]  data_len    要读取数据长度

* @param[in]  timeout     接收等待超时时间,单位ms

* @return     返回设置结果

* - >0      设置成功

* - 其他      读取超时或错误

*/

int UART_Recv(int fd, char *rcv_buf, int data_len, int timeout)

{

    int len=0, fs_sel=0;

    fd_set fs_read;

    struct timeval time;

 

    time.tv_sec = timeout / 1000;              //set the rcv wait time

    time.tv_usec = timeout % 1000 * 1000;    //100000us = 0.1s

 

    FD_ZERO(&fs_read);        //每次循环都要清空集合,否则不能检测描述符变化

    FD_SET(fd, &fs_read);    //添加描述符

 

    // 超时等待读变化,>0:就绪描述字的正数目, -1:出错, 0 :超时

    fs_sel = select(fd + 1, &fs_read, NULL, NULL, &time);

    printf("fs_sel = %d\n", fs_sel);

    if(fs_sel)

    {

        len = read(fd, rcv_buf, data_len);

        return len;

    }

    else

    {

        printf("Sorry,rev tout! \n");

        return -1;

    }

}

 

/**@brief 串口发送函数

* @param[in]  fd            打开的串口文件句柄

* @param[in]  *send_buf     发送数据指针

* @param[in]  data_len     发送数据长度

* @return     返回结果

* - data_len    成功

* - -1            失败

*/

int UART_Send(int fd, char *send_buf, int data_len)

{

    ssize_t ret = 0;

 

    ret = write(fd, send_buf, data_len);

    if (ret == data_len)

    {

        printf("send data is %s\n", send_buf);

        return ret;

    }

    else

    {

        printf("write device error\n");

        tcflush(fd,TCOFLUSH);

        return -1;

    }

}

 

int main(int argc,char *argv[])

{

    int fd = 0;

    char buf[16]="123456hellotty\n";

    char rbuf[16]={0x00};

    int len=0;

 

    

    fd =  open("/dev/ttymxc2",O_RDWR | O_NOCTTY | O_NDELAY );

    if(fd < 0)

    {

        perror("/dev/ttymxc2");

        printf("/dev/ttymxc2 open err \n");

        return -1;

    }

    printf("open uart3 \n");

 

    // 设置串口阻塞, 0:阻塞, FNDELAY:非阻塞

    if (fcntl(fd, F_SETFL, 0) < 0)    //阻塞,即使前面在open串口设备时设置的是非阻塞的

    {

        printf("fcntl failed!\n");

    }

    printf("fcntl=%d\n", fcntl(fd, F_SETFL, 0));

    

 

    if (isatty(fd) == 0)

    {

        printf("standard input is not a terminal device\n");

        close(fd);

        return -1;

    }

    else

    {

        printf("is a tty success!\n");

    }

    printf("fd-open=%d\n", fd);

     // 设置串口参数

    if (setOpt(fd, 115200, 8, 'N', 1)== -1)    //设置8位数据位、1位停止位、无校验

    {

        fprintf(stderr, "Set opt Error\n");

        close(fd);

        exit(1);

    }

 

    tcflush(fd, TCIOFLUSH);    //清掉串口缓存

    fcntl(fd, F_SETFL, 0);    //串口阻塞

 

 

    while(1)    //循环读取数据

    {

        len = UART_Recv(fd, rbuf, sizeof(rbuf), 10000);

        if(len ==-1)

        {

            UART_Send(fd, buf,sizeof(buf) );

        }

        else

        {

            UART_Send(fd, rbuf,sizeof(rbuf) );

            int ii=0;

            for(ii=0;ii<len;ii++)

            {

                printf("%02x ",rbuf[ii]);

            }

            memset(rbuf,0x00,sizeof(rbuf));

            len=0;

        }

    

    }

    

    close(fd);

    return 0;

}

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值