1 引言 近年來(lái),隨著(zhù)視頻技術(shù)發(fā)展,網(wǎng)絡(luò )穩定性能快速提高,視頻監控需求越來(lái)越大,其應用領(lǐng)域也越來(lái)越廣泛。社會(huì )的發(fā)展,汽車(chē)增量不斷增多,道路上各種違章的車(chē)輛也逐漸增多,為了構建一個(gè)平安交通和智能交通,視頻監控系統在交通行業(yè)的應用也越來(lái)越多,為了能全方位的對高速公路進(jìn)行監控,視頻監控的高速球也應用越來(lái)越廣泛。 本文將研究詳細分析I2C的工作原理和通信協(xié)議和Linux的I2C總線(xiàn)驅動(dòng)程序,設計一個(gè)應用在高速公路視頻監控的基于I2C云臺電機驅動(dòng)系統,為高速公路的全方位視頻監控提供一個(gè)設計方案。 2 高速公路視頻監控系統以及云臺電機整體設計 本研究課題的高速公路高清視頻監控系統采用TI公司的TMS320DM368,DM368 是一款面向多媒體技術(shù)應用的高性能芯片,功能強大,集成了ARM926EJ-S內核、硬件編碼協(xié)處理引擎( HDVICP)、圖像處理子系統( VPSS)。DM368頻率高達 432MH,支持多格式解碼、多速率以及高清多通道功能,最高可以支持H.264編碼 1080P格式 30幀/s的速度,而且還可提供多種獨立式音頻、語(yǔ)音以及高清視頻編解碼器(H.264)。該處理器有I2C總線(xiàn)等外圍接口等,其中ARM9運行開(kāi)源、性能穩定安全Linux 嵌入式操作系統。 視頻監控系統中云臺電機控制的設計采用DM368的I2C總線(xiàn)接口,設計基于A(yíng)RM9的I2C云臺電機,完成驅動(dòng)程序設計和應用程序設計,以及應用程序控制電機轉動(dòng),應用于視頻監控系統中,達到全方位的高速公路視頻監控。 3 I2C硬件構成和通信協(xié)議 I2C總線(xiàn)是由雙向數據線(xiàn)和時(shí)鐘線(xiàn)構成的二線(xiàn)制串行總線(xiàn),總線(xiàn)采用主從雙向通信,即總線(xiàn)上在某一時(shí)刻只有一個(gè)主設備總線(xiàn)上的其他設備都作為從設備,任何能夠進(jìn)行發(fā)送和接收的設備都可以成為主設備,但是在同一時(shí)間內只能有一個(gè)設備作為主設備,通常為處理器,其他器件作為從設備與主設備進(jìn)行通信,采用唯一的I2C地址識別。 圖1 I2C時(shí)序 如圖1I2C的工作時(shí)序圖所示,I2C總線(xiàn)在傳送數據過(guò)程中使用了三種信號。(1)開(kāi)始信號:SCL為高電平時(shí),SDA由高電平向低電平跳變,表示將要開(kāi)始傳送數據;(2)應答信號:從設備在接收到1個(gè)字節數據后向主設備發(fā)出一個(gè)低電平脈沖應答信號,表示已收到數據,主設備根據從設備的應答信號做出是否繼續傳輸數據的操作(I2C總線(xiàn)每次數據傳輸時(shí)字節數不限制,但是每發(fā)送都要有一個(gè)應答信號);(3)結束信號:為低電平時(shí)由低電平向高電平跳變,表示數據傳送結束。 總線(xiàn)具體的通信工作原理:主設備首先發(fā)出開(kāi)始信號,接著(zhù)發(fā)送的1個(gè)字節的數據,其由高7位地址碼和最低1位方向位組成(方向位表明主設備與從設備間數據的傳送方向)。系統中所有從設備將自己的地址與主設備發(fā)送到總線(xiàn)上的地址進(jìn)行比較,如果從設備地址與總線(xiàn)上的地址相同,該設備就是與主設備進(jìn)行數據傳輸的設備。接著(zhù)進(jìn)行數據傳輸,根據方向位,主設備接收從設備數據或發(fā)送數據到從設備。當數據傳送完成后,主設備發(fā)出一個(gè)停止信號,釋放I2C總線(xiàn),然后所有從設備等待下一個(gè)開(kāi)始信號的到來(lái)。 4 I2C的Linux和ARM驅動(dòng)設計 (1)Linux2.6.32的I2C驅動(dòng)分析。 I2C由主設備和從設備構成,通信上通過(guò)識別I2C地址進(jìn)行通信,即可以存在多個(gè)i2c adapter適配器和多個(gè)外設i2c device,Linux的I2C驅動(dòng)采用分層設計實(shí)現的思想,層與層之間不存在耦合,增加adapter和增加device不會(huì )影響其他驅動(dòng),具體分層如下。 第一層:提供i2c adapter的硬件驅動(dòng),探測、初始化i2c adapter(如申請i2c地址和中斷號),驅動(dòng)處理器控制的i2c adapter在硬件上產(chǎn)生信號(start、stop、ack)以及處理i2c中斷,涉及圖2中的硬件實(shí)現層。 第二層:提供i2c adapter的algorithm,用具體適配器的xxx_xfer()函數來(lái)填充i2c_algorithm的master_xfer函數指針,并把賦值后的i2c_algorithm,再賦值給i2c_adapter的成員指針,主要涉及圖2中訪(fǎng)問(wèn)抽象層、i2c核心層。 第三層:實(shí)現i2c設備驅動(dòng)中的i2c_driver接口,用具體的i2c device設備的i2c_add_driver ()、i2c_del_driver ()方法賦值給i2c_driver的成員函數指針,采用Probe探尋方式實(shí)現設備device與總線(xiàn)的掛接,涉及圖2中的driver驅動(dòng)層,此層是本文實(shí)現的驅動(dòng)部分。 第四層:實(shí)現i2c設備所對應的具體device的驅動(dòng),i2c_driver只是實(shí)現設備與總線(xiàn)的掛接,掛接在總線(xiàn)上的設備千差萬(wàn)別的,所以要實(shí)現具體設備device的write()、 read()、ioctl()等方法,賦值給file_operations,然后注冊字符設備,涉及圖2中的driver驅動(dòng)層,此層是本文實(shí)現的驅動(dòng)部分。 第一層和第二層又叫i2c總線(xiàn)驅動(dòng)(bus driver),第三層和第四層屬于i2c設備驅動(dòng)(device driver)。在Linux驅動(dòng)架構中,不需要再開(kāi)發(fā)總線(xiàn)驅動(dòng),因為L(cháng)inux內核幾乎集成所有總線(xiàn)驅動(dòng),驅動(dòng)設計主要是實(shí)現第三層和第四層的設備驅動(dòng)。 圖2 I2c驅動(dòng)架構圖 (2)云臺電機驅動(dòng)設計 根據Linux2.6.32的驅動(dòng)分層設計,驅動(dòng)的第一層和第二層在Linux-2.6.32中以及集成了成熟驅動(dòng),分別位于Linux源代碼目錄下的\drivers\i2c\i2c-core.c 和\drivers\i2c\busses\davinci.c中,本文重點(diǎn)講述第三層和第四層驅動(dòng)程序的設計。 驅動(dòng)設計采用字符設備方式來(lái)實(shí)現,motor_I2C_devInit()和motor_I2C_devExit()實(shí)現驅動(dòng)的初始化以及退出,初始化最后調用cdev_add()實(shí)現字符設備的添加,添加過(guò)程中通過(guò)完善file_operations的結構體,填充了 .open = I2C_devOpen, .release = I2C_devRelease,.ioctl = I2C_devIoctl三個(gè)結構體變量,這三個(gè)用戶(hù)空間接口驅動(dòng)函數,完成注冊后,用戶(hù)空間可以采用文件讀寫(xiě)的方式來(lái)操作I2C設備了,I2C_devOpen函數實(shí)現打開(kāi)字符設備,I2C_devRelease函數實(shí)現關(guān)閉字符設備,I2C_devIoctl是實(shí)現和硬件設備實(shí)現數據傳輸的最重要函數,主要實(shí)現設備加載、數據讀取和數據寫(xiě)入,從而完成用戶(hù)空間和驅動(dòng)程序以及硬件設備的數據交換,具體實(shí)現如圖3所示。 下面通過(guò)I2C_devIoctl介紹這三個(gè)函數的實(shí)現過(guò)程,命令I(lǐng)2C_CMD_SET_DEV_ADDR實(shí)現地址設置,I2C_CMD_READ實(shí)現數據讀取,I2C_CMD_WRITE實(shí)現數據寫(xiě)入,最終分別調用,其中I2C_create實(shí)現I2C設備加載,I2C_read實(shí)現I2C設備數據讀取,I2C_write實(shí)現I2C設備數據寫(xiě)入,其中I2C_create利用i2c_add_driver調用i2c_probe,最終調用i2c_set_clientdata加載I2C從設備,I2C_read和I2C_write利用i2c_transfer函數調用master_xfer實(shí)現數據的讀取和寫(xiě)入,具體實(shí)現過(guò)程如圖3所示,其中I2C_devIoctl實(shí)現部分代碼如下: int I2C_devIoctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { switch(cmd) { case I2C_CMD_SET_DEV_ADDR://I2C設置地址設置 filp->private_data = I2C_create(arg); …… case I2C_CMD_READ: //數據讀取 status = copy_from_user(&transferPrm, (void*)arg, sizeof(transferPrm)); if(status==0) { status = copy_from_user();//省略參數 if(status==0) { status = I2C_read();//省略參數 if(status==0) { status = copy_to_user();//省略參數 } } } break; case I2C_CMD_WRITE: //數據寫(xiě)入 …… } return status; 圖3 I2C電機驅動(dòng)設計圖 5 I2C應用程序設計 根據I2C驅動(dòng)程序設計,要正確調用驅動(dòng)程序,需要實(shí)現驅動(dòng)的用戶(hù)空間調用函數,主要是實(shí)現open和ioctl等調用函數,因此在應用層的接口函數中也需要實(shí)現此函數。 i2c_Init()函數實(shí)現open函數,調用驅動(dòng)函數打開(kāi)該設備驅動(dòng),定義一個(gè)數據結構體為: typedef struct { unsigned char dataSize; unsigned char count; unsigned char *reg; void *value; } I2C_Data; 該結構體主要用來(lái)實(shí)現用戶(hù)空間和內核空間的調用的數據交換,dataSize代表數據的大小,value是傳輸的數值,reg是傳輸命令參數,函數有I2c_Read8()是向內核讀入一個(gè)字節數據,I2c_Write8()是向內核寫(xiě)入一個(gè)字節數據,I2c_Read16()是向內核寫(xiě)入2個(gè)字節數據,I2c_Write16 ()是向內核寫(xiě)入2個(gè)字節數據,下面列舉一個(gè)函數說(shuō)明具體的實(shí)現過(guò)程, I2c_Write8(int fd unsigned char *reg, unsigned char *value, unsigned char count){ I2C_Data ptr; unsigned int cmd; int status; ptr.dataSize = 1; ptr.reg = reg; ptr.count = count; ptr.value = value; cmd = CMD_WRITE; status = ioctl(fd, cmd, & ptr); if (status != 0) printf("ioctl I2C_CMD_WRITE error!"); return status; } 如圖4所示,函數最終通過(guò)條用ioctl這個(gè)函數實(shí)現對驅動(dòng)的調用,其中參數fd是設備句柄,cmd讀寫(xiě)控制是命令, 其中宏定義I2C_CMD_SET_DEV_ADDR為地址設置命令,I2C_CMD_READ向內核讀取數據命令, I2C_CMD_WRITE向內核寫(xiě)入數據命令。 其他3個(gè)讀寫(xiě)函數實(shí)現過(guò)程類(lèi)似,這幾個(gè)函數是數據寫(xiě)入讀出的函數接口,方便應用層實(shí)現調用。 圖4 云臺電機控制應用程序設計圖 6 云臺電機控制應用程序設計 云臺很重要部分是電機轉動(dòng)控制,本課題研究采用圖像界面實(shí)現人機交互,其中界面設計采用QT圖形界面軟件來(lái)設計,可以在界面操作實(shí)現電機的水平轉動(dòng)、垂直轉動(dòng),逆時(shí)針轉動(dòng)和順時(shí)針轉動(dòng),從而帶動(dòng)視頻監控的攝像頭朝不同方位轉動(dòng)以及定位,如圖所示。根據協(xié)議,應用程序設計主要實(shí)現以下操作: (1)獲取當前的垂直位置,函數接口為get_motor_curVertical_ptr (),返回垂直位置值; (2)獲取當前的水平位置,函數接口為get_motor_curHorizontal_ptr (),返回水平位置值; (3)設置垂直運行的停止位置,函數接口為set_motor_vertical_ptr (unsigned short ptr),參數ptr為設置的垂直停止位置值; (4)設置水平運行的停止位置,函數接口為set_motor_horizontal_ptr (unsigned short ptr)參數ptr為設置的水平停止位置值; (5)水平操作和垂直操作的啟動(dòng)操作,接口函數為set_motor_opt(bool bVertical, bool bHorizontal) ,參數bVertical表示是否啟動(dòng)垂直操作,bHorizontal表示是否啟動(dòng)水平操作 (6)設置運行速度,函數接口為set_motor_speed(unsigned char vertical_speed, unsigned char horizontal_speed),參數vertical_speed控制垂直方向速度值,horizontal_speed控制水平方向速度值; (7)設置電機運行方向,接口函數set_motor_direction(bool bVertical, bool bHorizontal) ,設置運行方向為順時(shí)針或者逆時(shí)針,參數bVertical為真表示垂直方向向上運動(dòng),為假表示向下運動(dòng);bHorizontal為真,表示水平方向逆時(shí)針,否則為順時(shí)針。 下面通過(guò)運動(dòng)速度的接口函數set_motor_speed(),詳細介紹云臺控制接口函數的實(shí)現過(guò)程,電機轉動(dòng)速度設置函數設置set_motor_speed(),其中函數參數vertical_speed為垂直方向運動(dòng)速度;horizontal_speed為水平方向運動(dòng)速度,局部變量reg用于制定控制類(lèi)型,value設計為16位,其中高8位存放垂直轉動(dòng)速度數值命令,低8為存放水平轉動(dòng)速度數值,參數設置完后調用I2c_Write16()函數,從而調用ioctl實(shí)現對驅動(dòng)的調用,最終通過(guò)I2C總線(xiàn)控制電機,達到電機快速轉動(dòng)、定位準確。 set_motor_speed(unsigned char vertical_speed, unsigned char horizontal_speed) { int ret; unsigned char reg; unsigned short value=0; reg = 3; value = vertical_speed<<8; value |= horizontal_speed; ret = I2c_Write16 (fd, ®, &value); if (ret != 0) printf("set_motor_speed error"); return ret; } 通過(guò)實(shí)現人機交互操作程序,實(shí)現電機的向上轉動(dòng)、向下轉動(dòng),逆時(shí)針轉動(dòng)和順時(shí)針轉動(dòng),通過(guò)調用各種操作的接口函數,實(shí)現對I2C應用程序的調用,最用通過(guò)ioctl實(shí)現對電機的控制,從而帶動(dòng)視頻監控的攝像頭朝不同方位轉動(dòng)以及定位,具體實(shí)現如圖4所示。 7 結束語(yǔ) 本系統設計實(shí)現了一款基于TMS320DM368的高清視頻監控系統中的云臺電機控制設計,完成了i2c驅動(dòng)程序的分析以及設計,并且完成了i2c應用程序的設計和云臺電機控制應用程序設計,達到了應用目的,取得了良好效果。 |