说明
UART作为最常用的外设之一,通常在一些应用当中都起到了非常关键的作用,因此对其驱动和收发进行测试是非常有必要的。
端口确定
开发板上除了拥有type-C接口的调试串口外还引出了了另外3路uart接口,分别为COM1,COM2,COM3,如下:
![图片.png](//file.elecfans.com/web2/M00/88/41/pYYBAGOxeYSAUK0RAAMUQYx0g2g476.png)
本次,我就使用COM1来进行收发测试。
程序
开发板配套的资料里面有对UART控制的例程,通过稍加改动就可以作为我们测试的程序。
main函数如下:
int main(int argc, char *argv[])
{
int fd;
char send_buffer[100] = "Hello HD-G2UL-EVM\r\n";
char recv_buffer[100];
int i, ret;
if (argc != 2)
{
fprintf(stderr, "usage:serialtest com_port\n");
return -1;
}
ret = serial_open(argv[1], 9600, SERIAL_PARITY_NO, 8, SERIAL_STOPBIT_ONE, 1000);
if (ret == 0)
{
fprintf(stderr, "open serial failed\n");
return -1;
}
while(1)
{
serial_write(send_buffer, strlen(send_buffer));
while (serial_poll(1000)>0)
{
serial_read(recv_buffer, sizeof(recv_buffer));
}
}
serial_close();
return 0;
}
先是调用serial_open
函数对UART硬件进行初始化,其中设备名(串口号)需要作为参数传入,其它参数已经被程序指定死了,不可传入。默认波特率9600,8N1。
初始化完成后,进入while(1)循环中,循环发送字符串ello HD-G2UL-EVM
,同时查看串口是否有小写接收到,若有则通过控制台打印出来。
其余部分代码如下:
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <termio.h>
#include <sys/time.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <sys/mman.h>
#define CMSPAR 010000000000
#define SERIAL_FLUSH_TX 1
#define SERIAL_FLUSH_RX 2
#define SERIAL_PARITY_NO 0
#define SERIAL_PARITY_ODD 1
#define SERIAL_PARITY_EVENT 2
#define SERIAL_PARITY_MARK 3
#define SERIAL_PARITY_SPACE 4
#define SERIAL_STOPBIT_ONE 1
#define SERIAL_STOPBIT_TWO 2
static int serial_fd = -1;
struct termios old_tios;
static void serial_print_buf(unsigned char *buf,int len)
{
int i;
for(i=0;i<len;i++)
printf("%02X ",buf[i]);
printf("\n");
}
char *get_serial_dev_name(char *serial_name)
{
if (strcasecmp(serial_name, "COM2") == 0)
return "/dev/ttymxc1";
else if (strcasecmp(serial_name, "COM3") == 0)
return "/dev/ttymxc2";
else if (strcasecmp(serial_name, "COM4") == 0)
return "/dev/ttymxc3";
else if (strcasecmp(serial_name, "COM5") == 0)
return "/dev/ttymxc4 ";
else
return serial_name;
}
static int termios_init(struct termios *tios,int baud,int parity,int data_bits,int stop_bits)
{
speed_t baud_rate;
if (tios == NULL)
return -1;
tios->c_line = 0;
tios->c_cc[VMIN ] = 0;
tios->c_cc[VTIME] = 0;
tios->c_iflag = IGNBRK | IGNPAR | INPCK;
tios->c_oflag = 0;
tios->c_cflag = CREAD | CLOCAL;
if (data_bits == 5)
tios->c_cflag |= CS5;
else if (data_bits == 6)
tios->c_cflag |= CS6;
else if (data_bits == 7)
tios->c_cflag |= CS7;
else if (data_bits == 8)
tios->c_cflag |= CS8;
else
return -1;
if (stop_bits == 1)
tios->c_cflag &=~ CSTOPB;
else if (stop_bits == 2)
tios->c_cflag |= CSTOPB;
else
return -1;
if(parity == 0)
{
tios->c_cflag &=~ PARENB;
tios->c_cflag &=~ PARODD;
}
else if(parity == 2)
{
tios->c_cflag |= PARENB;
tios->c_cflag &=~ PARODD;
}
else if(parity == 1)
{
tios->c_cflag |= PARENB;
tios->c_cflag |= PARODD;
}
else if (parity == 3)
{
tios->c_cflag |= PARENB;
tios->c_cflag |= CMSPAR;
tios->c_cflag |= PARODD;
}
else if (parity == 4)
{
tios->c_cflag |= PARENB;
tios->c_cflag |= CMSPAR;
}
else
return -1;
tios->c_lflag = 0;
switch(baud)
{
case 110:
baud_rate = B110;
break;
case 300:
baud_rate = B300;
break;
case 600:
baud_rate = B600;
break;
case 1200:
baud_rate = B1200;
break;
case 2400:
baud_rate = B2400;
break;
case 4800:
baud_rate = B4800;
break;
case 9600:
baud_rate = B9600;
break;
case 19200:
baud_rate = B19200;
break;
case 38400:
baud_rate = B38400;
break;
case 57600:
baud_rate = B57600;
break;
case 115200:
baud_rate = B115200;
break;
case 230400:
baud_rate = B230400;
break;
case 460800:
baud_rate = B460800;
break;
case 576000:
baud_rate = B576000;
break;
case 921600:
baud_rate = B921600;
break;
default:
return -1;
}
if ((cfsetispeed(tios, baud_rate) < 0) ||(cfsetospeed(tios, baud_rate) < 0))
return -1;
return 0;
}
int serial_open(char *serial_name, int baud,int parity,int data_bits,int stop_bits,int timeout)
{
struct termios settings;
int fd;
char *serial_dev_name;
if (serial_fd >= 0)
return 0;
if (termios_init(&settings, baud,parity,data_bits,stop_bits) < 0)
return 0;
serial_dev_name = get_serial_dev_name(serial_name);
if (serial_dev_name == NULL)
{
fprintf(stderr, "invalid serial name:%s\n", serial_name);
return 0;
}
if((fd = open(serial_dev_name, O_RDWR | O_NOCTTY | O_NDELAY))< 0)
return 0;
if(tcgetattr(fd, &old_tios) < 0)
{
close(fd);
return 0;
}
if(tcsetattr(fd, TCSANOW, &settings) < 0)
{
close(fd);
return 0;
}
serial_fd = fd;
return 1;
}
int serial_close()
{
if (serial_fd < 0)
return 0;
tcsetattr(serial_fd, TCSANOW, &(old_tios));
close(serial_fd);
serial_fd = -1;
return 1;
}
int serial_flush(int flag)
{
if (serial_fd < 0)
return 0;
if (flag == SERIAL_FLUSH_TX)
tcflush(serial_fd,TCOFLUSH);
else if (flag == SERIAL_FLUSH_RX)
tcflush(serial_fd,TCIFLUSH);
else if (flag == (SERIAL_FLUSH_RX|SERIAL_FLUSH_TX) )
tcflush(serial_fd,TCIOFLUSH);
return 1;
}
int serial_write(char *buf,size_t size)
{
int writesize = 0;
writesize = write(serial_fd,buf,size);
return writesize;
}
int serial_read(char *buf,size_t size)
{
int readsize = 0;
if (size<=0)
return 0;
readsize = read(serial_fd,buf,size);
printf("serial read: length=%d, packet: ",readsize);
serial_print_buf(buf, readsize);
return readsize;
}
int serial_poll(int timeout)
{
int fd = serial_fd;
fd_set rfds;
struct timeval tv;
int sel_res;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv.tv_sec = timeout/1000;
tv.tv_usec = (timeout % 1000)*1000;
return select(fd + 1, &rfds, NULL,NULL,&tv);
}
编译运行
![图片.png](//file.elecfans.com/web2/M00/87/BB/poYBAGOxgUqAa5gXAADOwVZ5XWY270.png)
运行
将可执行程序拷贝到开发板上,运行程序并传入串口设备名:
![图片.png](//file.elecfans.com/web2/M00/88/42/pYYBAGOxgamAMeSQAAASCUqb7Uk259.png)
同时可以看到串口助手上,不停的有消息打印出来:
![图片.png](//file.elecfans.com/web2/M00/87/BB/poYBAGOxgdWABCRYAAAZRtbH2Eg314.png)
同时接收到的消息也可以通过控制台终端打印出来,如上图的控制台截图。
到此,说明UART的收发都是成功的。
结论
该程序运行后得到了预期的效果,下次将分享更多其它内容,欢迎阅读评论