1 硬件
先給出我使用的樹莓派的核心板與核心板解出來的串口。
再給出底板的串口的原理圖:
所以佑颇,結(jié)合這兩個(gè)圖雏吭,可以將核心板的TX接底板的RX,核心板的RX接底板的TX淮悼,能組成一個(gè)配對(duì)咐低,在電腦上使用usb線,接到開發(fā)板上的usb轉(zhuǎn)串口的接口上敛惊,就可以完成串口的debug口數(shù)據(jù)打印到電腦上渊鞋。
這樣,就完成調(diào)試串口的基本用法了瞧挤。
2 增加串口功能
基于1的硬件的說明锡宋,可以在sys_config.fex中增加串口2。
[uart_para2]
uart_used = 1
uart_port = 2
uart_type = 2
uart_tx = port:PI18<3><1><default><default>
uart_rx = port:PI19<3><1><default><default>
;uart_rts = port:PI16<3><1><default><default>
;uart_cts = port:PI17<3><1><default><default>
由于這幾根線并未在底板和核心板中引出來特恬,所以执俩,我們只需要做一個(gè)簡(jiǎn)單的實(shí)驗(yàn)去驗(yàn)證:
root@marsboard:~# echo "hello world" > /dev/ttyS0
hello world
root@marsboard:~#
root@marsboard:~# echo "hello world" > /dev/ttyS1
root@marsboard:~#
root@marsboard:~#
root@marsboard:~#
其中,ttyS0就是我們所看到的控制臺(tái)癌刽,所以役首,直接echo能在串口上顯示出來尝丐。
3 驅(qū)動(dòng)武漢中顯科技的Gpu35btp屏
基于以上說明,只需要在應(yīng)用層控制Gpu35btp屏即可衡奥。
代碼如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <time.h>
#include <sys/time.h>
#include <termios.h>
#define UART_SPEED 115200
#define CHAR_ONE "CLS(0);DS16(0,0,'we need to send command to the uart',4);"
#define LCD_DEV "/dev/ttyS1"
static int fd = -1;
speed_t 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};
static void set_speed(int fd, int speed)
{
int i = 0;
int status = 0;
struct termios opt = {0};
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);
}
}
}
static int set_parity(int fd, int databits, int stopbits, char parity)
{
struct termios opt = {0};
if (tcgetattr(fd, &opt) != 0) {
perror("SetupSerial 1");
return -1;
}
opt.c_cflag &= ~CSIZE;
switch (databits) {
case 7:
opt.c_cflag |= CS7;
break;
case 8:
opt.c_cflag |= CS8;
break;
default:
printf("Unsupported data size");
return -1;
}
switch (parity) {
case 'n':
case 'N':
opt.c_cflag &= ~PARENB; //Clear parity enable
opt.c_iflag &= ~INPCK; //Enable parity checking
break;
case 'o':
case 'O':
opt.c_cflag |= (PARODD | PARENB);
opt.c_iflag |= INPCK; //Disnable parity checking
break;
case 'e':
case 'E':
opt.c_cflag |= PARENB; //Enable parity
opt.c_cflag &= ~PARODD;
opt.c_iflag |= INPCK; //Disnable parity checking
break;
case 'S':
case 's':
opt.c_cflag &= ~PARENB;
opt.c_cflag &= ~CSTOPB;break;
default:
printf("Unsupported parity");
return -1;
}
switch (stopbits) {
case 1:
opt.c_cflag &= ~CSTOPB;
break;
case 2:
opt.c_cflag |= CSTOPB;
break;
default:
printf("Unsupported stop bits\n");
return (-1);
}
if (parity != 'n') {
opt.c_iflag |= INPCK;
}
tcflush(fd,TCIFLUSH);
opt.c_cc[VTIME] = 150;
opt.c_cc[VMIN] = 0;
opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
opt.c_oflag &= ~OPOST;
if (tcsetattr(fd,TCSANOW,&opt)!= 0) {
printf("SetupSerial 3");
return -1;
}
return 0;
}
int main()
{
fd = open(LCD_DEV, O_RDWR);
if (fd < 0) {
printf("Error open %s\n\n", LCD_DEV);
return -1;
}
printf("[%d]Open %s Ok\n", fd, LCD_DEV);
set_speed(fd, UART_SPEED);
set_parity(fd, 8, 1, 'n');
write(fd,CHAR_ONE,sizeof(CHAR_ONE));
while(1) {
}
close(fd);
return 0;
}
運(yùn)行程序:
root@marsboard:~# ./lcdTest
[3]Open /dev/ttyS1 Ok
^C
可以看到液晶顯示內(nèi)容如下:
4 速度測(cè)試
在樹莓派A20上的main函數(shù)中執(zhí)行如下內(nèi)容:
unsigned int lcd_x = 0;
unsigned int pic_x = 0;
unsigned int index = 0;
unsigned int gap = 0;
unsigned int base_gap = 0;
unsigned int base_x = 0;
unsigned int p_value;
struct timeval tm_start;
struct timeval tm_end;
if ((fd = open(uart_inf.path, O_RDWR)) < 0) {
uart_error("Open %s Error, Return", uart_inf.path);
return -1;
}
set_speed(fd, UART_SPEED);
set_parity(fd, 8, 1, 'n');
memset(cmd, 0, UART_BUF_SIZE);
while(1){
usleep(1000);
//輸入狀態(tài)
gettimeofday(&tm_start,NULL);
write(fd,cmd,100);
gettimeofday(&tm_end,NULL);
printf("time eclapse:%ld ms\r\n",tm_end.tv_sec *1000 +
tm_end.tv_usec / 1000 - tm_start.tv_sec * 1000 - tm_start.tv_usec / 1000);
//while(1);
}
測(cè)試的時(shí)候爹袁,發(fā)現(xiàn)如下現(xiàn)象:
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:332 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:331 ms
也就是說,隔一段時(shí)間有300+ms的延遲矮固。
按照計(jì)算來說失息,應(yīng)該只有1ms+100*8/115200s的延遲,所以這個(gè)現(xiàn)象是不正常的档址。
而將程序移到linux上盹兢,發(fā)現(xiàn)的現(xiàn)象如下所示:
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:1 ms
time eclapse:0 ms
time eclapse:2 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:1 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:1 ms
time eclapse:0 ms
time eclapse:1 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:1 ms
time eclapse:6 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:18 ms
time eclapse:0 ms
time eclapse:19 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:17 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:17 ms
time eclapse:0 ms
time eclapse:19 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:19 ms
time eclapse:0 ms
time eclapse:19 ms
time eclapse:0 ms
time eclapse:0 ms
time eclapse:15 ms
time eclapse:0 ms
從這里來看,linux上跑起來的的也不算不正確守伸。
note:
在linux上需要做如下操作:
$ dmesg
$ vi /etc/udev/rules.d/70-ttyusb.rules
在上面的.rules文件中绎秒,輸入內(nèi)容:“KERNEL=="ttyUSB[0-9]*",MODE="0666"。
最終經(jīng)過一系列測(cè)試尼摹,發(fā)現(xiàn)有幾個(gè)問題:
1.srand函數(shù)盡量不要放到while(1)中见芹,因?yàn)檫@樣產(chǎn)生的值有規(guī)律性,在液晶面板上看到的現(xiàn)象就是窘问,一個(gè)短暫的時(shí)間內(nèi)辆童,值是不變的。這個(gè)原因還不得而知惠赫,因?yàn)闆]法知道其實(shí)現(xiàn)把鉴。
2.目前的A20板子的DCD沒有使用,所以設(shè)置串口參數(shù)的時(shí)候儿咱,不能帶O_NDELAY庭砍,否則write的時(shí)候會(huì)報(bào)錯(cuò),盡管這會(huì)讓液晶屏刷新速率提高混埠,但是不提倡怠缸。