UART通信

时间:2021-10-01 04:05:18

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部分硬件示意图如下:

UART通信

                  图1 GPIO_EXT示意图

4、开发板发送数据,PC端读取串口数据
在Z:\rk3399\external路径下新建一个文件夹,命名为uart_send,里面包含两个文件:ursend.c和Android.mk,执行mm指令后得到可执行文件ursend。将可执行文件ursend传送到开发板/system/xbin目录下,在/system/xbin路径下执行./ursend指令后即完成发送操作,图2为在开发板上运行数据发送程序ursend。

UART通信

               图2 开发板发送数据

然后在串口调试助手上就可以看到要接收到的数据内容,如下图所示:

UART通信

                    图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所示)。

UART通信

                     图4 PC端发送数据

UART通信

                        图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通信的更多相关文章

  1. &lbrack;转&rsqb;UART通信简介

    1.前言 UART通信,即通用异步收发传输器(Universal Asynchronous Receiver/Transmitter). 串行通信是指利用一条传输线将资料一位位地顺序传送.特点是通信线 ...

  2. Arduino与Air800开发板使用UART通信:传输DHT22传感器数据

    硬件介绍 Arduino Leonardo在数字引脚0(RX)和1(TX)进行串口通信时是使用“Serial1”,USB的串口通信使用的是“Serial”.在数字引脚0(RX)和1(TX)与USB是相 ...

  3. ZigBee学习四 无线&plus;UART通信

    ZigBee学习四 无线+UART通信 1) 协调器编程 修改coordinator.c文件 byte GenericApp_TransID; // This is the unique messag ...

  4. ZigBee学习三 UART通信

    ZigBee学习三 UART通信 在使用串口时,只需掌握ZigBee协议栈提供的串口操作相关的三个函数即可. uint8 HalUARTOpen(uint8 port,halUARTCfg_t *co ...

  5. &lbrack;Intel Edison开发板&rsqb; 05、Edison开发基于MRAA实现IO控制,特别是UART通信

    一.前言 下面是本系列文章的前几篇: [Intel Edison开发板] 01.Edison开发板性能简述 [Intel Edison开发板] 02.Edison开发板入门 [Intel Edison ...

  6. Verilog之串口&lpar;UART&rpar;通信

    0:起始位,低电平:1~8:数据位:9:校验位,高电平:10:停止位,高电平. 波特率 “9600bps”表示每秒可以传输9600位. 波特率定时计数器由时钟频率除以波特率. 采集1~8位,忽略0.9 ...

  7. 【C51】UART串口通信

    我们常需要单片机和其他模块进行通信,数据传输,常用的方式就是串口通信技术. 常用来 单片机<-->电脑,  单片机<-->单片机之间通信. 串行通信 versus 并行通信 并 ...

  8. 什么是UART中的FIFO

    FIFO是先进先出缓冲区的意思,即串口接收到的数据可以先进入FIFO,不必马上进入中断服务程序接收,这样可以节省CPU时间.对于发送数据也一样可以把要发送的数据一起写入FIFO,串口控制器按照写入的顺 ...

  9. 基于FPGA的电压表与串口通信(上)

    实验原理 该实验主要为利用TLC549采集模拟信号,然后将模拟信号的数字量通过串口发送到PC上上位机进行显示,使用到的TLC549驱动模块在进阶实验已经使用到了,串口模块在基础实验也已经使用到了,本实 ...

随机推荐

  1. 【前端】提取URL中的各个GET参数

    /**************************** * 有这样一个URL:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xx ...

  2. kubernetes多节点部署解析

    注:以下操作均基于centos7系统. 安装ansible ansilbe可以通过yum或者pip安装,由于kubernetes-ansible用到了密码,故而还需要安装sshpass: pip in ...

  3. Remove Nth Node From End of List &lbrack;LeetCode&rsqb;

    Given a linked list, remove the nth node from the end of list and return its head. For example, Give ...

  4. SPOJ 3937 - Wooden Sticks 最长上升子序列LIS

    给了n个(n<=5000)木棍的长度hi与宽度wi(均小于10000),现在机器要打磨这些木棍,如果相邻连个木棍hi<=hj并且wi<=wj就不需要调整机器,问如何排序使得机器调整的 ...

  5. 深入浅出数据结构C语言版(1)——什么是数据结构及算法

    在很多数据结构相关的书籍,尤其是中文书籍中,常常把数据结构与算法"混合"起来讲,导致很多人初学时对于"数据结构"这个词的意思把握不准,从而降低了学习兴趣和学习信 ...

  6. UBIFS文件系统介绍

    1.  引言 UBIFS,Unsorted Block Image File System,无排序区块图像文件系统.它是用于固态硬盘存储设备上,并与LogFS相互竞争,作为JFFS2的后继文件系统之一 ...

  7. Python实现Plugin

    1. Plugin与Python 插件的历史最早可追溯至1970年代,它是一种程序组件,通过和应用程序的互动,为应用程序增加一些所需要的特定的功能[维基].插件允许第三方开发者对已有的程序功能进行扩展 ...

  8. Cocoa 集合类型:NSPointerArray,NSMapTable,NSHashTable

    iOS 中有很多种集合类型,最为常见的可能就 NSArray.NSDictionary.NSSet,但其实还有 NSPointerArray.NSMapTable.NSHashTable 等类型,虽然 ...

  9. mybatis中&commat;Param的使用

    @Param:当映射器方法需要多个参数时,这个注解可以被用于:给映射器方法中的每个参数来取一个名字.否则,多参数将会以它们的顺序位置和SQL语句中的表达式进行映射,这是默认的.    语法要求:若使用 ...

  10. MediaRecorder实现微信、QQ、人人、易信等语音录制功能工具&colon;MediaUtilAPI

    本文介绍使用MediaRecorder进行录制音频.录制视频学习,熟悉MediaRecorder执行流程,通过简单的Demo结合解释运行效果,最后封装MediaRecorder的API工具,实现常见比 ...