在嵌入式Linux系统中,UART是最常用的一种接口。UART包含TTL电平的串口和RS232电平的串口,在Digi的开发套件/单板计算机上,您可以找到这两种电平的接口。i.MX6UL支持最高5Mbps的各种标准或非标波特率。
串口通常在Linux中被看成终端设备(tty),用户可以通过/dev下的对应的终端设备描述符来访问串口。注意串行终端只是终端设备中的一种,i.MX系列处理器的串口通常以ttymxcN来命名,我们可以在系统中用ls /dev/tty*来查看可用的串口号。
测试嵌入式板卡上的串口,最简单的方法是用stty工具软件,比如要测试uart1,可以用下面的命令,
stty -F /dev/ttymxc0 115200 echo test > /dev/ttymxc0
上面命令把uart1的波特率设置为115200,然后发送“test”字符串,如果我们连接到电脑的串口上,用终端打开一个115200波特率的串口,就可以接收到相应的字符串。
在程序中访问串口,除了设置串口用了termios结构外,其它可以像访问文件一样进行打开或读写操作,一般的操作流程是:打开串口,串口初始化,读写串口,关闭串口。事实上Linux下的串口编程都是一样的方法,网上有大量的例程,您也可以参考下面这个简单的例程。
/* file name: dey-uart-test.c */
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <signal.h>
volatile int stop=0;
void sigalrm_handler( int sig )
{
stop = 1;
}
int set_interface_attribs(int fd, int speed)
{
struct sigaction sact;
sigemptyset (&sact.sa_mask);
sact.sa_flags = 0;
sact.sa_handler = sigalrm_handler;
sigaction(SIGALRM, &sact, NULL);
alarm(60);
/* Request SIGALRM in 60 seconds */
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
printf("Error from tcgetattr: %s\n", strerror(errno));
return -1;
}
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit characters */
tty.c_cflag &= ~PARENB; /* no parity bit */
tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
/* setup for non-canonical mode */
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tty.c_oflag &= ~OPOST;
/* fetch bytes as they become available */
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 1;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("Error from tcsetattr: %s\n", strerror(errno));
return -1;
}
return 0;
}
void set_mincount(int fd, int mcount)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
printf("Error tcgetattr: %s\n", strerror(errno));
return;
}
tty.c_cc[VMIN] = mcount ? 1 : 0;
tty.c_cc[VTIME] = 5; /* half second timer */
if (tcsetattr(fd, TCSANOW, &tty) < 0)
printf("Error tcsetattr: %s\n", strerror(errno));
}
int main()
{
/*if you need test other port,change portname here */
char *portname = "/dev/ttymxc0";
int fd;
int wlen;
fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
printf("Error opening %s: %s\n", portname, strerror(errno));
return -1;
}
/*baudrate 115200, 8 bits, no parity, 1 stop bit */
set_interface_attribs(fd, B115200);
//set_mincount(fd, 0); /* set to pure timed read */
/* simple output */
wlen = write(fd, "Hello!\n", 7);
if (wlen != 7) {
printf("Error from write: %d, %d\n", wlen, errno);
}
tcdrain(fd); /* delay for output */
/* simple noncanonical input */
while (!stop)
{
unsigned char buf[80];
int rdlen;
rdlen = read(fd, buf, sizeof(buf) - 1);
if (rdlen > 0) {
#ifdef DISPLAY_STRING
buf[rdlen] = 0;
printf("Read %d: \"%s\"\n", rdlen, buf);
#else /* display hex */
unsigned char *p;
printf("Read %d:", rdlen);
for (p = buf; rdlen-- > 0; p++)
printf(" 0x%x", *p);
printf("\n");
#endif
} else if (rdlen < 0) {
printf("Error from read: %d: %s\n", rdlen, strerror(errno));
}
/* repeat read to get full message */
}
close(fd);
exit(0);
}
该例程默认在一分钟内将接收到的字串以十六进制显示,如果您需要看ASCII码,可以在编译选项中加入DISPLAY_STRING,如
~> touch Makefile 输入以下内容: BINARY := dey-uart-test CFLAGS += -Wall -O0 -DDISPLAY_STRING .PHONY: all all: $(BINARY) $(BINARY): dey-uart-test.o .PHONY: clean clean: -rm -f *.o $(BINARY)