1. 程式人生 > >海思HI35xx平臺串列埠配置方法

海思HI35xx平臺串列埠配置方法

前言

序列介面簡稱串列埠(通常指COM介面),是採用序列通訊方式的擴充套件介面,其特點是通訊線路簡單,只要一對傳輸線就可以實現雙向通訊,從而大大降低了成本,但傳送速度一般,資料傳輸率為115kbps~230kbps。非同步序列是指UART(Universal Asynchronous Receiver/Transmitter),通用非同步接收/傳送。UART是一個並行輸入轉換為序列輸出的晶片(如MAX232、MAX485等),它們通常整合在主機板上。UART晶片的功能是將TTLL邏輯電平進行轉換,屬於硬體邏輯實現,不需要軟體干涉。UART常用的介面標準有RS-232、RS-485,其中RS-232的傳送距離最大為約15米,最高速率為20kb/s;而RS-485的最大傳輸距離約為1219米,最大傳輸速率為10Mb/s。這兩種介面標準的傳輸速率與傳輸速度差異這麼大,主要是對邏輯電平的規定及訊號傳輸抗干擾能力不一樣導致的,在實際應用中根據需求選用即可。

海思UART

在海思晶片架構中,UART主要是將來自外圍裝置的資料進行串並轉換後傳入內部匯流排,以及將資料進行並串轉換後輸出到外圍裝置,從而實現兩晶片簡的通訊。Hi35XX提供了3個UART單元:

UART0:4線UART,可用於除錯、報警和雲臺控制。

UART1:2線UART,可用於除錯、報警。

UART3:2線UART,可用於除錯、報警。

UART配置:

  1. 支援資料位和停止位的位寬可程式設計。資料位可通過程式設計設定為5/6/7/8位元,停止位可通過過程式設計設定為1bit或2bit。
  2. 支援奇、偶校驗方式或無校驗。
  3. 支援速率可程式設計,支援9600bit/s、14400bit/s、19200bit/s、38400bit/s、57600bit/s、76800bit/s、115200bit/s、230400bit/s、460800bit/s多種速率可選。

海思UART啟用

海思預設只開啟UART0單元作為除錯功能使用,在實際應用中我們常常需要使用UART1、UART2來與外圍裝置對接,以實現串列埠通訊。此時我們就需要配置啟用UART1、UART2單元,這個過程分為3步:

  1. 確保硬體IO口設計及時鐘頻率正常
  2. 檢查UART單元所使用的IO口複用關係
  3. 配置核心,將UART對映為裝置檔案

硬體電路部分按要求佈線連線,一般沒什麼問題,這裡主要講解IO口的複用關係配置及核心配置。

上表是IO口複用關係表,由此可知大多數IO口的預設功能都不是作為UART單元來使用,故需要配置它們的複用關係,可以採用在系統啟動腳本里新增如下命令來配置IO口的複用關係:

himm 0x120F00EC 0x1

himm 0x120F00F0 0x1

……

接下來是配置核心,以實現UART單元對映為linux下的裝置檔案,這裡主要涉及就是海思的裝置樹更改,相對簡單。進入SDK目錄\osdrv\opensource\kernel\linux-3.18.y\arch\arm\boot\dts,找到以下裝置樹檔案。

修改以下內容:

至此海思UART單元配置完成,如果沒有什麼異常,在裝置上的/dev/目錄下回有以下3個裝置檔案出現,接下來軟體操作對此裝置檔案進行程式設計操作即可。

/dev/ttyAMA0

/dev/ttyAMA1

/dev/ttyAMA2

海思UART軟體操作

與其他的linux裝置操作類似,通過open、fcntl、close來實現與UART單元進行操作。在串列埠裝置中,比較特殊的就是串列埠的波特率設定、奇偶校驗、資料位以及停止位的設定了,只有將它們正確設定了才能進行串列埠通訊。下面是一個樣例程式

*
*Function: HI_Serial_Open(int fd,char* ComDevice)  
*Param: fd:file descirbe handle	 Serial Device: /dev/ttyAMA1 /dev/ttyAMA2
*Output: Ok or Fail
*/

int HI_Serial_Open(char* HiSerDevice)  
{  
    int fd;
		
	fd = open(HiSerDevice, O_RDWR|O_NOCTTY|O_NDELAY);  
	if (HI_FALSE == fd)  
	{  
		perror("HiSerial Can't Open Serial HiSerDevice");  
		return(HI_FALSE);  
	}  
	//恢復串列埠為阻塞狀態                                 
	if(fcntl(fd, F_SETFL, 0) < 0)  
	{  
		debugpri("fcntl failed!\n");  
		return(HI_FALSE);  
	}       
	else  
	{  
		debugpri("fcntl=%d\n",fcntl(fd, F_SETFL,0));  
	}  
	//測試是否為終端裝置      
	if(0 == isatty(STDIN_FILENO))  
	{  
		debugpri("standard input is not a terminal device\n");  
		return(HI_FALSE);  
	}  
	else  
	{  
		debugpri("isatty success!\n");  
	}                
	printf("fd->open=%d\n",fd);  
	return fd;  
}  

/*
*Function: HI_Serial_Close(int fd) 
*Param: fd:file descirbe handle	 
*Output: Null
*/

void HI_Serial_Close(int fd)  
{  
	if(fd > 0)
		close(fd); 
	return;	
}  

/*
*Function: HI_Serial_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity) 
*Param1: fd: file descirbe handle	 
*Param2: speed: select the Serial speed.115200,19200,9600...
*Param3: flow_ctrl: if use flow control
*Param4: databits: data bit select
*Param5: stopbits: stopbits select	
*Param5: parity: partiy select	
*Output: Ok or Fail
*/
int HI_Serial_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity)  
{
    /*******
    ********
    ********/  
}

int HI_Serial_Usage(void)
{
    printf("Usage:\n");
    printf("\tmyhicom [-d] <HiSerialDevice> [-s] get netdeviece info [-rw] read or wite select\n");
    printf("\tmyhicom [-h] for more usage\n");
    printf("\tmyhicom [-v] the verson of the sofware\n");
	printf("\tExample:\n\tmyhicom -d /dev/ttyAMA1 -s 115200 -w HiSerial:HelloWorld\n");
}


/*
**Function: main()
**usage: read or write com
**parameter: help
*/
int main ( int argc, char *argv[] )
{
	int cmd;
	int len;
    //extern char *optarg;
    //extern int optind, opterr, optopt;
	char HiSerialDev[32]="/dev/ttyAMA1";
	char sendbuf[1024]={0};
	char recvbuf[1024]={0};
	int SerialSpeed = 115200;
	
	Hi_init_signals();
	if(argc == 1)
	{
		HI_Serial_Usage();		
		exit(0);
	}
	else
	{
		while ((cmd = getopt(argc, argv, ":d:s:rw:hv")) != -1)
		{
			switch (cmd)
			{
				case 'h':
					HI_Serial_Usage();
					break;
				case 'v':
					printf("myHicom --Verson V1.0.0\n");
					break;
				case 'd':
					//printf("catch -d %s \n",optarg);
					memset(HiSerialDev,0,sizeof(HiSerialDev));
					sprintf(HiSerialDev,"%s",optarg);
					printf("myHicom HiSerialDev %s\n",optarg);
					break;
				case 's':
					SerialSpeed = atoi(optarg);
					printf("myHicom speed %d\n",SerialSpeed);
					break;
				case 'r':					
					 debugpri("myHicom read\n");
					 HiSerfd = HI_Serial_Open(HiSerialDev);
					 HI_Serial_Init(HiSerfd,SerialSpeed,0,8,1,'N');
					 while(1)
					 {
						len = HI_Serial_Recv(HiSerfd, recvbuf,sizeof(recvbuf));  
						if(len > 0)  
						{  
							recvbuf[len] = '\0';  
							printf("Hiserial receive data: %s\n",recvbuf);  
							memset(recvbuf,0,sizeof(recvbuf));
							//break;  
						}  
						else  
						{  
							debugpri("Hiserial haven't data receive \n");  
						}  
						sleep(2); 						 
					 };		
					 break;
				case 'w':
					 debugpri("myHicom write %s\n",optarg);
					 HiSerfd = HI_Serial_Open(HiSerialDev);
					 printf("fd = %d device = %s speed = %d\n",HiSerfd,HiSerialDev,SerialSpeed);
					 HI_Serial_Init(HiSerfd,SerialSpeed,0,8,1,'N');					 
					 sprintf(sendbuf,"%s\n",optarg);					 
					 HI_Serial_Send(HiSerfd, sendbuf, strlen(sendbuf)+1); 
					 if(HiSerfd > 0)
						 HI_Serial_Close(HiSerfd);					
					 break;
			    case ':':
                    printf ("option: -%c missing argument. -h for help.\n",(char)optopt);
                    break;
			    case '?':
                    printf("Unknown option: -%c\n",(char)optopt);
                    break;
				default:
					exit(0);
			}
		}	
	}	
	return 0;
}	

總結

串列埠通訊加強了主控晶片與外圍裝置之間的聯絡,通過RS485介面可以實現遠距離通訊。在海思平臺開發中,可以實現球機平臺遠端控制、紅外報警等智慧監控應用。本文主要是總結海思UART單元的應用於配置及提供一個簡單的串列埠通訊樣例實現,樣例程式碼點選此下載。原創不易,轉載說明出處。