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;
}

 

转载于:https://www.cnblogs.com/dq23578/p/6774179.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值