一、项目简介
运用根据RT-thread操作体系的AB32VG1开发板作为主控,对ov7670摄像头进行图画收集,并运用串口发送图片RGB565格局到PC供opencv进行图画辨认。 原项目想象在开发板上进行收集的一起并经过简单的二值算法和插值算法完结车牌号辨认,但实践中发现开发板的ram并不够保存收集回来的图画信息,与数据手册中介绍的192k有一定距离,完结用户能运用的ram是70k;一起原想象是带lcd屏幕的,但最终发觉io口数量不够,只能经过串口调试显示,但lcd屏幕的 spi代码仍保留在原码中,可供参考。 现在开发板经过摄像头收集完好数据部分现已完结,并且能够经过串口uart1发送到上位机进行图画显示。
二、硬件说明
1.摄像头ov7670带fifo:选用csi总线的普通30w摄像头。考虑到用模仿读取摄像头,io的回转速度可能不能满意高速收集的需求,因而稳妥起见,直接运用带fifo的摄像头。sccb总线选用全模仿的方法,跳过了所有中间层,直接操作寄存器,提高了总线的时钟。
2.串口工具PL2302(ttl转RS232),一款与pc通讯的串口工具,免驱。
3.总接线图
三、软件说明
1.软件流程图
2.要害代码
/* 摄像头IO口选用直接操作寄存器的方法完结,极大提升io速度 */
#define BSP_FIFO_RCK_PIN "PA.5"
#define BSP_FIFO_RCK_SET_LOW (GPIOA_BASE[GPIOx] &= ~(1ul << 5))
#define BSP_FIFO_RCK_SET_HIGH (GPIOA_BASE[GPIOx] |= (1ul << 5))
/* sccb总线的初始化并设置ov7670相应寄存器 */
sccb_init();
if(sccb_write_reg(0x12, 0x80) == RT_FALSE){
return RT_FALSE;
}
rt_thread_delay(50);
id1 = sccb_read_reg(0x0b);
id2 = sccb_read_reg(0x0a);
rt_kprintf("id1 = 0x%02x, id2 = 0x%02xn", id1, id2);
for(rt_uint16_t i = 0;i < sizeof(ov7670_init_reg_tbl) / sizeof(ov7670_init_reg_tbl[0]);i++){
sccb_write_reg(ov7670_init_reg_tbl[0], ov7670_init_reg_tbl[1]);
}
/* 敞开摄像头vsync扫描线程(没有外部中断因而改用轮询的方法完结) */
rt_thread_t thread;
/* 查询VSYNC线程 */
thread = rt_thread_create("ov7670_vsync", ov7670_vsync_thread_entry, RT_NULL, 1024, 5, 100);
if (thread == RT_NULL){
rt_kprintf("ov7670_vsync thread create fail!n");
return RT_FALSE;
}
/* 发动线程 */
rt_thread_startup(thread);
/* 提取hal库完结了uart的数据发送函数 */
void uart1_send(rt_uint8_t *pbuf, rt_uint32_t len)
{
for(rt_uint32_t i = 0;i < len;i++){
hal_uart_clrflag(UART1_BASE, UART_FLAG_TXPND);
hal_uart_write(UART1_BASE, pbuf);
while(hal_uart_getflag(UART1_BASE, UART_FLAG_TXPND) == 0);
}
}
/* LCD底层驱动代码,因为引脚不够,所以无法演示,测试可用,别的程序里也配有寄存器版本的操作代码 */
static rt_uint32_t spi_bit_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
struct rt_spi_bit_ops *ops = (struct rt_spi_bit_ops *)device->user_data;
rt_uint8_t tmp_buf[1024];
rt_memset(tmp_buf, 0, sizeof(tmp_buf));
if(message->send_buf == RT_NULL){
message->send_buf = tmp_buf;
}else if(message->recv_buf == RT_NULL){
message->recv_buf = tmp_buf;
}else{
return RT_FALSE;
}
if (message->cs_take){
ops->set_cs(ops->data, PIN_LOW);
}
#ifdef SPI_DC
message->length & SPI_DC ? ops->set_dc(ops->data, PIN_HIGH) : ops->set_dc(ops->data, PIN_LOW);
message->length &= ~SPI_DC; /* 恢复消息长度 */
// rt_kprintf("message->length = %dn", message->length);
#endif
spi_rw_bytes(device, (rt_uint8_t *)message->send_buf, (rt_uint8_t *)message->recv_buf, message->length);
if (message->cs_release){
ops->set_cs(ops->data, PIN_HIGH);
}
}
static const struct rt_spi_ops spi_bit_bus_ops ={
RT_NULL,
spi_bit_xfer
};
优化思路:1. 因为ab32vg1没有外部中断能够运用,ov7670的帧同步信号vsync只要500us的高电平时间,因而为了捕捉到该信号,vsync线程一直占用许多的资源;2. 串口与上位通讯的速度现在最快只要115200bps,上位机能够接受256000bps的速度,但将驱动改为256000bps后,接纳会出现乱码,因而串口运用的图片数据非常缓慢。
四、项目演示