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