UART通信
UART0串口调试过程:
1、配置DTS节点
在Z:\rk3399\kernel\arch\arm64\boot\dts\rockchip路径下打开rk3399.dtsi文件,里面已经有UART0相关节点定义,如下所示:
uart0: serial@ff180000 {
compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
reg = <0x0 0xff180000 0x0 0x100>;
clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
clock-names = "baudclk", "apb_pclk";
interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH 0>;
reg-shift = <2>;
reg-io-width = <4>;
pinctrl-names = "default";
pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
status = "disabled"; // 使用UART0时需将“disabled”改为“okay”
};
由于本次调试使用UART0作为调试外接串口,所以需对UART0进行使能配置,即将上述定义中的最后一句status = "disabled"改为status = "okay",从而完成使能配置,将内核重新编译,并将kernel.img和resource.img烧写到开发板中。
2、编写测试代码(见附件ursend.c和receive.c文件)
ursend.c用来发送开发板中的数据,主要包括波特率设置函数set_speed(),奇偶校验设置函数set_parity(),串口数据发送函数serial_send()三个函数;
receive.c用来读取从PC端发送的数据内容。
3、连接硬件
将开发板uart0的TX、RX、GND(分别对应图1中引脚18、16、14)引脚分别和主机串口适配器的RX、TX、GND引脚相连,并PC端使用串口调试助手软件将主机的波特率设置与开发板的波特率一致,同时连接到相应串口,uart0串口所在的GPIO_EXT部分硬件示意图如下:
图1 GPIO_EXT示意图
4、开发板发送数据,PC端读取串口数据
在Z:\rk3399\external路径下新建一个文件夹,命名为uart_send,里面包含两个文件:ursend.c和Android.mk,执行mm指令后得到可执行文件ursend。将可执行文件ursend传送到开发板/system/xbin目录下,在/system/xbin路径下执行./ursend指令后即完成发送操作,图2为在开发板上运行数据发送程序ursend。
图2 开发板发送数据
然后在串口调试助手上就可以看到要接收到的数据内容,如下图所示:
图3 PC端数据接收
注:如果开发板发送端串口和主机接收端串口的波特率已经设置成一致,也可以在开发板终端上使用echo Hello, this is a Seria_Port test! > dev/ttyS1指令,向串口发送数据,并同样能在串口调试助手上显示接收内容。
5、PC端发送数据,开发板读取串口数据
在Z:\rk3399\external路径下新建一个文件夹,命名为uart_receive,里面包含两个文件:receive.c和Android.mk,执行mm指令后得到可执行文件receive。将可执行文件receive传送到开发板/system/xbin目录下,在/system/xbin路径下执行./receive指令后即可开始执行数据接收操作,接着在串口调试助手上发送数据(如图4所示),所发送的内容便会在开发板终端上显示(如图5所示)。
图4 PC端发送数据
图5 开发板数据接收
代码区:
1、receive.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<termios.h>
#include<errno.h>
#include<string.h>
#define TRUE 1
void setTermios(struct termios * pNewtio, int uBaudRate)
{
memset(pNewtio, 0, sizeof(struct termios));
pNewtio->c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;
pNewtio->c_iflag = IGNPAR;
pNewtio->c_oflag = 0;
pNewtio->c_lflag = 0;
pNewtio->c_cc[VINTR] = 0;
pNewtio->c_cc[VQUIT] = 0;
pNewtio->c_cc[VERASE] = 0;
pNewtio->c_cc[VKILL] = 0;
pNewtio->c_cc[VEOF] = 4;
pNewtio->c_cc[VTIME] = 5;
pNewtio->c_cc[VMIN] = 0;
pNewtio->c_cc[VSWTC] = 0;
pNewtio->c_cc[VSTART] = 0;
pNewtio->c_cc[VSTOP] = 0;
pNewtio->c_cc[VSUSP] = 0;
pNewtio->c_cc[VEOL] = 0;
pNewtio->c_cc[VREPRINT] = 0;
pNewtio->c_cc[VDISCARD] = 0;
pNewtio->c_cc[VWERASE] = 0;
pNewtio->c_cc[VLNEXT] = 0;
pNewtio->c_cc[VEOL2] = 0;
}
#define BUFSIZE 512
int main(int argc, char **argv)
{
int fd;
int nread;
int Rlength = BUFSIZE;
int Length = 0;
char buff[BUFSIZE] = {0};
char cMsg[BUFSIZE] = {0};
char *pch = buff;
int i = 0;
struct termios oldtio, newtio;
struct timeval tv;
char *dev =(char *)"/dev/ttyS0";
fd_set rfds;
if ((fd = open(dev, O_RDWR | O_NOCTTY))<0)
{
printf("err: can't open serial port!\n");
return -1;
}
tcgetattr(fd, &oldtio);
setTermios(&newtio, B9600);
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
tv.tv_sec=3;
tv.tv_usec=0;
while (TRUE)
{
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
if (select(1+fd, &rfds, NULL, NULL, &tv)>0)
{
printf("wait.......\n");
if (FD_ISSET(fd, &rfds))
{
nread=read(fd, pch, BUFSIZE-Length);
for(i=Length;i<nread+Length;i++)
{
printf("%c ", buff[i]);
}
Length += nread;
if(Length >= BUFSIZE)
{
printf("######Length<%d> is too long.\n", Length);
return -1;
}
pch += nread;
}
}
else
{
printf("Uart msg is :\n");
printf("%s\n", buff);
memset(buff, 0, BUFSIZE);
pch = buff;
Length = 0;
tv.tv_sec=3;
tv.tv_usec=0;
sleep(1);
}
}
tcsetattr(fd, TCSANOW, &oldtio);
close(fd);
}
2、ursend.c
#include <unistd.h>
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#define max_buffer_size 100
int speed_arr[] = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300,
B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300,
115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, };
/*-----------------------------------------------------------------------------
函数名: set_speed
参数: int fd ,int speed
返回值: void
描述: 设置fd 表述符的串口波特率
*-----------------------------------------------------------------------------*/
void set_speed(int fd ,int speed)
{
struct termios opt;
int i;
int status;
tcgetattr(fd,&opt);
for(i = 0;i<sizeof(speed_arr)/sizeof(int);i++)
{
if(speed == name_arr[i])
{
tcflush(fd,TCIOFLUSH);
cfsetispeed(&opt,speed_arr[i]);
cfsetospeed(&opt,speed_arr[i]);
status = tcsetattr(fd,TCSANOW,&opt);
if(status != 0)
perror("tcsetattr fd:");
return ;
}
tcflush(fd,TCIOFLUSH);
}
}
/*-----------------------------------------------------------------------------
函数名: set_parity
参数: int fd
返回值: int
描述: 设置fd 表述符的奇偶校验
*-----------------------------------------------------------------------------*/
int set_parity(int fd)
{
struct termios opt;
if(tcgetattr(fd,&opt) != 0)
{
perror("Get opt in parity error:");
return -1;
}
opt.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
opt.c_oflag &= ~OPOST;
opt.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
opt.c_cflag &= ~(CSIZE | PARENB);
opt.c_cflag |= CS8;
tcflush(fd,TCIFLUSH); \
if(tcsetattr(fd,TCSANOW,&opt) != 0)
{
perror("set attr parity error:");
return -1;
}
return 0;
}
/*-----------------------------------------------------------------------------
函数名: serial_init
参数: char *dev_path,int speed,int is_block
返回值: 初始化成功返回打开的文件描述符
描述: 串口初始化,根据串口文件路径名,串口的速度,和串口是否阻塞,block为1表示阻塞
*-----------------------------------------------------------------------------*/
int serial_init(char *dev_path,int speed,int is_block)
{
int fd;
int flag;
flag = 0;
flag |= O_RDWR;
if(is_block == 0)
flag |=O_NONBLOCK;
fd = open(dev_path,flag);
if(fd < 0)
{
perror("Open device file err:");
close(fd);
return -1;
}
set_speed(fd,speed);
if(set_parity(fd) != 0)
{
perror("set parity error:");
close(fd);
return -1;
}
return fd;
}
/*-----------------------------------------------------------------------------
函数名: serial_send
参数: int fd,char *str,unsigned int len
返回值: 发送成功返回发送长度,否则返回小于0的值
描述: 向fd描述符的串口发送数据,长度为len,内容为str
*-----------------------------------------------------------------------------*/
int serial_send(int fd,char *str,unsigned int len)
{
int ret;
if(len > strlen(str))
len = strlen(str);
printf("str: %s \n", str);
printf("len: %d \n", len);
ret = write(fd,str,len);
printf("ret: %d \n", ret);
if(ret < 0)
{
perror("serial send err:");
return -1;
}
return ret;
}
int main()
{
int fd;
int ret;
char str[]="Hello, this is a Seria_Port test!";
char buf[100];
printf("buf is: %d \n", sizeof(buf));
fd = serial_init("/dev/ttyS0",9600,1);
if(fd < 0)
{
perror("serial init err:");
return -1;
}
ret = serial_send(fd,str,50);
printf("send %d bytes!\n",ret);
close(fd);
return 0;
}
UART通信的更多相关文章
- [转]UART通信简介
1.前言 UART通信,即通用异步收发传输器(Universal Asynchronous Receiver/Transmitter). 串行通信是指利用一条传输线将资料一位位地顺序传送.特点是通信线 ...
- Arduino与Air800开发板使用UART通信:传输DHT22传感器数据
硬件介绍 Arduino Leonardo在数字引脚0(RX)和1(TX)进行串口通信时是使用“Serial1”,USB的串口通信使用的是“Serial”.在数字引脚0(RX)和1(TX)与USB是相 ...
- ZigBee学习四 无线+UART通信
ZigBee学习四 无线+UART通信 1) 协调器编程 修改coordinator.c文件 byte GenericApp_TransID; // This is the unique messag ...
- ZigBee学习三 UART通信
ZigBee学习三 UART通信 在使用串口时,只需掌握ZigBee协议栈提供的串口操作相关的三个函数即可. uint8 HalUARTOpen(uint8 port,halUARTCfg_t *co ...
- [Intel Edison开发板] 05、Edison开发基于MRAA实现IO控制,特别是UART通信
一.前言 下面是本系列文章的前几篇: [Intel Edison开发板] 01.Edison开发板性能简述 [Intel Edison开发板] 02.Edison开发板入门 [Intel Edison ...
- Verilog之串口(UART)通信
0:起始位,低电平:1~8:数据位:9:校验位,高电平:10:停止位,高电平. 波特率 “9600bps”表示每秒可以传输9600位. 波特率定时计数器由时钟频率除以波特率. 采集1~8位,忽略0.9 ...
- 【C51】UART串口通信
我们常需要单片机和其他模块进行通信,数据传输,常用的方式就是串口通信技术. 常用来 单片机<-->电脑, 单片机<-->单片机之间通信. 串行通信 versus 并行通信 并 ...
- 什么是UART中的FIFO
FIFO是先进先出缓冲区的意思,即串口接收到的数据可以先进入FIFO,不必马上进入中断服务程序接收,这样可以节省CPU时间.对于发送数据也一样可以把要发送的数据一起写入FIFO,串口控制器按照写入的顺 ...
- 基于FPGA的电压表与串口通信(上)
实验原理 该实验主要为利用TLC549采集模拟信号,然后将模拟信号的数字量通过串口发送到PC上上位机进行显示,使用到的TLC549驱动模块在进阶实验已经使用到了,串口模块在基础实验也已经使用到了,本实 ...
随机推荐
- 开源 & 免费使用 & 打包下载自行部署 :升讯威 周报系统
这个周报系统大约写于2015年,缘起当时所带的开发团队需要逐步建立或完善一些项目管理方法. 在调研了网上的诸多项目管理或周报/日报管理系统之后,并没有找到符合当时情况的系统,这里最大的问题不是网上既有 ...
- 浩哥解析MyBatis源码(三)——Transaction事务模块
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6634151.html 1.回顾 之前介绍了Environment环境类,这其实是一个单例类 ...
- C++ 拷贝控制和资源管理,智能指针的简单实现
C++ 关于拷贝控制和资源管理部分的笔记,并且介绍了部分C++ 智能指针的概念,然后实现了一个基于引用计数的智能指针.关于C++智能指针部分,后面会有专门的研究. 通常,管理类外资源的类必须定义拷贝控 ...
- 性能调优之提高 ASP.NET Web 应用性能的 24 种方法和技巧
性能调优之提高 ASP.NET Web 应用性能的 24 种方法和技巧 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对 ...
- IDEA 根据数据库表 生成 Model实体
首先在 Idea中 配置数据源,测试ok(过程略) idea窗口中左下角是否 有显示Persistence 窗口 如果没有显示就要如下方法 添加显示: File - > Project Str ...
- 在SQL Server中用好模糊查询指令LIKE
简介:like在sql中的使用 在SQL Server中用好模糊查询指令LIKE 查询是SQL Server中重要的功能,而在查询中将Like用上,可以搜索到一些意想不到的结果和效果,like的神奇之 ...
- CF CROC 2016 Intellectual Inquiry
题目链接:http://codeforces.com/contest/655/problem/E 大意是Bessie只会英文字母表中的前k种字母,现在有一个长度为m+n的字母序列,Bessie已经知道 ...
- JQuery插件之Animate.css和 jquery-aniview
Animate.css 一款强大的预设css3动画库 简介 animate.css 是一个来自国外的 CSS3 动画库,它预设了抖动(shake).闪烁(flash).弹跳(bounce).翻转(fl ...
- Java泛型知识点:泛型类、泛型接口和泛型方法
有许多原因促成了泛型的出现,而最引人注意的一个原因,就是为了创建容器类. 泛型类 容器类应该算得上最具重用性的类库之一.先来看一个没有泛型的情况下的容器类如何定义: public class Cont ...
- 2017/4/27-Gradle的配置与Spring的下载
Gradle的配置与Spring的下载 1.Gradle 1) 介绍 Gradle是一个基于Groovy的构建工具,类似Maven,但是比其更加简单轻便.它可以自动化地进行软件构建.测试.发布.部署. ...