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驱动模块在进阶实验已经使用到了,串口模块在基础实验也已经使用到了,本实 ...
随机推荐
- Object-C定时器,封装GCD定时器的必要性!!! (二)
上一篇:Object-C定时器,封装GCD定时器的必要性!!! (一) 上一篇认识了Object-C中的几种定时器,这一篇将Dispatch定时器(GCD定时器)封装起来. p.p1 { margin ...
- PAT乙级练习1001
1001. 害死人不偿命的(3n+1)猜想 (15) 卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反复砍下去, ...
- poptest老李谈Socket
poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-845052 ...
- DC平衡双向控制串行器 转接IC GM8913:LVTTL转FPD-LINK III芯片
1 概述 GM8913型DC平衡双向控制串行器,其主要功能是实现将10或12位并行控制信号和一路时钟信号串行为一路2.8Gbps高速串行数据:同时接收低速通道信号实现模式配对的功能.芯片内部集 ...
- windows环境搭建jira 详解
一.事前准备 1:JDK下载并安装:http://www.oracle.com/technetwork/java/javase/downloads/index.html2:MySQL JDBC连接驱动 ...
- c++设计成员变量可动态调整的动态类结构
本文主要介绍一下如何使用c++设计成员变量可动态调整的抽象动态类结构.首先介绍一下项目中以前使用的一种类结构:静态类结构 1.静态类结构 很多时候,在项目开发中设计类结构时,我们往往有一种简单.直接的 ...
- python 线程与进程
线程和进程简介 应用程序和进程以及线程的关系? 一个应用程序里可以有多个进程,一个进程里可以有多个线程 最原始的计算机是如何运行的? CPU是什么?为什么要使用多个CPU? 为什么要使用多线程? 为什 ...
- web 项目中a标签传值(中文)到后台的乱码问题
web 项目中a标签传值(中文)到后台的乱码问题 jsp页面中的a标签: .............. <c:forEach items="${sellerList }" v ...
- 通过一个小游戏开始接触Python!
之前就一直嚷嚷着要找视频看学习Python,可是一直拖到今晚才开始....好好加油吧骚年,坚持不一定就能有好的结果,但是不坚持就一定是不好的!! 看着视频学习1: 首先,打开IDLE,在IDLE中新建 ...
- sql中 datediff的使用
简介:我们在sql中经常要判断年或者月或者日是否相等,我们可以用datediff函数,使用很方便 datediff:判断年或月或日或周.星期.小时.分钟等的差别数使用格式: DATEDIFF(date ...