HI3521D串口使用 转载自www.acodelife.cn

概述

因项目需要,需要使用的HI3521D的串口1和串口2,并把串口2作为485使用。

海思UART启用

因为海思默认启用uart0 ,作为调试串口。所以我们需要说明的是uart1和uart2。

uart1:

我们进入/dev目录下,发现有uart1存在,编写代码的时候,open /dev/ttyARM1,发现报错No such device or address。我猜,肯定是内核问题,所以内核需要配置,这个稍后再讲。 使用uart1 ,我们需要做些什么? 查看电路图:

连接uart1的引脚,有两个功能,所以,我们先要复用引脚。
在Hi3521DV100_PINOUT_CN.xlsx文件中,找到GPIO6_5和GPIO6_7,如图

我们可以在启动文件中,通过如下方式复用GPIO6_5和GPIO6_7使为uart1引脚使用。

himm 0x120F00F8 0x1
himm 0x120F00FC 0x1

第二步:就是我们将的配置内核了。以实现UART单元映射为linux下的设备文件,这里主要涉及就是海思的设备树更改。
在osdrv/opensource/kernel/linux-3.18y/arch/arm/boot/dts目录下,找到如下文件

打开hi3521d.dtsi文件,修改文件。

aliases {
        fmc = &fmc;
        serial0 = &uart0;
        serial1 = &uart1;
        spi0 = &spi_bus0;
    };

uart1: uart@121090000 {
                compatible = "arm,pl011", "arm,primecell";
                reg = <0x12090000 0x1000>;
                interrupts = <0 7 4>;
                clocks = <&clock HI3521D_UART1_CLK>;
                clock-names = "apb_pclk";
                status = "okay";
            };

保存,然后编译内核,烧写内核,就ok啦。

uart2

对呀uart2,完全就是按照uart1的方式操作,略过。

串口编程

uart1

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
#include <termios.h>



int serial_fd = 0 ;
#define RECE_BUFF_LEN 3000
char serialBuff[RECE_BUFF_LEN] ;

int open_port(int fd,int comport)
{
    long  vdisable;

    fd = open("/dev/ttyAMA2", O_RDWR|O_NOCTTY|O_NDELAY);
    if (-1 == fd)
    {
        perror("Can't Open Serial Port");
        return(-1);
    }else
    {
        printf("%d\n" , fd) ;
    }

     return fd;
}


int set_speed(int fd , int speed)
{
    int birdrate_arr[] = {B115200, B38400, B19200, B9600, B4800,
    B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300};
    int name_arr[] = {115200, 38400, 19200, 9600, 4800, 2400 ,
    1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300};

    struct termios oldtio;
    if  (tcgetattr( fd,&oldtio)  !=  0) {
      perror("SetupSerial 1");
      return -1;
     }
    int i = -1 ;
    for(i = 0 ; i < sizeof(name_arr)/sizeof(name_arr[0]) ; i++)
    {
        if(speed == name_arr[i])
            break ;
    }

    tcflush(fd,TCIFLUSH);
    cfsetispeed(&oldtio, birdrate_arr[i]);
    cfsetospeed(&oldtio, birdrate_arr[i]);
    if((tcsetattr(fd,TCSANOW,&oldtio))!=0)
    {
        perror("com set error");
        return -1;
    }
    tcflush(fd,TCIFLUSH);

    return 0 ;

}


int set_Parity(int fd, int databits, int stopbits, int parity)
{
    struct termios oldtio;
    if  (tcgetattr( fd,&oldtio)  !=  0)
    {
      perror("SetupSerial 1");
      return -1;
    }
    oldtio.c_cflag |= (CLOCAL | CREAD) ;
    switch(databits) //ÉèÖÃÊýŸÝλ
    {
        case 7:
            oldtio.c_cflag &= ~CSIZE ;
            oldtio.c_cflag |= CS7 ;
            break ;
        case 8:
            oldtio.c_cflag &= ~CSIZE ;
            oldtio.c_cflag |= CS8 ;
            break ;
        default:
            perror("Unsupported data size.");
            return -1 ;
    }
    switch(parity)
    {
        case 'n':
        case 'N':
            oldtio.c_cflag &= ~PARENB ;
            oldtio.c_iflag &= ~INPCK ;
            break ;
        case 'o':
        case 'O':
            oldtio.c_cflag |= PARENB ;
            oldtio.c_cflag |= PARODD ;
            oldtio.c_iflag |= INPCK ;
            break ;
        case 's':
        case 'S':
            oldtio.c_cflag &= ~PARENB ;
            oldtio.c_cflag &= ~CSTOPB ;
            oldtio.c_iflag |= INPCK ;
            break ;
        case 'e':
        case 'E':
            oldtio.c_cflag |= PARENB;
            oldtio.c_cflag &= ~ PARODD ;
            oldtio.c_iflag |= INPCK ;
            break ;
        default :
            perror("Unsupported parity.");
            return -1 ;
    }

    switch(stopbits)
    {
        case 1:
            oldtio.c_cflag &= ~CSTOPB ;
            break ;
        case 2:
            oldtio.c_cflag |= CSTOPB ;
            break ;
        default :
            perror("Unsupported stopbits.");
            return -1 ;
    }

    oldtio.c_cflag |= (CLOCAL|CREAD) ;
    oldtio.c_iflag &= ~(ICANON|ECHO|ECHOE|ISIG) ;

    oldtio.c_oflag &= ~OPOST ;
    oldtio.c_oflag &= ~(ONLCR|OCRNL) ;

    oldtio.c_iflag &= (ICRNL | INLCR) ;
    oldtio.c_iflag &= ~(IXON|IXOFF|IXANY) ;


    tcflush(fd,TCIFLUSH);
    oldtio.c_cc[VTIME] = 0 ;
    oldtio.c_cc[VTIME] = 0 ;

    /*raw model*/
    oldtio.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);
    oldtio.c_oflag  &= ~OPOST;

    oldtio.c_iflag &= ~(INLCR|IGNCR|ICRNL);
    oldtio.c_iflag &= ~(ONLCR|OCRNL);

    oldtio.c_oflag &= ~(INLCR|IGNCR|ICRNL);
    oldtio.c_oflag &= ~(ONLCR|OCRNL);
    if((tcsetattr(fd,TCSANOW,&oldtio))!=0)
    {
        perror("com set error");
        return -1;
    }
    return 0 ;


}


int init_serial_port()
{
    int serial_fd ;
    if((serial_fd=open_port(serial_fd,1))<0){//Žò¿ªŽ®¿Ú
        perror("open_port error");
        return 0;
    }

    int speed = 9600; //115200 ;
    if(set_speed(serial_fd,speed) < 0)
    {
        perror("set speed error");
        return 0 ;
    }
    int databits = 8 ;
    int stopBits = 1 ;
    if(set_Parity(serial_fd,databits , stopBits , 'N') < 0)
    {
        perror("set_Parity error");
        return 0 ;
    }

    return serial_fd ;
}


void serial_port_pthread()
{

    while(1)
    {
        usleep(400) ;
        if(serial_fd <= 0)
        {
            printf("get_serial_fd() <= 0\n") ;

            continue ;
        }

        {
            char buff[RECE_BUFF_LEN] ;


            int ret = read(serial_fd , buff , RECE_BUFF_LEN) ;
            if(ret <= 0)
            {
                //printf("serial read error!\n") ;
                continue ;
            }else
            {
                int i = 0 ;
                for( i = 0 ; i < ret ; i++)
                   printf("%x,", buff[i]) ;
                   printf(" end!\n") ;

            }

        }
    }
}


int main(void)
{
    printf("Hello World!\n");


    if((serial_fd = init_serial_port()) ==-1)
           printf("init_serial_port error!\n") ;

    serial_port_pthread();

    return 0;
}

uart2串口编程

对于uart2,我们是用来作为RS485的,所以,需要有一个使能信号。如图:

RE脚连接到海思是GPIO0_7引脚,图就不截了。

所以,我们需要设置GPIO0_7为IO输出,配置步骤如下:
通用输入输出
每个管脚可以配置为输入或者输出,具体步骤如下:
步骤 1. 参考“管脚复用控制寄存器”配置管脚的相应位,使能需要使用的GPIO 管脚功能。
步骤 2. 配置寄存器GPIO_DIR,选择GPIO 是作为输入还是输出。
步骤 3. 当配置成输入管脚时,读取GPIO_DATA 寄存器可查看输入信号值;当配置成输出管
脚时,通过向GPIO_DATA 寄存器写入输出值可控制GPIO管脚输出电平。

配置GPIO_DIR

GPIO0基地址(0x1215_0000)+GPIO_DIR偏移地址(0x400),设置为何值?

从图可以看出,我们设置的是GPIO0_7的DIR,所以第8位设置为1,即himm 0x12150400 0x80

配置GPIO_DATA ,因为DATA的配置跟DIR差不多,所以不详细的说。GPIO_DATA 地址:0x121503FC

所以,uart2的编程跟uart1编程区别就在,需要发送数据的时候,DATA拉高,读取数据的时候DATA拉低。

system("himm  0x121503fc 0xff");
usleep(250);
write(serial_fd , buff , ret) ;
system("himm  0x121503fc 0x7f");

以上是我的小见解,如有错误,多多指教

猜你喜欢

转载自www.cnblogs.com/new-ass/p/11309619.html