微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 单片机图像采集与网络传输

单片机图像采集与网络传输

时间:03-20 来源:互联网 点击:

BH,0D-0EH,0F-10H)寄存器。程序先定义reg00-reg10, 然后用初始化函数init_8019( )对RTL8019AS各寄存器进行配置:
#define XBYTE ((unsigned char volatile xdata *) 0)
#define reg00 XBYTE[0x8000] //对应300H A15=1, A14=0,A13=A12=A11=A10=A9=A8=0
………………..
#define reg10 XBYTE[0x9000] //对应310H A15=1, A14=0,A13=0,A12=1,A11=A10=A9=A8=0
sbit RST8019 = P1 ^ 5; // RST8019AS的硬件复位端。
void init_8019(void) // (例程2--RTL8019AS的初始化):
{ UINT C1; for(C1=0;C11000;C1++); // 软件延时,确保芯片进入稳定状态
RST8019=1; for(C1=0;C11000;C1++); // 硬件复位、延时以确保芯片完全复位
RST8019=0; for(C1=0;C11000;C1++); // 硬件复位、延时以确保芯片完全复位
reg00=0x21; // 选择第0页寄存器,并使芯片停止收发和DMA操作reg0e=0xC8; // DCR: 采用普通、8位DMA方式
reg07=0xFF; reg0f=0x00; // 清除和屏蔽所有中断(本系统未采用中断)
reg0d=0xE0; // TCR:采用普通发送模式、允许CRC产生和校验
}

为了节省资源,上述对RTLS8019AS的初始化中,凡是与发送无关的寄存器都没有设置。发送时所要用的组播地址、物理地址和IP地址,则在打包时再封装到各协议层数据包的头部。

3.3 图像数据的采集

负责图像采集的DB200摄像模块内部有数据、状态、采集控制和地址控制4个寄存器,表1是它们的寻址方式。对各寄存器的操作规则如下:

(1)写操作-对采集控制寄存器(CAP_CTRLr)D0位写1,可启动采集过程;对地址控制寄存器(CAP_INCr)D0位写一次1,其图像缓存的地址就加1。

(2)读操作-如果状态寄存器(CAP_STAUSr)的D0=1,表示可以开始图像采集过程;D1=1表示已完成1帧图像采集,可以读取数据寄存器(CAP_DATAr)的图像数据。

DB200工作的地址范围是:1100 0000 0000 0000 ~ 1110 0000 0000 0000 = 0C00H ~ 0E00H。据此,我们可写出如下图像采集函数(例程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是否准备就绪?
CAP_CONTROLr=0xff; // 启动采集1帧图像过程。
while(!(CAP_CONTROLr 0x02)); // 是否采集完1帧图像?是就结束。
}
img_capture( )函数只完成了1帧图像数据的采集,采集好的数据存在DB200的数据缓冲区内,留待Send_img( )函数读取和发送。Send_img( )是以读1行图像数据就发送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--图像数据的读取和发送):
{ UINT data Colon, Line ;
for(Line=0;Line288;Line++) // 288行
{ for(Colon=0;Colon385;Colon++) // 385 列
{ databuf[Colon]=CAP_DATAr; // 从 db200读1个像点到databuf。
CAP_INCr=0xff; // db200图像数据缓存地址加1。
}
udp_send(databuf, UDP_PORT, 386); // 封装并发送1行图像数据。
}
}

3.4 图像数据的封装

DB200采集完1帧图像后,通过数据总线传送给89C52;89C52则将图像数据按TCP/IP协议封装成以太网帧(图3),然后通过数据总线送给RTL8019AS;RTL8019AS则将以太网帧经RJ45接口送到10M以太网上。

从图3可以看到,每个以太网帧的最大长度为1518字节,最小为64字节。其数据部分最大为1500字节,最小为46字节。每个UDP数据传输前,必须加上 8字节的UDP头来构成UDP数据报;再加上20字节的IP头来构成IP数据报;最后加上14字节的帧头来构成以太网帧。这就是所谓的数据包封装。为了避免分段操作的麻烦,UDP数据报的最大长度应为1500 - 28=1472字节。在实际应用中,我们采用每行图像数据(385字节)封装一个包的方式传输数据。
void Data_send( UINT src_port, UINT datalen) // (例程5--UDP数据报封装):
{ UDP_HEADER xdata * udp;
udp = (UDP_HEADER xdata *)(outbuf + 34); // 34=14(以太网帧头长)+ 20(IP报头长) udp->dest_port = 2001; // 目的端口号
udp->source_port = 20011; // 源端口号
udp->length = 8 + datalen; // UDP包总长= UDP头长度+数据长度
udp->checksum = 0; // 不校验UDP数据报
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数据报总长度
ip = (IP_HEADER xdata *)(outbuf + 14); // 14字节为以太网帧头长度。
ip->ver_len = 0x45; ip->type_of_service = 0; // 版本号和服务类型。
ip->total_length = 20 + datalen; // 数据报总长=IP头长度+数据长度
ip->identifier = ip_ident++; // IP数据报序列号。
ip->fragment_info = 0; // IP数据报不分段。
ip->time_to_live = 32; // 生存时间。
ip->protocol_id = UDP_TYPE; // 协议类型为UDP=17。
ip->header_cksum = 0; // 校验和清0。
ip->dest_ipaddr = 0xEA050607L; // 0xEA050607L=234.5.6.7 为目标组播地址
ip->source_ipaddr = 0xD224446FL; // 0xD224446FL=210.36.68.111为本地IP地址
ip->header_cksum = ~cksum(outbuf + 14, 20); // 计算20字节的IP数据报头校验和
eth_send(outbuf, 34 + datalen); // 封装以太网帧并发送。
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top