單片機(jī)圖像采集與網(wǎng)絡(luò)傳輸
掃描二維碼
隨時(shí)隨地手機(jī)看文章
1.引言
隨著網(wǎng)絡(luò)技術(shù)的發(fā)展和網(wǎng)絡(luò)應(yīng)用的普及,如何充分利用網(wǎng)絡(luò)資源來(lái)實(shí)現(xiàn)低成本、高可靠的遠(yuǎn)程視頻監(jiān)控,已成為一個(gè)技術(shù)熱點(diǎn)。本文介紹一個(gè)用單片機(jī)與圖像采集模塊接口,嵌入TCP/IP協(xié)議棧,制作“網(wǎng)絡(luò)攝像頭”的方法。本網(wǎng)絡(luò)攝像頭在一個(gè)組播式視頻圖像監(jiān)控系統(tǒng)中,只作為組播源向以太網(wǎng)發(fā)送視頻圖像數(shù)據(jù);其它監(jiān)控計(jì)算機(jī)則作為組播成員接收數(shù)據(jù)。整個(gè)視頻圖像發(fā)送和監(jiān)控系統(tǒng)在局域網(wǎng)中使用時(shí),監(jiān)控接收端的PC機(jī)只要加入了組播組,不必知道網(wǎng)絡(luò)攝像頭的IP地址和 MAC地址,也不需要兩者的IP地址是在同一網(wǎng)段,均可接收到網(wǎng)絡(luò)攝像頭發(fā)出的圖像數(shù)據(jù),使用起來(lái)相當(dāng)方便。
2. 硬件接口電路
網(wǎng)絡(luò)攝像頭的硬件接口電路如圖1所示。該電路采用的單片機(jī)是89C52芯片,另擴(kuò)展32K的外部存儲(chǔ)器,供網(wǎng)絡(luò)和圖像數(shù)據(jù)處理用。
圖1中的DB200是一個(gè)產(chǎn)品攝像模塊,它由微型攝像鏡頭、圖像緩存、時(shí)序發(fā)生、總線接口等電路構(gòu)成;其外接信號(hào)是一個(gè)16腳的插座(9 ~ 16腳分別對(duì)應(yīng)數(shù)據(jù)線D7 ~ D0,其它為地址、電源和讀寫(xiě)控制線)。
圖1中,U1、U4和DB200的片選信號(hào)由89C52的地址線A14、A15和74HC00的3個(gè)與非門(mén)提供:A15=0時(shí)選通U4;A15=1及A14=0時(shí)選通U1;A15=1及A14=1時(shí)選通DB200。DB200的第8腳接A13用來(lái)選擇其內(nèi)部寄存器。
RTL8019AS有3種工作方式:(1)跳線方式。(2)即插即用方式。(3)免跳線方式。RTL8019AS使用哪種工作方式由第65腳(JP)決定。為減少連線,我們采用跳線方式(把65腳接高電平)。這樣網(wǎng)卡的傳輸介質(zhì)、I/O基地址和中斷號(hào)就由74、77、78、79、80、81、82、 84、85等引腳狀態(tài)決定。
RTL8019AS的81、82、84、85(BD0-BD3)腳接低電平,對(duì)應(yīng)32個(gè)I/O寄存器地址范圍為300H - 31FH;78-80(BD4-BD6)腳接低電平,對(duì)應(yīng)中斷號(hào)為INT0(IRQ2/9);74(BA14)、77(BD7)腳接低電平,為自動(dòng)檢測(cè)傳輸介質(zhì)方式。
RTL8019AS有20根地址(SA0-SA19)線,將其5、7、8、9、10(SA0-SA4)腳接89C52的A8-A12,將15、 16(SA8、SA9)腳接高電平來(lái)確?;刂窞?00H,其余地址線則全部接地。由于RTL8019AS的使能(AEN)信號(hào)是由89C52的 A15=1及A14=0時(shí)提供,因此我們可得出以下地址關(guān)系:
89C52: A15 A14 A13 A12 A11 A10 A9 A8 A7………A0
8019: SA4 SA3 SA2 SA1 SA0 …………
2進(jìn)制數(shù): 1 0 0 0 0 0 0 0 0000 0000 16進(jìn)制數(shù): 0X8000
2進(jìn)制數(shù): 1 0 0 1 1 1 1 1 0000 0000 16進(jìn)制數(shù): 0X9F00
可見(jiàn),如果89C52輸出地址0X8000至0X9F00,均可選中RTL8019AS。由于RTL8019AS的SA9和SA8恒接高電平,當(dāng)89C52 的地址信號(hào)由0X8000至0X9F00變動(dòng)時(shí),會(huì)有:SA9 SA8 SA7 SA6 SA5 SA4 SA3 SA2 SA1 SA0 =11 0000 0000 至 11 0001 1111,即對(duì)應(yīng)選擇RTL8019AS的I/O寄存器地址300H至31FH。
RTL8019AS的96腳(IOCS16B)接低電平,使其工作在8位總線模式;64腳接低電平,使用非AUI接口;31、32腳接高電平,屏蔽遠(yuǎn)程自舉加載功能;33腳所需復(fù)位信號(hào),由89C52的P1.5提供;29、30腳對(duì)應(yīng)接89C52的讀寫(xiě)腳。
3. 軟件模塊設(shè)計(jì)
嵌入式系統(tǒng)一般采用簡(jiǎn)化的TCP/IP協(xié)議棧。常用的有IP、ARP、UDP、ICMP、TCP以及HTTP等協(xié)議。為了嘗試實(shí)現(xiàn)一個(gè)最簡(jiǎn)易的嵌入式TCP/IP協(xié)議,我們選用UDP通訊方式。
UDP的通訊方式有3種:點(diǎn)對(duì)點(diǎn)、廣播和組播??紤]到點(diǎn)對(duì)點(diǎn)通訊需要ARP協(xié)議來(lái)取得目標(biāo)節(jié)點(diǎn)的物理地址,我們不用點(diǎn)對(duì)點(diǎn)通訊。至于廣播通訊和組播通訊,兩者都不需要ARP協(xié)議。但廣播方式有如下缺陷:(1)廣播數(shù)據(jù)報(bào)不能跨過(guò)路由器傳播;(2)廣播時(shí)本地子網(wǎng)的所有主機(jī)都會(huì)接收到廣播并作出響應(yīng),既增加了非接收者的開(kāi)銷(xiāo),保密性也不好。我們采用的組播方式不存在這些問(wèn)題,較適合作為網(wǎng)絡(luò)視頻監(jiān)控的信息傳輸。
3.1 主程序工作流程
網(wǎng)絡(luò)攝像頭的圖像采集、打包、發(fā)送的軟件流程如圖2所示,對(duì)應(yīng)的主程序源碼見(jiàn)例程1。為了便于接收端正確判斷每幀圖像的開(kāi)始,主程序在發(fā)送1幀圖像數(shù)據(jù)前,先用Send_lwm( ) 函數(shù)發(fā)送特征字為“lwm”的4字節(jié)長(zhǎng)的數(shù)據(jù)包(該函數(shù)從略),然后再發(fā)送圖像數(shù)據(jù)。
void main(void) //(例程1--循環(huán)采集和發(fā)送圖像數(shù)據(jù)的主程序):
{ init_8019( ); // RTLS8019AS初始化。
while(1) // 循環(huán)采集和發(fā)送圖像:
{ img_capture( ); // 采集1幀圖像。
Send_lwm( ); // 發(fā)送圖像開(kāi)始的特征字“lwm”
Send_img( ); // 發(fā)送1幀圖像數(shù)據(jù)。
}
}
3.2 以太網(wǎng)控制芯片的初始化
RTL8019AS 芯片有32個(gè)寄存器地址,映射到4個(gè)頁(yè)面,每頁(yè)有16個(gè)寄存器。本系統(tǒng)只用0頁(yè)的14個(gè)(00-01H,04-0BH,0D-0EH,0F-10H)寄存器。程序先定義reg00-reg10, 然后用初始化函數(shù)init_8019( )對(duì)RTL8019AS各寄存器進(jìn)行配置:
#define XBYTE ((unsigned char volatile xdata *) 0)
#define reg00 XBYTE[0x8000] //對(duì)應(yīng)300H A15=1, A14=0,A13=A12=A11=A10=A9=A8=0
………………..
#define reg10 XBYTE[0x9000] //對(duì)應(yīng)310H A15=1, A14=0,A13=0,A12=1,A11=A10=A9=A8=0
sbit RST8019 = P1 ^ 5; // RST8019AS的硬件復(fù)位端。
void init_8019(void) // (例程2--RTL8019AS的初始化):
{ UINT C1; for(C1=0;C1<1000;C1++); // 軟件延時(shí),確保芯片進(jìn)入穩(wěn)定狀態(tài)
RST8019=1; for(C1=0;C1<1000;C1++); // 硬件復(fù)位、延時(shí)以確保芯片完全復(fù)位
RST8019=0; for(C1=0;C1<1000;C1++); // 硬件復(fù)位、延時(shí)以確保芯片完全復(fù)位
reg00=0x21; // 選擇第0頁(yè)寄存器,并使芯片停止收發(fā)和DMA操作reg0e=0xC8; // DCR: 采用普通、8位DMA方式
reg07=0xFF; reg0f=0x00; // 清除和屏蔽所有中斷(本系統(tǒng)未采用中斷)
reg0d=0xE0; // TCR:采用普通發(fā)送模式、允許CRC產(chǎn)生和校驗(yàn)
}
為了節(jié)省資源,上述對(duì)RTLS8019AS的初始化中,凡是與發(fā)送無(wú)關(guān)的寄存器都沒(méi)有設(shè)置。發(fā)送時(shí)所要用的組播地址、物理地址和IP地址,則在打包時(shí)再封裝到各協(xié)議層數(shù)據(jù)包的頭部。
3.3 圖像數(shù)據(jù)的采集
負(fù)責(zé)圖像采集的DB200攝像模塊內(nèi)部有數(shù)據(jù)、狀態(tài)、采集控制和地址控制4個(gè)寄存器,表1是它們的尋址方式。對(duì)各寄存器的操作規(guī)則如下:
(1)寫(xiě)操作-對(duì)采集控制寄存器(CAP_CTRLr)D0位寫(xiě)1,可啟動(dòng)采集過(guò)程;對(duì)地址控制寄存器(CAP_INCr)D0位寫(xiě)一次1,其圖像緩存的地址就加1。
(2)讀操作-如果狀態(tài)寄存器(CAP_STAUSr)的D0=1,表示可以開(kāi)始圖像采集過(guò)程;D1=1表示已完成1幀圖像采集,可以讀取數(shù)據(jù)寄存器(CAP_DATAr)的圖像數(shù)據(jù)。
DB200工作的地址范圍是:1100 0000 0000 0000 ~ 1110 0000 0000 0000 = 0C00H ~ 0E00H。據(jù)此,我們可寫(xiě)出如下圖像采集函數(shù)(例程3):
#define CAP_CONTROLr XBYTE[0X0C000] //A15=1=A14, A13=0
#define CAP_STATUSr XBYTE[0X0C000]
void img_capture( ) // (例程3--圖像采集):
{ while(!(CAP_STATUSr & 0x01)); // 檢查DB200是否準(zhǔn)備就緒?
CAP_CONTROLr=0xff; // 啟動(dòng)采集1幀圖像過(guò)程。
while(!(CAP_CONTROLr & 0x02)); // 是否采集完1幀圖像?是就結(jié)束。
}
img_capture( )函數(shù)只完成了1幀圖像數(shù)據(jù)的采集,采集好的數(shù)據(jù)存在DB200的數(shù)據(jù)緩沖區(qū)內(nèi),留待Send_img( )函數(shù)讀取和發(fā)送。Send_img( )是以讀1行圖像數(shù)據(jù)就發(fā)送1行的方式工作。其源碼如下:
#define CAP_INCr XBYTE[0X0E000] //A15=1=A14,A13=1
#define CAP_DATAr XBYTE[0X0E000]
extern UCHAR xdata outbuf[1520];
void Send_img( ) // (例程4--圖像數(shù)據(jù)的讀取和發(fā)送):
{ UINT data Colon, Line ;
for(Line=0;Line<288;Line++) // 288行
{ for(Colon=0;Colon<385;Colon++) // 385 列
{ databuf[Colon]=CAP_DATAr; // 從 db200讀1個(gè)像點(diǎn)到databuf。
CAP_INCr=0xff; // db200圖像數(shù)據(jù)緩存地址加1。
}
udp_send(databuf, UDP_PORT, 386); // 封裝并發(fā)送1行圖像數(shù)據(jù)。
}
}
3.4 圖像數(shù)據(jù)的封裝
DB200采集完1幀圖像后,通過(guò)數(shù)據(jù)總線傳送給89C52;89C52則將圖像數(shù)據(jù)按TCP/IP協(xié)議封裝成以太網(wǎng)幀(圖3),然后通過(guò)數(shù)據(jù)總線送給RTL8019AS;RTL8019AS則將以太網(wǎng)幀經(jīng)RJ45接口送到10M以太網(wǎng)上。
從圖3可以看到,每個(gè)以太網(wǎng)幀的最大長(zhǎng)度為1518字節(jié),最小為64字節(jié)。其數(shù)據(jù)部分最大為1500字節(jié),最小為46字節(jié)。每個(gè)UDP數(shù)據(jù)傳輸前,必須加上 8字節(jié)的UDP頭來(lái)構(gòu)成UDP數(shù)據(jù)報(bào);再加上20字節(jié)的IP頭來(lái)構(gòu)成IP數(shù)據(jù)報(bào);最后加上14字節(jié)的幀頭來(lái)構(gòu)成以太網(wǎng)幀。這就是所謂的數(shù)據(jù)包封裝。為了避免分段操作的麻煩,UDP數(shù)據(jù)報(bào)的最大長(zhǎng)度應(yīng)為1500 - 28=1472字節(jié)。在實(shí)際應(yīng)用中,我們采用每行圖像數(shù)據(jù)(385字節(jié))封裝一個(gè)包的方式傳輸數(shù)據(jù)。
void Data_send( UINT src_port, UINT datalen) // (例程5--UDP數(shù)據(jù)報(bào)封裝):
{ UDP_HEADER xdata * udp;
udp = (UDP_HEADER xdata *)(outbuf + 34); // 34=14(以太網(wǎng)幀頭長(zhǎng))+ 20(IP報(bào)頭長(zhǎng)) udp->dest_port = 2001; // 目的端口號(hào)
udp->source_port = 20011; // 源端口號(hào)
udp->length = 8 + datalen; // UDP包總長(zhǎng)= UDP頭長(zhǎng)度+數(shù)據(jù)長(zhǎng)度
udp->checksum = 0; // 不校驗(yàn)UDP數(shù)據(jù)報(bào)
ip_pack(outbuf, dest_ipaddr, udp->length); // 封裝IP包
}
void ip_pack(UCHAR xdata * outbuf, ULONG dest_ipaddr, UINT datalen)//(例程6-封裝IP包)
{ IP_HEADER xdata * ip; static UINT ip_ident; // datalen為UDP數(shù)據(jù)報(bào)總長(zhǎng)度
ip = (IP_HEADER xdata *)(outbuf + 14); // 14字節(jié)為以太網(wǎng)幀頭長(zhǎng)度。
ip->ver_len = 0x45; ip->type_of_service = 0; // 版本號(hào)和服務(wù)類(lèi)型。
ip->total_length = 20 + datalen; // 數(shù)據(jù)報(bào)總長(zhǎng)=IP頭長(zhǎng)度+數(shù)據(jù)長(zhǎng)度
ip->identifier = ip_ident++; // IP數(shù)據(jù)報(bào)序列號(hào)。
ip->fragment_info = 0; // IP數(shù)據(jù)報(bào)不分段。
ip->time_to_live = 32; // 生存時(shí)間。
ip->protocol_id = UDP_TYPE; // 協(xié)議類(lèi)型為UDP=17。
ip->header_cksum = 0; // 校驗(yàn)和清0。
ip->dest_ipaddr = 0xEA050607L; // 0xEA050607L=234.5.6.7 為目標(biāo)組播地址
ip->source_ipaddr = 0xD224446FL; // 0xD224446FL=210.36.68.111為本地IP地址
ip->header_cksum = ~cksum(outbuf + 14, 20); // 計(jì)算20字節(jié)的IP數(shù)據(jù)報(bào)頭校驗(yàn)和
eth_send(outbuf, 34 + datalen); // 封裝以太網(wǎng)幀并發(fā)送。
}
在上述例程5和例程6中,UDP的校驗(yàn)和是可選的,IP頭的校驗(yàn)和是必需的。例程5將UDP檢驗(yàn)和置為0,例程6則用cksum( )函數(shù)來(lái)計(jì)算IP頭校驗(yàn)和。本地IP地址可取任意有效值。
3.5 以太網(wǎng)幀的封裝和發(fā)送
從圖3可知,以太網(wǎng)幀封裝就是要將目的MAC地址、源MAC地址和所要傳輸?shù)臄?shù)據(jù)類(lèi)型放到待發(fā)送的IP數(shù)據(jù)報(bào)前(成為以太網(wǎng)幀頭)。因?yàn)槲覀円M(jìn)行的是組播發(fā)送,所以目的MAC地址也必須是組播的MAC地址;而本地的源MAC地址我們就用01:02:03:04:05:06。
上面說(shuō)到,“IP組播地址”范圍是224.0.0.0到239.255.255.255。而以太網(wǎng)幀用到的“MAC組播地址”范圍是 01:00:5E:00:00:00-01:00:5E:7F:FF:FF 。MAC組播地址的構(gòu)成方法是:前3個(gè)字節(jié)固定用01:00:5E,后3個(gè)字節(jié)則用IP組播地址的后3個(gè)字節(jié)。所以我們用234.5.6.7作IP組播地址時(shí),對(duì)應(yīng)的MAC組播地址就是 01:00:5E:05:06:07。
在下面的程序中,RTL8019AS用查詢(xún)方式進(jìn)行發(fā)送操作。
UCHAR code dest_hwaddr[6] = { 0x01, 0x00, 0x5E, 0x05, 0x06, 0x07}; // 目標(biāo)MAC組播地址
UCHAR code my_hwaddr[6] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; // 源MAC地址
void eth_send(UCHAR xdata * outbuf, UINT Data_len) // (例程7--以太網(wǎng)幀封裝和發(fā)送):
{ UINT i , send_len; ETH_HEADER xdata * eth; eth = (ETH_HEADER xdata *)outbuf;
for(i=0;i<6;i++)
{ eth->dest_hwaddr[i]= dest_hwaddr[i]; // 裝入目的MAC地址。
eth->source_hwaddr[i]= my_hwaddr[i]; // 裝入源MAC地址。
}
eth->frame_type = IP_PACKET; // 數(shù)據(jù)類(lèi)型為IP數(shù)據(jù)報(bào)
// send_len為實(shí)際要發(fā)送的以太網(wǎng)幀長(zhǎng)度,它不能小于60字節(jié):
send_len = (Data_len>=60) ? Data_len : 60 ;
reg00=0x22; // 選擇0頁(yè)寄存器,啟動(dòng)芯片。
while( reg00 & 0x04 ); // 原來(lái)的數(shù)據(jù)發(fā)送完沒(méi)有?完了往下執(zhí)行
reg08=0x00; reg09=0x40; // 設(shè)置發(fā)送緩沖區(qū)開(kāi)始地址為4000H。
//設(shè)置(RBCR0-1)遠(yuǎn)端DMA傳送數(shù)據(jù)包長(zhǎng)度(高、低字節(jié)):
reg0a=(unsigned char)(Data_len); reg0b=(unsigned char)(Data_len>>8);
reg00=0x16; // 設(shè)置遠(yuǎn)端DMA寫(xiě),啟動(dòng)遠(yuǎn)端DMA傳送數(shù)據(jù)到發(fā)送緩沖區(qū)
for(i=0;i<Data_len;i++) reg10=outbuf[i]; // 往RTL8019AS的I/O端口傳送圖像數(shù)據(jù)
reg04=0x40; // 設(shè)置發(fā)送緩沖區(qū)開(kāi)始地址高字節(jié)
//設(shè)置(TBCR0-1)發(fā)送字節(jié)計(jì)數(shù)器的計(jì)數(shù)長(zhǎng)度(高、低字節(jié)):
reg05=(unsigned char)(send_len); reg06=(unsigned char)(send_len>>8);
reg00=0x26; // 啟動(dòng)本地DMA操作,向網(wǎng)絡(luò)發(fā)送圖像數(shù)據(jù)。
}
上述程序先設(shè)置好遠(yuǎn)端DMA開(kāi)始地址(RSAR)和遠(yuǎn)端DMA數(shù)據(jù)字節(jié)數(shù)(RBCR),并設(shè)置遠(yuǎn)端DMA寫(xiě)( reg00=0x16),就可以把圖像數(shù)據(jù)寫(xiě)入RTL8019AS的數(shù)據(jù)緩沖區(qū)。給出發(fā)送緩沖區(qū)首地址和數(shù)據(jù)包長(zhǎng)度后,啟動(dòng)發(fā)送命令 (reg00=0x26), RTL8019AS就會(huì)按以太網(wǎng)協(xié)議將圖像數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)上。
4. 結(jié)束語(yǔ)
TCP/IP協(xié)議較復(fù)雜,嵌入式系統(tǒng)自身的資源又很有限,動(dòng)輒幾十K的TCP/IP協(xié)議棧,使很多入門(mén)者望而卻步。其實(shí)要在嵌入式系統(tǒng)實(shí)現(xiàn)TCP/IP協(xié)議,只不過(guò)就是編制各個(gè)符合TCP/IP協(xié)議規(guī)則的軟件模塊罷了。根據(jù)自己系統(tǒng)的具體情況編制專(zhuān)門(mén)的功能模塊,也可以實(shí)現(xiàn)相當(dāng)簡(jiǎn)化的TCP/IP協(xié)議棧。本文在此給出了一個(gè)可供借鑒的實(shí)例。
參考文獻(xiàn):
[1] 吳禮發(fā), 網(wǎng)絡(luò)程序設(shè)計(jì)教程[M],北京:希望電子出版社,2002.1
[2] RTL8019AS SPECIFICATION[EB/OL],REALTEKSEMI-CONDUCTOR CO., LTD , 2000.8.20
[3] 單片機(jī)與TCP/IP網(wǎng)絡(luò)[EB/OL], HTTP:// WWW.LAOGU.COM