以下给出了一个源文件uart.c和makefile文件,在 sdk/mpp/sample/ 底下新建一个文件夹,随便命名,现在命名为UartTest,再把uart.c和makefile拷贝进去,编译
此外,还需要把 libjpeg.so libmpi.so libtde.so 放入核心板 /lib目录下;
所有的文件拷贝完成后 运行 ./uart /dev/ttyAMA2 0
源文件 uart.c
/*
* uart_gkwzt.c
*
* Created on: 2012-10-15
* Author: root
*/
#include /* 标准输入输出定义 */
#include /* 标准函数库定义 */
#include /* Unix标准函数定义 */
#include /* */
#include /* */
#include /* 文件控制定义 */
#include /* PPSIX终端控制定义 */
#include /* 错误号定义 */
#include
#include "mpi_sys.h"
#include "hi_comm_sys.h"
#include "hi_io.h"
#include "hi_tde_api.h"
#define TRUE 1
#define FALSE 0
/*
**********************************************************************************************************
*寄存器基地址映射
**********************************************************************************************************
*/
#define IOCFG_BASE_ADDR 0x200F0000 /* IO口复用寄存器地址空间映射 */
#define GPIO0_BASE_ADDR 0x20150000 /* GPIO0的地址空间映射 */
#define GPIO1_BASE_ADDR 0x20160000 /* GPIO1的地址空间映射 */
#define GPIO2_BASE_ADDR 0x20170000 /* GPIO2的地址空间映射 */
#define GPIO3_BASE_ADDR 0x20180000 /* GPIO3的地址空间映射 */
#define GPIO4_BASE_ADDR 0x20190000 /* GPIO4的地址空间映射 */
#define GPIO5_BASE_ADDR 0x201A0000 /* GPIO5的地址空间映射 */
#define GPIO6_BASE_ADDR 0x201B0000 /* GPIO6的地址空间映射 */
#define GPIO7_BASE_ADDR 0x201C0000 /* GPIO7的地址空间映射 */
#define GPIO8_BASE_ADDR 0x201D0000 /* GPIO7的地址空间映射 */
int speed_arr[] = {B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300};
int name_arr[] = {115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300};
/*
**********************************************************************************************************
*说 明:设置波特率,数据位,停止位,奇偶校验位
*入口参数:
*出口参数:
**********************************************************************************************************
*/
int wzt_SetSerialParameter(int fd, int baudrate, int databits, int stopbits, int parity)
{
struct termios scmTermios ;
if(tcgetattr(fd,&scmTermios) != 0){
perror("Get serial parameter error");
return(FALSE);
}
/* 设置波特率 */
int i = 0;
for(i = 0; i < sizeof(speed_arr)/sizeof(int); i++){
if(baudrate == name_arr[i]){
tcflush(fd, TCIOFLUSH); /* 清除输入输出缓冲区 */
if(0 != cfsetispeed(&scmTermios,speed_arr[i])){ /* 设置输入波特率 成功返回0 否则-1 */
printf("ERROR:Set input Serial baudrate fail\n");
}
if(0 != cfsetospeed(&scmTermios,speed_arr[i])){ /* 设置输出波特率 成功返回0 否则-1 */
printf("ERROR:Set output Serial baudrate fail\n");
}
break;
}
}
/* 设置数据位 */
scmTermios.c_cflag &= ~CSIZE; /* 清零 */
switch (databits){
case 7: scmTermios.c_cflag |= CS7; break;
case 8: scmTermios.c_cflag |= CS8; break;
default:fprintf(stderr,"Unsupported data size\n");return (FALSE);
}
/* 设置停止位 */
switch(stopbits){
case 1: scmTermios.c_cflag &= ~CSTOPB; break;
case 2: scmTermios.c_cflag |= CSTOPB; break;
default:fprintf(stderr,"Unsupported stop bits\n");return (FALSE);
}
/* 奇偶校验位 */
switch (parity){
case 'n':
case 'N':
scmTermios.c_cflag &= ~PARENB;
scmTermios.c_iflag &= ~INPCK;
break;
case 'o':
case 'O':
scmTermios.c_cflag |= (PARODD | PARENB);
scmTermios.c_iflag |= INPCK;
break;
case 'e':
case 'E':
scmTermios.c_cflag |= PARENB;
scmTermios.c_cflag &= ~PARODD;
scmTermios.c_iflag |= INPCK;
break;
case 'S':
case 's':
scmTermios.c_cflag &= ~PARENB;
scmTermios.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr,"Unsupported parity\n");
return (FALSE);
}
if(parity != 'n') scmTermios.c_iflag |= INPCK;
scmTermios.c_cc[VTIME] = 150; /* 非规范模式读取时的超时时间 */
scmTermios.c_cc[VMIN] = 0; /* 非规范模式读取时的最小字符数 */
tcflush(fd, TCIOFLUSH); /* 清除输入输出缓冲区 */
if (tcsetattr(fd,TCSANOW,&scmTermios) != 0){ /* 不等数据传输完毕就立即改变属性 */
perror("Set serial parameter error");
return (FALSE);
}
else{
printf("MSG :Set serial parameter successfully!\n");
}
return (TRUE);
}
/*
**********************************************************************************************************
*说 明:标准输入模式,显示输入字符
*入口参数:
*出口参数:
**********************************************************************************************************
*/
void wzt_DisableTerminalReturn(int fd)
{
struct termios scmTermios;
tcgetattr(fd, &scmTermios);
scmTermios.c_lflag &= ~(ICANON | ECHO);
tcsetattr(fd, TCSANOW, &scmTermios);
}
/*
**********************************************************************************************************
*说 明:gpio 复用寄存器初始化,如果在内核中复用过,在这个地方就不需要配置
*入口参数:
*出口参数:
**********************************************************************************************************
*/
void gpio_cfg_init(void)
{
HI_S32 byregval = 0;
HI_MPI_SYS_SetReg(IOCFG_BASE_ADDR+0x050,0x01); /* 设置GPIO5_1为UART1_RXD */
HI_MPI_SYS_SetReg(IOCFG_BASE_ADDR+0x058,0x01); /* 设置GPIO5_3为UART1_TXD */
HI_MPI_SYS_SetReg(IOCFG_BASE_ADDR+0x05C,0x01); /* 设置GPIO5_4为UART2_RXD */
HI_MPI_SYS_SetReg(IOCFG_BASE_ADDR+0x060,0x01); /* 设置GPIO5_5为UART2_TXD */
HI_MPI_SYS_SetReg(IOCFG_BASE_ADDR+0x0B8,0x01); /* 设置GPIO1_0为UART3_TXD */
HI_MPI_SYS_SetReg(IOCFG_BASE_ADDR+0x0BC,0x01); /* 设置GPIO1_1为UART3_RXD */
}
/*
**********************************************************************************************************
*说 明:主函数
*入口参数:
*出口参数:
*备 注:LED灯闪烁
**********************************************************************************************************
*/
int main(int argc, char** argv, char *envp[])
{
if(argc<3){
printf("*****************************************************\n");
printf("if argv[2] = 0,function: uart test \n");
printf("Usage: filename /dev/ttyAMAn 0\n");
printf("*****************************************************\n");
exit(0);
}
int action = atoi(argv[2]);
if(action==0){
gpio_cfg_init();
printf("Devices:%s\n",argv[1]);
int Ctrlfd = open(argv[1], O_RDWR);
if(-1 == Ctrlfd){
Ctrlfd = 0;
printf("Can't Open Serial Port!\n");
return 0;
}
wzt_SetSerialParameter(Ctrlfd, 115200, 8, 1, 'N');
wzt_DisableTerminalReturn(Ctrlfd);
int n=0,ret;
char buffer[1024];
char cmd[12];
for(n=0;n<10;n++){cmd[n]='0'+n;}cmd[10] = '\r';cmd[11] = '\n';
while(1){
cmd[0]='0'+(n++)%8;
ret = write(Ctrlfd,cmd,12);
int count = read(Ctrlfd,buffer,sizeof(buffer));
if(count>0){
buffer[count] = '\0';
printf("Read:%s\n",buffer);
}
else{
printf("Read:%d\n",count);
}
usleep(20000);
}
return 0;
}
exit(0);
}
Makefile 文件(其实就是在SDK/mpp/sample/ 底下随便找个例程把其中的makefile直接拿来用就行)
# Hisilicon Hi3516 sample Makefile
include ../Makefile.param
#ifeq ($(SAMPLE_PARAM_FILE), )
# SAMPLE_PARAM_FILE:=../Makefile.param
# include $(SAMPLE_PARAM_FILE)
#endif
# target source
SRC := $(wildcard *.c)
OBJ := $(SRC:%.c=%.o)
TARGET := $(OBJ:%.o=%)
.PHONY : clean all
all: $(TARGET)
MPI_LIBS := $(REL_LIB)/libmpi.a
MPI_LIBS += $(REL_LIB)/libhdmi.a
$(TARGET):%:%.o $(COMM_OBJ)
$(CC) $(CFLAGS) -lpthread -lm -o $@ $^ $(MPI_LIBS) $(AUDIO_LIBA) $(JPEGD_LIBA)
clean:
@rm -f $(TARGET)
@rm -f $(OBJ)
@rm -f $(COMM_OBJ)
cleanstream:
@rm -f *.h264
@rm -f *.jpg
@rm -f *.mjp
@rm -f *.mp4
实际工程并不直接使用read函数读取串口数据,使用 select函数 配合,部分代码如下
/*
**************************************************************************************************
**功能描述: 设置串口接受数据为 select 方式
**入口参数: @fd --- -打开的串口文件句柄 -
**出口参数: 返回-1接收错误; 返回0接收超时; 返回>0接收到数据
**-------------------------=------------------------------------
**函数注释: xx_uart_select(fd);
**************************************************************************************************
*/
static int xx_uart_select(int fd)
{
fd_set fs;
struct timeval tmp_time;
/* 清除描述词组fs的全部位 */
FD_ZERO(&fs);
/* 设置描述词组fs中相关fd的位 */
FD_SET (fd, &fs);
/* 设置串口 100ms 等待超时 */
tmp_time.tv_sec = 0;
tmp_time.tv_usec = 100000;
/* 使用select实现串口的多路通信 */
return select(fd+1, &fs, NULL, NULL, &tmp_time);
}
/* 调用方式 */
err = xx_uart_select(uart_ptr->fd);
if(-1 == err)
{
/* 接收错误 */
continue;
}
else if (0 == err)
{
//xxlog_trace(DBG_FALSE, "uart select timeout\n");
/* 接收超时 */
if(0 == new_flag) {continue;}
else {len = 0; }
}
else
{
/* 接收正常 */
len = read(uart_ptr->fd, &recv_ptr[cnt], (RECV_BUFF_LEN - cnt));
cnt += len;
new_flag = 1;
/* 接收缓冲区未满 */
if(RECV_BUFF_LEN != cnt)
{
/* 结束本次循环,从while(1)开始执行 */
continue;
}
}