引言
UART是一种常用的串行通信接口,常用于单片机和外围设备之间进行数据传输。Linux系统下提供了丰富的串口通信工具和库函数,可以非常方便地进行串口通信测试和开发。本文将介绍Linux系统下的UART测试程序,详细讲解其原理、实现和使用方法。
一、UART简介
UART(Universal Asynchronous Receiver/Tranitter)是一个通用异步串行接口,它可以支持异步传输和少量同步传输。在UART串口通信中,数据以字节为单位通过串行通信线路进行传输,通信线路包括一条单向数据线(TX)和一条单向接收线(RX),同时还有一个以上的控制线(如CTS、RTS等)。
在UART通信中,数据传输是以一定波特率进行的。波特率表示传输速率,即单位时间内传输的比特数。例如,对于波特率为9600 bps的UART串口通信,每秒可以传输9600个比特(即9600/8=1200个字节)的数据。波特率越高,传输速度越快,但是传输距离越短,误码率越高。
二、UART测试程序原理
Linux系统下提供了多种测试UART串口通信的工具和库函数,例如minicom、stty、termios等。这些工具和库函数都是基于系统调用函数编写的,主要目的是为了方便用户进行串口通信的测试和开发。而本文将介绍一种基于C语言的UART测试程序,它可以直接调用串口设备文件的读写函数进行数据的收发。具体原理如下:
1. 打开串口设备文件
在Linux系统下,每个串口都会被表示为一个设备文件,例如/dev/ttyS0、/dev/ttyS1等。在UART测试程序中,首先需要打开指定的串口设备文件,以便后续进行数据的读写。
2. 设置串口参数
在进行串口通信时,需要设置一些参数,如波特率、数据位、校验位、停止位等。通过串口控制寄存器,可以对这些参数进行设置。在UART测试程序中,可以通过调用tcgetattr和tcsetattr等函数设置指定的串口参数。
3. 发送数据
在UART测试程序中,可以通过调用write函数向串口发送数据。write函数会将指定的数据写入串口设备文件,发送给外部设备。
4. 接收数据
在UART测试程序中,可以通过调用read函数从串口接收数据。read函数会从串口设备文件中读取数据,存储到缓冲区中,供后续进行处理。
5. 关闭串口设备文件
在串口通信完成后,需要关闭打开的串口设备文件,以便下次进行访问。
三、UART测试程序实现
基于上述原理,可以编写C语言程序实现UART测试功能。下面给出一段完整的UART测试程序代码:
#include
#include
#include
#include
#include
int set_interface_attribs (int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
perror (“error %s from tcgetattr”);
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for miatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn’t block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
perror (“error %s from tcsetattr”);
return -1;
}
return 0;
}
void set_blocking (int fd, int should_block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
perror (“error %s from tggetattr”);
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
if (tcsetattr (fd, TCSANOW, &tty) != 0)
perror (“error %s setting term attributes”);
}
int mn()
{
char buf[256];
int fd = open(“/dev/ttyS0”, O_RDWR | O_NOCTTY | O_SYNC);
if (fd
{
perror(“error opening”);
return -1;
}
set_interface_attribs(fd, B9600, 0); // set speed to 9600 bps, 8n1 (no parity)
set_blocking(fd, 0); // set no blocking
write(fd, “hello\n”, 6); // send 6 character greeting
usleep ((6 + 25) * 100); // sleep enough to tranit the 6 plus
// receive 25: approx 100 uS per char tranit
int n = read(fd, buf, sizeof buf); // read up to 100 characters if ready to read
printf(“received %d bytes: %s\n”, n, buf);
close(fd);
return 0;
}
本段代码中,首先通过调用open函数打开指定的串口设备文件(/dev/ttyS0),然后通过tcgetattr和tcsetattr函数设置串口参数(波特率为9600,数据位为8位,校验位为无,停止位为1位)。通过write函数向串口发送一条数据“hello\n”,并通过read函数从串口接收数据,存储到buf缓冲区中。
在进行编译时,需要将此代码保存为uart_test.c文件,并通过gcc命令进行编译:
$ gcc uart_test.c -o uart_test
四、UART测试程序使用方法
在Linux系统上,进行UART测试时需要先连接好串口线,将串口设备连接到计算机上。然后,执行上述编译好的uart_test程序即可进行测试。如果测试通过,可以在终端上看到接收到的数据。
需要注意的是,在Linux系统下,串口设备文件的权限可能需要进行修改才能进行读写操作。可以通过chmod命令进行修改,例如:
$ sudo chmod 666 /dev/ttyS0
这条命令将/dev/ttyS0串口设备文件的权限设置为666,即所有用户都有读写权限。
结论
相关问题拓展阅读:
(1)试验目的:掌握通过文件系统操作UART设备的方烂槐法.
(2)在linux中,所有设备都是以文件的形式被打开并进行读/写慎橘操作的,本饥孝友试验中使用POSIX兼容的文件操作接口函数对底层设备进行操作.其中,POSIX是Portable Operating System Interface for UNIX的首字母缩写,是一套IEEE和ISO标准.
就是把串口的波特率提上去,硬件环境呢,就是采用飞凌的TE2440-II(比较古老了,大家勿喷)操作系统是linux2.6.28,大家都知道,正常情况下,Linux下串口波特率更高到115200,因为我们特殊需要的原因,需要把波特率提高到至少460800,当然最理想的结果就是波特率达到921600,大的背景就是这个样子了。
然后先考究硬件,看看在硬件上到底能不能满足我们的要求,主控芯片S3C2440,在UART一章说在系统时钟下,波特率更高可达115200,然后注释中说如果Pclk达到60M,可以实现921600,我就按他说的,将主频提高,顺便将pclk提高到了60M,发现921600根本实现不了,230400波特率虽然能通,但是错误率很高,根本无法用,然后我又尝试着将Pclk提高到了70M,通过这种饮鸩止渴的方式,波特率可以提高到230400并且稳定传输,但是更高的波特率则无法实现,而Pclk不能无限提高,因为我们开发板还连接了触摸屏,在Pclk70M的情况下,触摸屏经常重启,说明这个方案不可行,所以就pass掉了,下面简单说一下我怎么更改的系统时钟Fclk,Hclk,Pclk。这三个时钟的关系以及计算方法我就不赘述了,我主要参考博客
进行修改
1)首先找到bootloader中 INC文件夹下的Option.inc文件,打开以后,找到如下代码段,这段代码就是主频400M时对应的M,P和S值设置,需要更改主频的话虚野更改其中相应的数值几个(后来我发现,其实这个地方不改也行,因为最终起作用的是第二步)
CLKDIV_VAL EQU5
;1:4:8
M_MDIV EQU
127 ;127
M_PDIV EQU
2 ;2
M_SDIV EQU
1 ; 2440A
|
M_SDIV EQU
0 ; 2440X
>
>
2)找到u2440mon.c,然后在main()函数中找到如下代码,修改case2中的mpll_val = (92flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
else
quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud);
/* check to see if we need to change clock source */
if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
s3c24xx_serial_setsource(port, clksrc);
if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
clk_disable(ourport->baudclk);
ourport->baudclk = NULL;
}
clk_enable(clk);
ourport->clksrc = clksrc;
ourport->baudclk = clk;
}
其中,uart_get_baud_rate()函数用于计算出上位机程序到设置的波特率的值,经我调试得知,上位机波特率从2400到921600都可以被准确的计算出来;所以这个函数跳过,然后看最后那个if语句,这个语句的作用是产看目前的时钟源是否与设置的时钟源相同,如果不相同,则按照设置的时钟源进行更改,这里面还涉及linux下的关于管理时钟的一个结构体clk结构体,参照博客
以及
我找到了linux下的mach-dk2440.c这个文件,这个文件中定义了串口所用的clk结构体,这也是linux系统启动时对串口的初始化配置结构体都在这,但是我更改过这个地方,让他初始化配置是选择fclk作为串口的时钟源,但是我发现这并没有效果,所以继续寻找中。
这样就剩下一个函数可以考虑了,s3c24xx_serial_getclk(),进入这个函数你会发现,这个函数是对串口时钟及波特率一个全面的配置,进入这个函数中,就有个结构体tmp_clksrc,这个结构体很关键,他的内容如下:
static struct s3c24xx_uart_clksrc tmp_clksrc = {
.name = “pclk”,
.min_baud
= 0,
.max_baud
= 0,
.divisor
= 1,
};
从这个名字中就可以看出,它把串口的时钟源内定成为了pclk,这也是罪魁祸首,但是当我把name更改为fclk时,整个系统就无法启动了,包括前面说的更改mach-dk2440.c中初始化配置,也是无法启动,后来在配置串口是做了一个判断,当波特率低于202300时,才有系统源配置不变,当波特率高于202300时,不在采用tmp_clksrc这个结构体,而是采用我自己定义的一个结构体,当然就是把name改成fclk,发现虽然只是能够更改 里面部分参数的时钟源,而正在的时钟源还是pclk,说明我的更改根本么有生效,由于这个linux调用太庞杂了,我就抱着试试看的态度,也是没有办法的办法,在配置完串口时钟的代码之后,添加了如下几行代码,直接更改S3C2440的寄存器,我知道这样做是很不“道德”的,而且很容易引起系统混乱,但是我只是这么试试,没想到还真的有用。
在 samsung.c文件中添加
if (baud >=)
{
printk(“baud >=@samsung.c\n”);
__raw_writel(0x1fc5,S3C24XX_VA_UART0 + S3C2410_UCON);
__raw_writel(0x0fc5,S3C24XX_VA_UART1 + S3C2410_UCON);
__raw_writel(0x8fc5,S3C24XX_VA_UART2 + S3C2410_UCON);
__raw_writel(32,S3C24XX_VA_UART0 + S3C2410_UCON+0x24);//保证控制台的波特率还是115200用于显示
__raw_writel(3,S3C24XX_VA_UART1 + S3C2410_UCON+0x24);//921600
//__raw_writel(3,S3C24XX_VA_UART1 + S3C2410_UCON+0x24);
}
上面这段代码经我多次试验得到的,因为一开始用的系统主时钟fclk为400M,这样算出来UBRDIV1分频应该为3,但是这样的话错误率比较高,还是导致无法传输,至此我终于明白手册上为什么说pclk在60M 可以实现921600了,因为用60M时钟计算的话,分频UBRDIV1为3.069,最接近整数3,所以在这个错误率下可以实现921600的波特率传输,所以我将系统时钟fclk设置为420M,其中MDIV=97,PDIV=1,SDIV=1,而ucon0=0x1fc5,ucon1=0x0fc5,ucon2=0x8fc5,这样n=1+6=7,所以串口的时钟源为fclk/n=60M,可以得到精确的921600波特率,所以实现我刚开始的目标,其实要实现其他的波特率也可以,比如460800,计算后主时钟fclk(尽量算出的分频UBRDIV1最贴近整数),然后就可以实现了。
在这还有个小想法,提高串口波特率,还可以使用USB转串口,因为USB转串口可以实现921600,而linux中以及集成了USB转串口的驱动,只需要在调用串口的那个open函数中改为调用USB转串口的节点即可,当然,这个方案我没有试,因为我们就一个USB口,而且还被占用了,所以希望有需要的朋友可以试一下。
用 stty 命令 (使用前请确认你的终端设备确实支持这个速率), 比如
stty# 设置 baud rate 到
stty speed # 查看当前终端 baud rate
# 如果不是设置当洞销前终端段游,则用下面的命令纳燃游设置指定终端设备
stty -F /dev/
88、四时田园杂兴范大成
88、四时田园杂兴 范大成
linux uart测试程序的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux uart测试程序,Linux系统下的UART测试程序详解,linux下uart的文件节点是怎样创建的,如何在S3C2440上linux操作系统下将串口的波特率提高以致921600的信息别忘了在本站进行查找喔。
创新互联服务器托管拥有成都T3+级标准机房资源,具备完善的安防设施、三线及BGP网络接入带宽达10T,机柜接入千兆交换机,能够有效保证服务器托管业务安全、可靠、稳定、高效运行;创新互联专注于成都服务器托管租用十余年,得到成都等地区行业客户的一致认可。
当前标题:Linux系统下的UART测试程序详解(linuxuart测试程序)
本文URL:http://www.shufengxianlan.com/qtweb/news35/476235.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联