全地形越障排爆小车

目录

记录一下去年工科赛的项目吧,疫情没去省赛太可惜了

1. 比赛场地

(1)场地地面为 408cm×175cm(尺寸误差±3cm) 的宝丽布,

(2)窄桥尺寸图:

(3)台阶尺寸图:

(4)管道尺寸图:

(5)气球:

关于气球说明:

 2.比赛所用模块

2.1 颜色识别——OV7670模块

2.1.1 摄像头主要参数

(1)CCD VS CMOS

(2)图像分辨率

(3)摄像头OV7670特点

2.1.2 所用协议——sccb协议

1.SCCB协议介绍

2.SCCB读写过程

3.SCCB与I2C区别

4.SCCB实现代码

2.1.3 OV7670模块初始化代码

1.OV7670.h

2.OV7670.c

2.1.4 FIFO的作用

OV7670带FIFO引脚定义

什么是FIFO?

为什么需要FIFO?

FIFO引脚功能

一幅图像的读取


1. 比赛场地


      场地中设定四种五个不同特点、不同难度的障碍物,每种障碍物均有一定的分值,参赛队根据比赛规则自主设计制作全地形小车,完成穿越各个障碍物的比赛。 

      障碍物分别为三种颜色的气球、楼梯、管道、窄桥,各障碍物由黑色引导线连接,形成完整的比赛赛道,并设置比赛起点和终点,比赛场地由组委会统一布置。

      全地形小车启动后自动行驶并跨越其他三种障碍物(管道,窄桥,楼梯)后,需识别颜色板上随机色卡的颜色并扎破对应颜色气球。

(1)场地地面为 408cm×175cm(尺寸误差±3cm) 的宝丽布

四周有高度为 18cm 的围栏。场地地面设有起点线和终止线,距离边缘 90cm。部分障碍前后20cm 设有标志线,供参赛队伍参考使用。距离长边 60cm 的两条红线为装饰线。5 个 障碍物按图 1、图 2 所示种类、数量和位置安放,并以双面胶固定在场地地面上,不可移动。黑线用 3.8cm 宽低反光绝缘胶带铺设。

(2)窄桥尺寸图:

                         单位:cm

                         材料:发泡 EVA

                         颜色:黑色

3)台阶尺寸图:

                         单位:cm

                         材料:发泡 EVA

                         颜色:黑色

(4)管道尺寸图:

                         单位:cm

                         材料:亚克力颜色:透明

(5)气球:

           单位:cm

           材料:橡胶

           颜色:红、蓝、绿各一个

           关于窄桥和台阶障碍:表面贴磨砂砂纸。

           气球布置说明(其中尺寸标注±10mm):

关于气球说明:

气球颜色为:深红、深绿、深蓝

气球大小(宽):22cm和26cm之间,测量宽度方向以下图黑线示意为参考(横向最宽距离);

气球安装角度:气球横放,气嘴朝向终点线反方向,气球底面中部与场地布紧贴,气球 与场地布通过粘度较高的双面胶固定(以侧向拍打不掉落为准),气球固定位置距离气球底面中点误差±5cm;

关于扎气球的装置说明:扎气球装置末端可采用细小尖锐物体,如曲别针、图钉、牙签等,机器人上场前将对扎气球装置进行检验;

关于挡板布置,如下图蓝色外框(其中尺寸标注误差±10mm) 

 2.比赛所用模块

其实这个比赛主要完成的是三个功能,一个是寻线,一个是扎气球,一个是进行颜色识别。

2.1 颜色识别——OV7670模块

OV7670摄像头模块资料_-liming-的博客-CSDN博客

————————————————
版权声明:本文为CSDN博主「-liming-」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_38393591/article/details/116291875

这里主要是通过对代码的分析来加固自己的理解,

2.1.1 摄像头主要参数

(1)CCD VS CMOS

CCD成像质量高,动态响应比较好,但制造工艺复杂,价格昂贵,比较重,电压12V。
CMOS质量轻,对电源电压的要求低,功耗比较低,成像质量差,噪声大。
目前市面上绝大多数的消费级别以及高端数码相机都使用CCD作为感应器;CMOS感应器则作为低端产品应用于一些摄像头上。

(2)图像分辨率

SXGA(分辨率1280x1024)又称130万像素;
XGA(分辨率1024x768)又称80万像素;
VGA,分辨率为 640*480 ;
CIF(分辨率352x288)又称10万像素
SIF/QVGA(分辨率320x240)
QCIF(分辨率176x144)
QSIF/QQVGA(分辨率160x120)

(3)摄像头OV7670特点

高灵敏度、低电压适合嵌入式应用;
标准的 SCCB 接口,兼容 IIC 接口;
支持 RawRGB、RGB(GBR4:2:2,RGB565 /RGB555 /RGB444),YUV(4:2:2)和 YCbCr(4:2:2)输出格式;
支持 VGA、QVGA、CIF,和从 CIF 到 40*30 的各种尺寸输出;
支持自动曝光控制、自动增益控制、自动白平衡、自动消除灯光条纹、自动黑电平校准等自动控制功能。同时支持色饱和度、色相、伽马、锐度等设置;
支持闪光灯;
支持图像缩放;

2.1.2 所用协议——sccb协议

SCCB协议_FPGA小白758的博客-CSDN博客

1.SCCB协议介绍

SCCB(Serial Camera Control Bus ),为串行相机控制总线。与I2C协议极为类似
SCCB 的起始信号、停止信号及数据有效性与 I2C 完全一样。
1.起始信号: 在 SCL(图中为 SIO_C) 为高电平时, SDA(图中为 SIO_D)出现一个下降沿,则 SCCB 开始传输。
2.停止信号:在 SCL 为高电平时, SDA 出现一个上升沿,则 SCCB 停止传输。
3.数据有效性:除了开始和停止状态, 在数据传输过程中,当 SCL 为高电平时,
必须保证 SDA 上的数据稳定,也就是说, SDA 上的电平变换只能发生在 SCL 为低电平的时候,SDA 的信号在 SCL 为高电平时被采集。


2.SCCB读写过程

写过程:起始信号+设备地址写+不关心+寄存器地址+不关心+写数据+不关心+停止位。
ID ADDRESS和I2C一样由七位地址线加一位读写位组成,X表示不关心。

读过程:起始信号+设备地址写+不关心+寄存器地址+不关心+停止信号+起始信号+设备地址写+不关心+读数据+未应答+停止位。

3.SCCB与I2C区别

SCCB(Serial Camera Control Bus)和 I2C(Inter-Integrated Circuit)是两种串行通信协议,通常用于控制图像传感器与主控芯片之间的通信。它们之间的区别如下:

1.应答位:I2C应答位为ACK(0为有应答,1为无应答)。而SCCB中应答位位X,表示don’t care

2.I2C中部分设备支持页操作,而SCCB中不支持页操

在 I2C 中,页操作是指通过指定页寄存器来访问设备内部的多个寄存器。通过设置页寄存器,可以在一个传输中读取或写入多个相关的寄存器值,从而提高数据传输的效率。

然而,在 SCCB 中,并没有像页寄存器这样的机制来支持一次读写多个相关寄存器的操作。SCCB 更加简化和专注于图像传感器的控制,只能逐个读写指定的寄存器。

因此,在使用 I2C 接口时,可以利用页操作来批量传输数据,而在使用 SCCB 接口时,需要依次读写每个特定的寄存器。这也是 I2C 在某些场景下相对于 SCCB 更加灵活和高效的原因之一。

3.SCCB读操作中虚写后有stop信号,而I2C中可有可无

4.性能:SCCB 是一种基于 I2C 的协议,相较于标准的 I2C,SCCB 有更高的时钟速率和更短的传输周期,因此在图像传感器的控制方面具有更好的性能。

5.地址格式:I2C 使用 7 位或 10 位的地址格式来寻址从设备,可以同时连接多个从设备。而 SCCB 通常使用 8 位的地址格式,寻址范围相对较小,往往只能连接单个图像传感器。

6.简化协议:相对于 I2C,SCCB 的协议更为简化,功能更专一,适合于图像传感器等特定应用场景。

4.SCCB实现代码

sccb.c

#include "sys.h"
#include "sccb.h"
#include "delay.h"
//
//本程序参考自网友guanfu_wang代码。
//ALIENTEK MiniSTM32开发板
//OV7670 驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/10/31
//版本:V1.0
//

//初始化SCCB接口
//CHECK OK
void SCCB_Init(void)
{


    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);	 //使能PC端口时钟


    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;				 // 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //输输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC,GPIO_Pin_6|GPIO_Pin_7);						 // 输出高

    SCCB_SDA_OUT();
}

//SCCB起始信号
//当时钟为高的时候,数据线的高到低,为SCCB起始信号
//在激活状态下,SDA和SCL均为低电平
void SCCB_Start(void)
{
    SCCB_SDA=1;     //数据线高电平
    SCCB_SCL=1;	    //在时钟线高的时候数据线由高至低
    delay_us(50);
    SCCB_SDA=0;
    delay_us(50);
    SCCB_SCL=0;	    //数据线恢复低电平,单操作函数必要
}

//SCCB停止信号
//当时钟为高的时候,数据线的低到高,为SCCB停止信号
//空闲状况下,SDA,SCL均为高电平
void SCCB_Stop(void)
{
    SCCB_SDA=0;
    delay_us(50);
    SCCB_SCL=1;
    delay_us(50);
    SCCB_SDA=1;
    delay_us(50);
}
//产生NA信号
void SCCB_No_Ack(void)
{
    delay_us(50);
    SCCB_SDA=1;
    SCCB_SCL=1;
    delay_us(50);
    SCCB_SCL=0;
    delay_us(50);
    SCCB_SDA=0;
    delay_us(50);
}
//SCCB,写入一个字节
//返回值:0,成功;1,失败.
u8 SCCB_WR_Byte(u8 dat)
{
    u8 j,res;
    for(j=0; j<8; j++) //循环8次发送数据
    {
        if(dat&0x80)SCCB_SDA=1;
        else SCCB_SDA=0;
        dat<<=1;
        delay_us(50);
        SCCB_SCL=1;
        delay_us(50);
        SCCB_SCL=0;
    }
    SCCB_SDA_IN();		//设置SDA为输入
    delay_us(50);
    SCCB_SCL=1;			//接收第九位,以判断是否发送成功
    delay_us(50);
    if(SCCB_READ_SDA)res=1;  //SDA=1发送失败,返回1
    else res=0;         //SDA=0发送成功,返回0
    SCCB_SCL=0;
    SCCB_SDA_OUT();		//设置SDA为输出
    return res;
}
//SCCB 读取一个字节
//在SCL的上升沿,数据锁存
//返回值:读到的数据
u8 SCCB_RD_Byte(void)
{
    u8 temp=0,j;
    SCCB_SDA_IN();		//设置SDA为输入
    for(j=8; j>0; j--) 	//循环8次接收数据
    {
        delay_us(50);
        SCCB_SCL=1;
        temp=temp<<1;
        if(SCCB_READ_SDA)temp++;
        delay_us(50);
        SCCB_SCL=0;
    }
    SCCB_SDA_OUT();		//设置SDA为输出
    return temp;
}
//写寄存器
//返回值:0,成功;1,失败.
u8 SCCB_WR_Reg(u8 reg,u8 data)
{
    u8 res=0;
    SCCB_Start(); 					//启动SCCB传输
    if(SCCB_WR_Byte(SCCB_ID))res=1;	//写器件ID
    delay_us(100);
    if(SCCB_WR_Byte(reg))res=1;		//写寄存器地址
    delay_us(100);
    if(SCCB_WR_Byte(data))res=1; 	//写数据
    SCCB_Stop();
    return	res;
}
//读寄存器
//返回值:读到的寄存器值
u8 SCCB_RD_Reg(u8 reg)
{
    u8 val=0;
    SCCB_Start(); 				//启动SCCB传输
    SCCB_WR_Byte(SCCB_ID);		//写器件ID
    delay_us(100);
    SCCB_WR_Byte(reg);			//写寄存器地址
    delay_us(100);
    SCCB_Stop();
    delay_us(100);
    //设置寄存器地址后,才是读
    SCCB_Start();
    SCCB_WR_Byte(SCCB_ID|0X01);	//发送读命令
    delay_us(100);
    val=SCCB_RD_Byte();		 	//读取数据
    SCCB_No_Ack();
    SCCB_Stop();
    return val;
}




sccb.h

#ifndef __SCCB_H
#define __SCCB_H
#include "sys.h"
//
//本程序参考自网友guanfu_wang代码。
//ALIENTEK MiniSTM32开发板
//OV7670 驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/10/31
//版本:V1.0
//

#define SCCB_SDA_IN()  {GPIOC->CRL&=0X0FFFFFFF;GPIOC->CRL|=0X80000000;}
#define SCCB_SDA_OUT() {GPIOC->CRL&=0X0FFFFFFF;GPIOC->CRL|=0X30000000;}

//IO操作函数
#define SCCB_SCL    		PCout(6)	 	//SCL
#define SCCB_SDA    		PCout(7) 		//SDA	 

#define SCCB_READ_SDA    	PCin(7)  		//输入SDA    
#define SCCB_ID   			0X42  			//OV7670的ID

///
void SCCB_Init(void);
void SCCB_Start(void);
void SCCB_Stop(void);
void SCCB_No_Ack(void);
u8 SCCB_WR_Byte(u8 dat);
u8 SCCB_RD_Byte(void);
u8 SCCB_WR_Reg(u8 reg,u8 data);
u8 SCCB_RD_Reg(u8 reg);
#endif


2.1.3 OV7670模块初始化代码

1.OV7670.h
#ifndef _OV7670_H
#define _OV7670_H
#include "sys.h"
#include "sccb.h"
//
//本程序参考自网友guanfu_wang代码。
//ALIENTEK MiniSTM32开发板
//OV7670 驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/10/31
//版本:V1.0
//
#define OV7670_WRST		PCout(0)		//写指针复位
#define OV7670_RCK		PCout(5)		//读数据时钟
#define OV7670_RRST		PCout(1)  		//读指针复位
#define OV7670_CS		PCout(3)  		//片选信号(OE)
#define OV7670_WREN		PCout(2)		//写入FIFO使能
#define OV7670_VSYNC  	PCout(4)		//同步信号检测IO

#define OV7670_DATA   GPIOA->IDR&0x00FF  					//数据输入端口
/

u8   OV7670_Init(void);
void OV7670_Light_Mode(u8 mode);
void OV7670_Color_Saturation(u8 sat);
void OV7670_Brightness(u8 bright);
void OV7670_Contrast(u8 contrast);
void OV7670_Special_Effects(u8 eft);
void OV7670_Window_Set(u16 sx,u16 sy,u16 width,u16 height);


#endif


2.OV7670.c
#include "sys.h"
#include "ov7670.h"
#include "ov7670cfg.h"
#include "timer.h"
#include "delay.h"
#include "usart.h"
#include "sccb.h"
#include "exti.h"
//
//本程序参考自网友guanfu_wang代码。
//ALIENTEK MiniSTM32开发板
//OV7670 驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/10/31
//版本:V1.0
//

//初始化OV7670
//返回0:成功
//返回其他值:错误代码
u8 OV7670_Init(void)
{
    u8 temp;
    u16 i=0;
    //设置IO

    GPIO_InitTypeDef  GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);	 //使能相关端口时钟

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_5;				 // 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_5);


    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4; //PA15输入 上拉
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC,GPIO_Pin_4);

    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3|GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC,GPIO_Pin_3|GPIO_Pin_2);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;				 //LED0-->PB.5 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB.5

    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);	//SWD

    SCCB_Init();        		//初始化SCCB 的IO口
    if(SCCB_WR_Reg(0x12,0x80))return 1;	//复位SCCB
    delay_ms(50);
    //读取产品型号
    temp=SCCB_RD_Reg(0x0b);
    if(temp!=0x73)return 2;
    temp=SCCB_RD_Reg(0x0a);
    if(temp!=0x76)return 2;
    //初始化序列
    for(i=0; i<sizeof(ov7670_init_reg_tbl)/sizeof(ov7670_init_reg_tbl[0]); i++)
    {
        SCCB_WR_Reg(ov7670_init_reg_tbl[i][0],ov7670_init_reg_tbl[i][1]);
        delay_ms(2);
    }
    return 0x00; 	//ok
}

//OV7670功能设置
//白平衡设置
//0:自动
//1:太阳sunny
//2,阴天cloudy
//3,办公室office
//4,家里home
void OV7670_Light_Mode(u8 mode)
{
    u8 reg13val=0XE7;//默认就是设置为自动白平衡
    u8 reg01val=0;
    u8 reg02val=0;
    switch(mode)
    {
    case 1://sunny
        reg13val=0XE5;
        reg01val=0X5A;
        reg02val=0X5C;
        break;
    case 2://cloudy
        reg13val=0XE5;
        reg01val=0X58;
        reg02val=0X60;
        break;
    case 3://office
        reg13val=0XE5;
        reg01val=0X84;
        reg02val=0X4c;
        break;
    case 4://home
        reg13val=0XE5;
        reg01val=0X96;
        reg02val=0X40;
        break;
    }
    SCCB_WR_Reg(0X13,reg13val);//COM8设置
    SCCB_WR_Reg(0X01,reg01val);//AWB蓝色通道增益
    SCCB_WR_Reg(0X02,reg02val);//AWB红色通道增益
}
//色度设置
//0:-2
//1:-1
//2,0
//3,1
//4,2
void OV7670_Color_Saturation(u8 sat)
{
    u8 reg4f5054val=0X80;//默认就是sat=2,即不调节色度的设置
    u8 reg52val=0X22;
    u8 reg53val=0X5E;
    switch(sat)
    {
    case 0://-2
        reg4f5054val=0X40;
        reg52val=0X11;
        reg53val=0X2F;
        break;
    case 1://-1
        reg4f5054val=0X66;
        reg52val=0X1B;
        reg53val=0X4B;
        break;
    case 3://1
        reg4f5054val=0X99;
        reg52val=0X28;
        reg53val=0X71;
        break;
    case 4://2
        reg4f5054val=0XC0;
        reg52val=0X33;
        reg53val=0X8D;
        break;
    }
    SCCB_WR_Reg(0X4F,reg4f5054val);	//色彩矩阵系数1
    SCCB_WR_Reg(0X50,reg4f5054val);	//色彩矩阵系数2
    SCCB_WR_Reg(0X51,0X00);			//色彩矩阵系数3
    SCCB_WR_Reg(0X52,reg52val);		//色彩矩阵系数4
    SCCB_WR_Reg(0X53,reg53val);		//色彩矩阵系数5
    SCCB_WR_Reg(0X54,reg4f5054val);	//色彩矩阵系数6
    SCCB_WR_Reg(0X58,0X9E);			//MTXS
}
//亮度设置
//0:-2
//1:-1
//2,0
//3,1
//4,2
void OV7670_Brightness(u8 bright)
{
    u8 reg55val=0X00;//默认就是bright=2
    switch(bright)
    {
    case 0://-2
        reg55val=0XB0;
        break;
    case 1://-1
        reg55val=0X98;
        break;
    case 3://1
        reg55val=0X18;
        break;
    case 4://2
        reg55val=0X30;
        break;
    }
    SCCB_WR_Reg(0X55,reg55val);	//亮度调节
}
//对比度设置
//0:-2
//1:-1
//2,0
//3,1
//4,2
void OV7670_Contrast(u8 contrast)
{
    u8 reg56val=0X40;//默认就是contrast=2
    switch(contrast)
    {
    case 0://-2
        reg56val=0X30;
        break;
    case 1://-1
        reg56val=0X38;
        break;
    case 3://1
        reg56val=0X50;
        break;
    case 4://2
        reg56val=0X60;
        break;
    }
    SCCB_WR_Reg(0X56,reg56val);	//对比度调节
}
//特效设置
//0:普通模式
//1,负片
//2,黑白
//3,偏红色
//4,偏绿色
//5,偏蓝色
//6,复古
void OV7670_Special_Effects(u8 eft)
{
    u8 reg3aval=0X04;//默认为普通模式
    u8 reg67val=0XC0;
    u8 reg68val=0X80;
    switch(eft)
    {
    case 1://负片
        reg3aval=0X24;
        reg67val=0X80;
        reg68val=0X80;
        break;
    case 2://黑白
        reg3aval=0X14;
        reg67val=0X80;
        reg68val=0X80;
        break;
    case 3://偏红色
        reg3aval=0X14;
        reg67val=0Xc0;
        reg68val=0X80;
        break;
    case 4://偏绿色
        reg3aval=0X14;
        reg67val=0X40;
        reg68val=0X40;
        break;
    case 5://偏蓝色
        reg3aval=0X14;
        reg67val=0X80;
        reg68val=0XC0;
        break;
    case 6://复古
        reg3aval=0X14;
        reg67val=0XA0;
        reg68val=0X40;
        break;
    }
    SCCB_WR_Reg(0X3A,reg3aval);//TSLB设置
    SCCB_WR_Reg(0X68,reg67val);//MANU,手动U值
    SCCB_WR_Reg(0X67,reg68val);//MANV,手动V值
}
//设置图像输出窗口
//对QVGA设置。
void OV7670_Window_Set(u16 sx,u16 sy,u16 width,u16 height)
{
    u16 endx;
    u16 endy;
    u8 temp;
    endx=sx+width*2;	//V*2
    endy=sy+height*2;
    if(endy>784)endy-=784;
    temp=SCCB_RD_Reg(0X03);				//读取Vref之前的值
    temp&=0XF0;
    temp|=((endx&0X03)<<2)|(sx&0X03);
    SCCB_WR_Reg(0X03,temp);				//设置Vref的start和end的最低2位
    SCCB_WR_Reg(0X19,sx>>2);			//设置Vref的start高8位
    SCCB_WR_Reg(0X1A,endx>>2);			//设置Vref的end的高8位

    temp=SCCB_RD_Reg(0X32);				//读取Href之前的值
    temp&=0XC0;
    temp|=((endy&0X07)<<3)|(sy&0X07);
    SCCB_WR_Reg(0X17,sy>>3);			//设置Href的start高8位
    SCCB_WR_Reg(0X18,endy>>3);			//设置Href的end的高8位
}

2.1.4 FIFO的作用

OV7670带FIFO引脚定义

什么是FIFO?

FIFO: First in, First out

代表先进的数据先出 ,后进的数据后出。

为什么需要FIFO?

(1)典型的串口设计,发送/接收缓冲区只有1字节,每次发送/接收只能处理1帧数据。这样在单
片机中没什么问题,但是到复杂SoC中(一般有操作系统的)就会有问题,会导致效率低下,因
为CPU需要不断切换上下文。
(2)解决方案就是想办法扩展串口控制器的发送/接收缓冲区,譬如将发送/接收缓冲器设置为64
字节,CPU- -次过来直接给发送缓冲区64字节的待发送数据,然后transmitter慢慢发, 发完再找
CPU再要64字节。但是串口控制器本来的发送/接收缓冲区是固定的1字节长度的,所以做了个变
相的扩展,就是FIFO。
(3) FIFO就是first in first
out, 先进先出。fifo其实是一种数据结构,这里这个大的缓冲区叫FIF0是因为这个缓冲区的工
作方式类似于FIF0这种数据结构。

FIFO存储器是系统的缓冲环节,如果没有FIFO存储器,整个系统就不可能正常工作。

FIFO的功能可以概括为

(1)对连续的数据流进行缓存,防止在进机和存储操作时丢失数据

(2)数据集中起来进行进机和存储,可避免频繁的总线操作,减轻CPU的负担;

(3)允许系统进行DMA操作,提高数据的传输速度。这是至关重要的一点,如果不采用DMA操作,数据传输将达不到传输要求,而且大大增加CPU的负担,无法同时完成数据的存储工作。

FIFO引脚功能

解释一下,本模块没有用到PCLK和XCLK,已经有FIFO和OV7670自行配置好了。
SIOC和SIOD两条线是SCCB通信协议的时钟线和数据线,具体和IIC通信基本一样,通信过程自行了解。
HREF行同步信号基本不用它。
VSYNC帧同步信号,就是每次摄像头写出一幅图之前,拉高这个引脚告诉你,我要开始输出啦。
复位口和电源模式口直接接3v和GND就好,也可以接IO口控制,不过要注意,接IO口的话,引脚配置一点要放在OV7670寄存器配置前,不然直接给你复位了。(都是血泪···)
拍照闪光的不要
剩下的就是FIFO的控制IO了。
(录音机啥的都是比喻哈)
RCK就是你按录音机暂停键的信号,读一次数据给一个上升沿。
WR就是控制你录音机是否录音的IO,高电平时录音。
OE就是你录音机的电源键。
WRST就是写复位,相当于把录音机倒带到开始,录音时从磁带的开头往后记录。
RRST就是读复位,相当于吧录音机倒带,然后从头听。

一幅图像的读取

读取过程及其简单,我用录音机比喻的方式说:
/>>>(图像写入)录音过程
1.等待帧同步信号拉高
2.FIFO复位写指针(录音机倒带到磁带开头)
3.FIFO写允许(录音机按下录音键)
4.等待帧同步信号再次拉高(说明第二幅图到来,同时说明第一幅图写完了)
5.FIFO写禁止(停止录音)
/>>>读图过程(听录音)
1.FIFO读指针复位(录音机倒带到磁带开头)
2.FIFO给RCK(按下录音机播放键,这里假设录音机按一下放半句话,一句话代表一个像素)
3.读数据(听第一句话的上半句)
4.FIFO给RCK
5.读数据(听第一句话的下半句)
6.FIFO给RCK
7.读数据(听第二句话的上半句)
8.FIFO给RCK
9.读数据(听第二句话的下半句)
·············如此循环读出全部像素
n.读完最后一个像素
结束,获得全部图像像素数据。
OV7670带FIFO入坑指南_weixin_42368395的博客-CSDN博客

2.2 霍尔电机模块

2.2.1 所用电机参数

JGA25-370直流减速电机 编码器测速码盘大功率大力矩平衡小车马达

这里可以看到减速比为21.3,额定电流0.5A

霍尔电机的空载转速指的是电机在未承受任何负载的情况下,以最大额定电压供电时的转速。在没有外部负载的情况下,电机只需克服自身的内部摩擦和惯性阻力,因此能够达到的最高转速即为空载转速。空载转速是对电机性能的一个重要指标,它通常以转/分钟(rpm)或转/秒(rps)来表示。

2.2.2 减速比

上面可以获取到减速比为21.3,分辨率根据淘宝的客服给的是234.4

转一分钟脉冲数量 = 280 RPM * 21.3 * 234.3

2.2.3 电机的控制

电机的控制核心其实就是控制电源端电压

TB6612驱动

电机驱动其实是一个功率放大器,把我们的输出功率进行功率放大之后输出给执行元件---电机,实现输出信号对执行元件的控制。驱动板的作用其实就是将单片机产生的控制信号转换位电机可以理解的电信号,并通过提高足够的电流和电压、以及保护电路等方式来保证电机的安全运转。

产品参数

  • 逻辑部分输入电压VCC3.3~5V
  • 驱动部分输入电压VM2.5~12V
  • 驱动电机路数:2通道
  • 单通道最大连续驱动电流:1.2A
  • 启动峰值:2A/3.2A(连续脉冲/单脉冲)
  • 接口方式:2.54mm间距排针

引脚说明

管脚映射

标号

名称

功能描述

1

DIR1

电机M1的方向控制引脚

3

PWM2

电机M2的速度控制引脚

4

DIR2

电机M2的方向控制引脚

5

GND

逻辑部分电源负极

6

VCC

逻辑部分电源正极

7

M1+

M1路电机输出1

8

M1-

M1路电机输出2

9

M2+

M2路电机输出1

10

M2-

M2路电机输出2

11

GND

电机电源负极

12

VM(<12V)

电机电源正极

  • 模块尺寸:20 × 19.5(mm)

TB6612有两个GND,这时一个GND接电源的地,一个GND接单片机的地。如果都接同一地的话,电流从正极出发,单片机会流进一个比较大的电流这种情况可能会对单片机造成损害。所以说一个GND接电源的地是为了保证电源可以回流,一个GND接单片机的地就是为了能够信号有一个共同参考。

基本的控制框图

链接:https://pan.baidu.com/s/1didnZ8RCCjAaLdO4iVBPdA?pwd=6666 
提取码:6666

猜你喜欢

转载自blog.csdn.net/qq_51519091/article/details/132502962