• 迅为IMX6ULL开发板Linux RS232/485驱动实验(下)


    53.3  硬件原理图
    53.3.1 RS232
    <ignore_js_op>
    UART3 通过跳线帽 J46 来设置成 TTL 电平的 RS232 信号。连接 J46 的 3-5 和 4-6 后,UART3 通过 TTL 电平输出。
    53.3.2 RS485
    <ignore_js_op>
    RS485 通过 SP3485 芯片将串口信号转换为 RS485 信号,RE 是接收使能信号(低电平有效),OE 是发送使能信号(高电平有效)。在图中 RE 和 OE 经过一系列的电路,最终通过 RS485_1_TX 来控制,这样我们可以省掉一个 RS485 收发控制 IO,将 RS485 完全当作一个串口来使用,方便我们写驱动。
    53.4 RS232  驱动
    I.MX6U 的 UART 驱动 NXP 已经编写好了,所以不需要我们编写。我们需要做的就是在设备树中添加 UART3 对应的设备节点即可。
    53.4.1  设备树添加 UART3  节点
    打开 topeet_emmc_4_3.dts 文件,首先添加 UART3 对应的 pinctrl 子节点,在 iomuxc 中添加如下内容:
    1 pinctrl_uart3: uart3grp {
    2 fsl,pins = <
    3 MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0X1b0b1
    4 MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0X1b0b1
    5 >;
    6 };
    然后检查一下 UART3_TX 和 UART3_RX 这两个引脚有没有被用作其他功能,如果有的话要将其屏蔽掉,保证这两个 IO 只用作 UART3。
    添 加 完 pinctrl 子 节 点 后 , 添 加 uart3 节 点 , 仍 然 是 在 topeet_emmc_4_3.dts 文 件 中 , 在topeet_emmc_4_3.dts 文件中已经默认存在了 uart1 和 uart2 两个节点了,如图 53.4.1.1 所示:
    <ignore_js_op>
    因为没有用到 uart2,并且 uart2 的引脚节点中用到了 uart3 的 IO,所以需要将 uart2 注释或删掉。然后添加 uart3 节点,内容如下:
    1 &uart3 {
    2 pinctrl-names = "default";
    3 pinctrl-0 = <&pinctrl_uart3>;
    4 status = "okay";
    5 };
    添加完成后,重新编译设备树文件,然后使用新的设备树文件启动 Linux 系统。系统启动以后就会生成一个名为“/dev/ttymxc2”的设备文件,ttymxc2 就是 UART3 对应的设备文件,应用程序可以通过访问ttymxc2 来实现对 UART3 的操作。
    53.5 RS232  驱动测试
    53.5.1  编写应用测试程序
    本实验例程路径:i.MX6UL 终结者光盘资料/06_Linux 驱动例程/19_uart
    创建 uart_test.c 应用测试程序,具体内容如下:
    1 #include
    2 #include
    3 #include
    4 #include
    5 #include
    6 #include
    7 #include
    8 #include
    9 #include
    10
    11 int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
    12 {
    13 struct termios newtio,oldtio;
    14 if ( tcgetattr( fd,&oldtio) != 0) {
    15 perror("SetupSerial 1");
    16 return -1;
    17 }
    18 bzero( &newtio, sizeof( newtio ) );
    19 newtio.c_cflag |= CLOCAL | CREAD;
    20 newtio.c_cflag &= ~CSIZE;
    21
    22 switch( nBits )
    23 {
    24 case 7:
    25 newtio.c_cflag |= CS7;
    26 break;
    27 case 8:
    28 newtio.c_cflag |= CS8;
    29 break;
    30 }
    31
    32 switch( nEvent )
    33 {
    34 case 'O':
    35 newtio.c_cflag |= PARENB;
    36 newtio.c_cflag |= PARODD;
    37 newtio.c_iflag |= (INPCK | ISTRIP);
    38 break;
    39 case 'E':
    40 newtio.c_iflag |= (INPCK | ISTRIP);
    41 newtio.c_cflag |= PARENB;
    42 newtio.c_cflag &= ~PARODD;
    43 break;
    44 case 'N':
    45 newtio.c_cflag &= ~PARENB;
    46 break;
    47 }
    48
    49 switch( nSpeed )
    50 {
    51 case 2400:
    52 cfsetispeed(&newtio, B2400);
    53 cfsetospeed(&newtio, B2400);
    54 break;
    55 case 4800:
    56 cfsetispeed(&newtio, B4800);
    57 cfsetospeed(&newtio, B4800);
    58 break;
    59 case 9600:
    60 cfsetispeed(&newtio, B9600);
    61 cfsetospeed(&newtio, B9600);
    62 break;
    63 case 115200:
    64 cfsetispeed(&newtio, B115200);
    65 cfsetospeed(&newtio, B115200);
    66 break;
    67 case 460800:
    68 cfsetispeed(&newtio, B460800);
    69 cfsetospeed(&newtio, B460800);
    70 break;
    71 default:
    72 cfsetispeed(&newtio, B9600);
    73 cfsetospeed(&newtio, B9600);
    74 break;
    75 }
    76 if( nStop == 1 )
    77 newtio.c_cflag &= ~CSTOPB;
    78 else if ( nStop == 2 )
    79 newtio.c_cflag |= CSTOPB;
    80 newtio.c_cc[VTIME] = 0;
    81 newtio.c_cc[VMIN] = 0;
    82 tcflush(fd,TCIFLUSH);
    83 if((tcsetattr(fd,TCSANOW,&newtio))!=0)
    84 {
    85 perror("com set error");
    86 return -1;
    87 }
    88
    89 // printf("set done! ");
    90 return 0;
    91 }
    92 int main(int argc , char **argv)
    93 {
    94 int fd,wr_static,ret,nread,count=0;
    95 char *buffer = "hello world! ";
    96 char buff[8];
    97 int i;
    98
    99 if(argc < 3)
    100 printf("Usage ...");
    101
    102 printf(" uart__test start ");
    103
    104 char *uart = argv[1];
    105
    106 if((fd = open(uart, O_RDWR|O_NOCTTY|O_NDELAY))<0){
    107 printf("open %s is failed",uart);
    108 }
    109 else {
    110 printf("open %s is success ",uart);
    111 set_opt(fd, 115200, 8, 'N', 1);
    112 }
    113
    114 if(atoi(argv[2]) == 0)
    115 {
    116 while(1){
    117 if (ret == 0)
    118 printf("write time out ");
    119 else{
    120 ret = write(fd,buffer, strlen(buffer));
    121 sleep(1);
    122 }
    123 }
    124 }
    125
    126 else if(atoi(argv[2]) == 1)
    127 {
    128 memset(buff,0,8);
    129 while(1){
    130 while((nread = read(fd,buff,8))>0){
    131 //count+=nread;
    132 //printf("count = %d ",count);
    133 printf("read: ");
    134 for(i = 0; buff != 0; i++)
    135 printf("%c",buff);
    136 printf(" ");
    137 memset(buff,0,8);
    138 }
    139 }
    140 }
    141
    142 close(fd);
    143 return 0;
    144 }
    第 11~91 行,用于设置串口的波特率。
    第 92 行,main 函数需要两个参数,第一个参数是串口的设备节点文件,比如/dev/ttymxc2,第二个参数选择读写数据,0:写数据,1:读数据。
    第 111 行,当打开串口设备文件成功时,设置串口参数为:115200/8/N/1。用户可以根据实际情况修改。
    第 114~124 行,当指令为写数据时执行。使用 sleep 函数延时,1s 发一次数据。
    第 126~140 行,当指令为读数据时执行。
    53.5.2  运行测试
    首先使用下面的命令编译应用测试程序:
    arm-linux-gnueabihf-gcc -o uart_test uart_test.c
    编译成功,得到 uart_test 应用程序。
    然后开始测试 RS232 功能,因为 RS232 是 TTL 电平所以需要 USB 转 TTL 电平设备,然后连接开发板上的 uart3 引脚,在电脑打开 USB 转 TTL 电平设备的终端,如图 53.5.2.1 所示:
    <ignore_js_op>
    选择正确的 port 端口,应用程序中默认波特率为 115200,所以设置波特率为 115200,然后连接设备。
    拷贝编译好的 uart_test 应用测试程序到开发板中,执行下面命令进行写数据实现:
    ./uart_test /dev/ttymxc2 0 &
    运行结果如图 53.5.2.2 所示:
    <ignore_js_op>
    使用下面的命令进行读数据:
    ./uart_test /dev/ttymxc2 1 &
    运行结果如图 53.5.2.3 所示:
    <ignore_js_op>
    应用程序每次接受 8 个字节的数据,可以看出运行正常。
    53.6 RS485  测试
    其实 RS485 测试和 RS232 测试流程一样,只不过接口不一样,需要使用 USB 转 485 设备。应用测试程序也是一样的。在这里就不重复测试了,用户可以自己试验一下。
    <ignore_js_op>
    <ignore_js_op>

  • 相关阅读:
    matplotlib直方图学习小记
    matplotlib饼状图学习小记
    P2306 被yyh虐的mzc
    P1776 宝物筛选_NOI导刊2010提高(02)&& 多重背包二进制优化
    51NOD 1445 变色DNA
    51NOD 1459 迷宫游戏
    CODEVS 1001 舒适的路线
    P4514 上帝造题的七分钟
    1082 线段树练习 3 && 树状数组区间修改区间查询
    P4145 上帝造题的七分钟2 / 花神游历各国
  • 原文地址:https://www.cnblogs.com/liyue3/p/14154770.html
Copyright © 2020-2023  润新知