海思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配置:
- 支援資料位和停止位的位寬可程式設計。資料位可通過程式設計設定為5/6/7/8位元,停止位可通過過程式設計設定為1bit或2bit。
- 支援奇、偶校驗方式或無校驗。
- 支援速率可程式設計,支援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步:
- 確保硬體IO口設計及時鐘頻率正常
- 檢查UART單元所使用的IO口複用關係
- 配置核心,將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單元的應用於配置及提供一個簡單的串列埠通訊樣例實現,樣例程式碼點選此下載。原創不易,轉載說明出處。