实践3 . 给树莓派A20添加串口2

1 硬件

先给出我使用的树莓派的核心板与核心板解出来的串口。

A20主板
A20连接线
CPU串口引脚

再给出底板的串口的原理图:

DVK521串口原理图

所以,结合这两个图,可以将核心板的TX接底板的RX,核心板的RX接底板的TX,能组成一个配对,在电脑上使用usb线,接到开发板上的usb转串口的接口上,就可以完成串口的debug口数据打印到电脑上。

接线

这样,就完成调试串口的基本用法了。

2 增加串口功能

基于1的硬件的说明,可以在sys_config.fex中增加串口2。

[uart_para2]
uart_used           = 1
uart_port           = 2
uart_type           = 2
uart_tx             = port:PI18<3><1>
uart_rx             = port:PI19<3><1>
;uart_rts            = port:PI16<3><1>
;uart_cts            = port:PI17<3><1>

添加串口2功能

由于这几根线并未在底板和核心板中引出来,所以,我们只需要做一个简单的实验去验证:

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就是我们所看到的控制台,所以,直接echo能在串口上显示出来。

3 驱动武汉中显科技的Gpu35btp屏

基于以上说明,只需要在应用层控制Gpu35btp屏即可。
代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


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

运行程序:


root@marsboard:~# ./lcdTest
[3]Open /dev/ttyS1 Ok
^C

可以看到液晶显示内容如下:

液晶内容显示

4 速度测试

在树莓派A20上的main函数中执行如下内容:

    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);
        //输入状态
        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);
    }

测试的时候,发现如下现象:

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

也就是说,隔一段时间有300+ms的延迟。
按照计算来说,应该只有1ms+100*8/115200s的延迟,所以这个现象是不正常的。

而将程序移到linux上,发现的现象如下所示:

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文件中,输入内容:“KERNEL=="ttyUSB[0-9]*",MODE="0666"。

输入配置内容

最终经过一系列测试,发现有几个问题:
1.srand函数尽量不要放到while(1)中,因为这样产生的值有规律性,在液晶面板上看到的现象就是,一个短暂的时间内,值是不变的。这个原因还不得而知,因为没法知道其实现。
2.目前的A20板子的DCD没有使用,所以设置串口参数的时候,不能带O_NDELAY,否则write的时候会报错,尽管这会让液晶屏刷新速率提高,但是不提倡。

你可能感兴趣的:(实践3 . 给树莓派A20添加串口2)