53.3 硬件原理圖 53.3.1 RS232 ![]() UART3 通過跳線帽 J46 來設置成 TTL 電平的 RS232 信號。連接 J46 的 3-5 和 4-6 后,UART3 通過 TTL 電平輸出。 53.3.2 RS485 ![]() 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 所示: ![]() 因為沒有用到 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!\n\r"); 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!\r\n"; 96 char buff[8]; 97 int i; 98 99 if(argc < 3) 100 printf("Usage ..."); 101 102 printf("\r\n uart__test start\r\n"); 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\n",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\n"); 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\r\n",count); 133 printf("read: "); 134 for(i = 0; buff != 0; i++) 135 printf("%c",buff); 136 printf("\r\n"); 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 所示: ![]() 選擇正確的 port 端口,應用程序中默認波特率為 115200,所以設置波特率為 115200,然后連接設備。 拷貝編譯好的 uart_test 應用測試程序到開發板中,執行下面命令進行寫數據實現: ./uart_test /dev/ttymxc2 0 & 運行結果如圖 53.5.2.2 所示: ![]() 使用下面的命令進行讀數據: ./uart_test /dev/ttymxc2 1 & 運行結果如圖 53.5.2.3 所示: ![]() 應用程序每次接受 8 個字節的數據,可以看出運行正常。 53.6 RS485 測試 其實 RS485 測試和 RS232 測試流程一樣,只不過接口不一樣,需要使用 USB 轉 485 設備。應用測試程序也是一樣的。在這里就不重復測試了,用戶可以自己試驗一下。 ![]() ![]() |