Hi3520D 串口使用实例

以下给出了一个源文件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;
			}
		}








你可能感兴趣的:(HI3520D)