I.MX6ULL 的 UART 驱动 NXP 已经编写好了,所以不需要我们编写关于IMX6ULL 开发板UART程序, 以下为UART3作为rs232使用。
串口驱动配置 1、 UART3 IO 节点创建UART3 用到了 UART3_TXD 和 UART3_RXD 这两个 IO,因此要先在 iomuxc 中创建 UART3对应的 pinctrl 子节点,在 iomuxc 中添加如下内容:
pinctrl_uart3: uart3grp {
fsl,pins = <
MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1
MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1
>;
};
最后检查一下 UART3_TX 和 UART3_RX 这两个引脚有没有被用作其他功能,如果有用作其它功能的话要将其屏蔽掉,保证这两个 IO 只用作 UART3
2、添加 uart3 节点默认情况下 imx6ull-alientek-emmc.dts 中只有 uart1 和 uart2 这两个节点,如下图所示:
uart1 是 UART1 的,在 I.MX6ull开发板上没有用到 UART2,而且 UART2默认用到了 UART3 的 IO,因此需要将 uart2 这个节点删除掉,然后加上 UART3 对应的 uart3,uart3 节点内容如下:
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart3>;
status = "okay";
};
完成以后重新编译设备树并使用新的设备树启动 Linux, 如果设备树修改成功的话,系统启动以后就会生成一个名为“/dev/ttymxc2”的设备文件, ttymxc2 就是 UART3 对应的设备文件,应用程序可以通过访问 ttymxc2 来实现对 UART3 的操作。
串口应用程序编写#include串口用编程函数介绍#include #include #include #include #include #include #include int set_opt(int,int,int,char,int); void main() { int fd,nByte,flag=1; char *uart3 = "/dev/ttymxc2"; //"/dev/ttymxc2"是COM3 char buffer[512]; char *uart_out = "Please input,waiting....rn"; char *uart_demo = "Linux uart demorn"; memset(buffer, 0, sizeof(buffer)); //if((fd = open(uart3, O_RDWR|O_NOCTTY))<0)//默认为阻塞读方式 if((fd = open(uart3, O_RDWR|O_NONBLOCK))<0)//非阻塞读方式 printf("open %s is failed",uart3); else{ set_opt(fd, 115200, 8, 'N', 1); write(fd,uart_demo, strlen(uart_demo)); write(fd,uart_out, strlen(uart_out)); while(1){ while((nByte = read(fd, buffer, 512))>0){ buffer[nByte+1] = ' '; write(fd,buffer,strlen(buffer)); memset(buffer, 0, strlen(buffer)); nByte = 0; } } } } int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop) { struct termios newtio,oldtio; if ( tcgetattr( fd,&oldtio) != 0) { perror("SetupSerial 1"); return -1; } bzero( &newtio, sizeof( newtio ) ); newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; switch( nBits ) { case 7: newtio.c_cflag |= CS7; 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] = 100;// newtio.c_cc[VMIN] = 0; tcflush(fd,TCIFLUSH); if((tcsetattr(fd,TCSANOW,&newtio))!=0) { perror("com set error"); return -1; } // printf("set done!nr"); return 0; }
1、读取当前参数函数:
int tcgetattr(int fd,struct termios *termios_p)
fd:open操作后返回的文件句柄 *termios_p:为前面介绍的结构体 初始化开始前调用这个函数.
2、获取当前波特率函数:
int speed_t cfgetispeed(const struct termios *termios_p) int speed_t cfgetospeed(const struct termios *termios_p)
*termios_p:为前面介绍的结构体 成功返回0,失败返回-1
3、波特率设置函数:
int cfsetispeed(struct termios *termios_p,speed_t speed) int cfsetospeed(struct termios *termios_p,speed_t speed)
*termios_p:为前面介绍的结构体 speed:波特率,常用B2400,B4800,B9600,B115200,B460800 成功返回0,失败返回-1
4、清空buffer数据函数:
int tcflush(int fd,int queue_selector)
queue_selector:有三个常用宏定义
TCIFLUSH:清空正读的数据,且不会读出
TCOFLUSH:清空正写入的数据,且不会发送到终端
TCIOFLUSH:清空所有正在发生的I/O数据.
成功返回0,失败返回-1
5、设置串口参数函数:
int tcsetattr(int fd,int optional_actions,cons struct termios *termios_p)
optional_actions:有三个常用宏定义
TCSANOW:不等数据传输完毕,立即改变属性
TCSADRAIN:等所有数据传输完毕,再改变属性
TCSAFLUSH:清空输入输出缓冲区才改变属性
成功返回0,失败返回-1
串口号介绍
PC的默认串口为ttyS0;
嵌入式设备的默认串口为ttymxc*(代表数字);
注:嵌入式设备Samsung Artik 710架构的则是ttySAC(*代表数字)



