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.acodelife.cn

猜你喜欢

转载自blog.csdn.net/wo_Niu123/article/details/85044249
Hi~