STM32——OV2640摄像头实验

一、硬件连接原理图

实物图:

 

二、OV2640驱动代码

1、SCCB_Init函数

//初始化SCCB接口
void SCCB_Init(void)
{
  GPIO_InitTypeDef GPIO_InitABC;
 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);//使能GPIO时钟
  
  GPIO_InitABC.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;//PD6,7
  GPIO_InitABC.GPIO_Mode=GPIO_Mode_OUT;//PD6,7推挽输出
  GPIO_InitABC.GPIO_OType=GPIO_OType_PP;//推挽输出
  GPIO_InitABC.GPIO_Speed=GPIO_Speed_50MHz;//50MHz
  GPIO_InitABC.GPIO_PuPd=GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOD,&GPIO_InitABC);//初始化

  GPIO_SetBits(GPIOD,GPIO_Pin_6|GPIO_Pin_7);
  SCCB_SDA_OUT();
}

2、OV2640_Init函数

u8 OV2640_Init(void)
{
  u16 i=0;
  u16 reg;
  GPIO_InitTypeDef GPIO_InitABC;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE);
  GPIO_InitABC.GPIO_Pinn=GPIO_Pin_9|GPIO_Pin_15;//PG9,15推挽输出
  GPIO_InitABC.GPIO_Mode=GPIO_Mode_OUT;//推挽输出
  GPIO_InitABC.GPIO_OType=GPIO_OType_PP;//推挽输出
  GPIo-InitABC.GPIO_Speed=GPIO_Speed_50MHz;//50MHz
  GPIO_InitABC.GPIO_PuPd=GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOG,&GPIO_InitABC);//初始化
  
  OV2640_PWDN=0;//POWER  ON
  delay_ms(10);
  OV2640_RST=0;//硬复位OV2640
  delay_ms(10);
  OV2640_RST=1;//结束复位
  SCCB_Init();//初始化SCCB的IO口
  SCCB_WR_Reg(OV2640_DSP_RA_DLMT,0x01);//操作sensor寄存器
  SCCB_WR_Reg(OV2640_SENSOR_COM7,0x80);//软复位OV2640
  delay_ms(50);
  reg=SCCB_RD_Reg(OV2640_SENSOR_MIDH);//读取厂家ID高八位
  reg<<=8;
  reg|=SCCB_RD_Reg(OV2640_SENSOR_MIDL);//读取厂家ID低八位
  if(reg!=OV2640_MID)
  {
    printf("MID:%d\r\n",reg);
    return 1;
  }
  reg=SCCB_RD_Reg(OV2640_SENSOR_PIDH);//读取厂家ID高八位
  reg<<=8;
  reg|=SCCB_RD_Reg(OV2640_SENSOR_PIDL);//读取厂家ID低八位
  if(reg!=OV2640_PID) 
  {
    printf("HID:%d\r\n",reg);
    return 2;
  }
  //
  for(i=0;i<sizeof(ov2640_uxga_init_reg_tbl)/2;i++)
  {
    SCCB_WR_Reg(ov2640_uxga_init_reg_tbl[i][0],ov2640_uxga_init_reg_tbl[i][1]);
  }
  return 0x00;//ok
}

3、OV2640_IPEG_Moed函数

//OV2640切换为JPEG模式
void OV2640_JPEG_Mode(void)
{
  u16 i=0;
  //设置:YUV422模式
  for(i=0;i<sizeof(ov2640_yuv422_reg_tbl)/2;i++)
  {
    SCCB_WR_Reg(ov2640_yuv422_reg_tbl[i][0],ov2640_yuv422_reg_tbl[i][1]);
  }
  //设置:输出JPEG数据
  for(i=0;i<(sizeof(ov2640_jpeg_reg_tbl)/2);i++)
  {
    SCCB_WR_Reg(ov2640_jpeg_reg_tbl[i][0],ov2640_jpeg_reg_tbl[i][1]);
  }
}

4、OV2640_RGB565_Mode函数

//OV2640切换为RGB565模式
void OV2640_RGB565_Mode(void)
{
  u16 i=0;
  //设置RGB565
  for(i=0;i<(sizeof(ov2640_rgb565_reg_tbl)/2);i++)
  {
    SCCB_WR_Reg(ov2640_rgb565_reg_tbl[i][0],ov2640_rgb565_reg_tbl[i][1]);
  }
}

5、OV2640_ImageWin_Set函数

/*设置图像开窗大小
由:OV2640_ImageSize_Set确定传感器输出分辨率大小
该函数则在这个范围上面进行开窗,用于OV2640_OutSize_Set的输出
注意:本函数的宽度和高度必须大于等于OV2640_OutSize_Set1函数的宽度和高度
OV2640_OutSize_Set设置的宽度和高度,根据本函数设置的宽度和高度,由DSP自动计算缩放比例,输出给外部设备。
width,height:宽度(对应:horizontal)和高度(对应:vertical)width和height都必须是四的倍数
返回值:0 设置成功  其它设置失败*/
u8 OV2640_ImageWin_Set(u16 offx,u16 offy,u16width,u16 height)
{
  u16 hsize;
  u16 vsize;
  u8 temp;
  if(width%4) return 1;
  if(height%4) return 2;
  hsize=width/4;
  vsize=height/4;
  SCCB_WR_Reg(0XFF,0X00);
  SCCB_WR_Reg(0XE0,0X04);
  SCCB_WR_Reg(0X51,hsize&0XFF);//设置H_SIZE的低八位
  SCCB_WR_Reg(0X52,vsize&0XFF);//设置V_SIZE的低八位
  SCCB_WR_Reg(0X53,offx&0XFF);//设置offx的低八位
  SCCB_WR_Reg(0X54,offy&0XFF);//设置offy的低八位
  temp=(vsize>>1)&0X80;
  temp|=(offy>>4)&0X70;
  temp|=(hsize>>5)&0X08;
  temp|=(offx>>8)&0X07;
  SCCB_WR_Reg(0X55,temp);//设置H_SIZE/V_SIZE/0FFX,0FFY的高位
  SCCB_WR_Reg(0X57,(hsize>>2)&0X80);//设置H_SIZE/V_SIZE/0FFX,0FFY的高位
  SCCB_WR_Reg(0XE0,0X00);
  return 0;
}

三、DCMI驱动代码

1、My_DCMI_Init函数(完成DCMI的初始化、中断的配置、IO口的配置)

2、DCMI_DMA_Init函数

该函数用来配置DMA,包含四个参数: DMA_Memory0BaseAddr、DMA_BufferSize、DMA_MemoryDataSize、DMA_MemoryInc

DMA_Memory0BaseAddr:存储器地址,存储摄像头数据的内存地址(也可以是外设地址)

DMA_BufferSize:存储器长度

DMA_MemoryDataSize:存储器位宽

DMA_MemoryInc:存储器增长方式(用SRAM则地址自增,用LCD则不用增加)

3、单纯初始化函数是无法启用DCMI的,需要再加一个开始函数(DCMI_Start),有开启就会有关闭,后面呢还有一个关闭函数(DCMI_STOP)

//DCMI启动传输
void DCMI_Start(void)
{
  LCD_SetCursor(0,0);
  LCD_WriteRAM_Prepare();//开始写入GRAM
  DMA_Cmd(DMA2_Stream1,ENABLE);//开启DMA2,Stream1
  DCMI_CaptureCmd(ENABLE);//DCMI捕获使能
}
//DCMI关闭传输
void DCMI_Stop(void)
{
  DCMI_CaptureCmd(DISABLE);//DCMI捕获使能关闭
  while(DCMI->CR&0X01);//等待传输结束
  DMA_Cmd(DMA2_Stream1,DISABLE);//关闭DMA2,Stream1
}

4、DCMI中断服务函数

void DCMI_IRQHandler(void)
{
  if(DCMI_GetITStatus(DCMI_IT_FRAME)==SET)//捕获到一帧图像
  {
    jpeg_data_process;//JPEG数据处理
    DCMI_ClearITPendingBit(DCMI_IT_FRAME);//清除帧中断
    LED1=!LED1;//LED取反
    ov_frame++;
  }
}

5、jpeg_data_process函数

//处理JPEG数据
//当采集完一帧JPEG数据后,调用此函数,切换JPEG BUF,开始下一帧采集
void jpeg_data_process(void)
{
  if(ov2640_mode)//只有在JPEG格式下才需要处理
  {
    if(jpeg_data_ok==0)//JPEG数据还未采集完
    {
      DMA_Cmd(DMA2_Stream1,DISABLE);//停止当前传输
      while(DMA_GetCmdStatus(DMA2_Stream1)!=DISABLE){}//等待DMA2_Stream1可配置
      jpeg_data_len=jpeg_buf_size-DMA_GetCurrDataCounter(DMA2_Stream1);//得到此次数据传输的长度
      jpeg_data_ok=1;//标记JPEG数据采集完成,等待其他函数处理
    }
    if(jpeg_data_ok==2)//上一次的JPEG数据已经被处理
    {
      DMA2_Stream1->NDTR=jpeg_buf_size;
      DMA_SetCurrDataCounter(DMA2_Stream1,jpeg_buf_size);//传输长度为jpeg_buf_size*4字节
      DMA_Cmd(DMA2_Stream1,ENABLE);//重新传输
      jpeg_data_ok=0;//标记数据未采集
    }
  }
}

  • 7
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32103单片机读写OV2640 摄像头模块驱动测试程序工程源码,可以做为你的学习设计参考。 int main(void) { u8 res; u8 *pname; //带路径的文件名 u8 key; //键值 u8 sd_ok=1; //0,sd卡不正常;1,SD卡正常. u16 pixcnt=0; //像素统计 u16 linecnt=0; //行数统计 Stm32_Clock_Init(9); //系统时钟设置 uart_init(72,115200); //串口初始化为115200 delay_init(72); //延时初始化 usmart_dev.init(72); //初始化USMART LED_Init(); //初始化与LED连接的硬件接口 KEY_Init(); //初始化按键 LCD_Init(); //初始化LCD BEEP_Init(); //蜂鸣器初始化 W25QXX_Init(); //初始化W25Q128 my_mem_init(SRAMIN); //初始化内部内存池 exfuns_init(); //为fatfs相关变量申请内存 f_mount(fs[0],"0:",1); //挂载SD卡 f_mount(fs[1],"1:",1); //挂载FLASH. POINT_COLOR=RED; while(font_init()) //检查字库 { LCD_ShowString(30,50,200,16,16,"Font Error!"); delay_ms(200); LCD_Fill(30,50,240,66,WHITE);//清除显示 } Show_Str(30,50,200,16,"STM32F103 开发板",16,0); Show_Str(30,70,200,16,"OV2640照相机实验",16,0); Show_Str(30,90,200,16,"KEY0:拍照(bmp格式)",16,0); Show_Str(30,110,200,16,"KEY1:拍照(jpg格式)",16,0); Show_Str(30,130,200,16,"2015年4月16日",16,0); res=f_mkdir("0:/PHOTO"); //创建PHOTO文件夹 if(res!=FR_EXIST&&res!=FR_OK) //发生了错误 { Show_Str(30,150,240,16,"SD卡错误,无法拍照!",16,0); sd_ok=0; } ov2640_framebuf=mymalloc(SRAMIN,52*1024);//申请帧缓存 pname=mymalloc(SRAMIN,30); //为带路径的文件名分配30个字节的内存 while(!pname||!ov2640_framebuf) //内存分配出错 { Show_Str(30,150,240,16,"内存分配失败!",16,0); delay_ms(200); LCD_Fill(30,150,240,146,WHITE);//清除显示 delay_ms(200); } while(OV2640_Init()) //初始化OV2640 { Show_Str(30,150,240,16,"OV2640 错误!",16,0); delay_ms(200); LCD_Fill(30,150,239,206,WHITE); delay_ms(200); } Show_Str(30,170,200,16,"OV2640 正常",16,0); delay_ms(1500); //TIM6_Int_Init(10000,7199); //10Khz计数频率,1秒钟中断,屏蔽则不打印帧率 OV2640_RGB565_Mode(); //RGB565模式 OV2640_OutSize_Set(lcddev.width,lcddev.height); ov2640_sp
OV2640是一种CMOS图像传感器,常用于数字摄像头。它具有200万像素,支持JPEG压缩格式,适用于在嵌入式系统中进行图像采集和处理。 STM32F103是一款32位ARM Cortex-M3内核的微控制器。它具有丰富的外设和强大的处理能力,是嵌入式系统开发中常用的控制器之一。 要在STM32F103上使用OV2640摄像头,首先需要连接它们之间的硬件接口。一般来说,OV2640摄像头需要通过I2C总线与STM32F103通信,以配置图像传感器的参数和获取图像数据。在连接完成后,我们可以编写代码来控制OV2640摄像头STM32F103之间的通信。 在编程方面,我们可以使用STM32的相关软件开发工具来编写代码。根据具体的应用需求,我们可以实现不同的功能,例如拍摄静态图像、录制视频、设置曝光时间和白平衡等。通过读取OV2640传感器的数据寄存器,我们可以采集摄像头的图像数据,并通过STM32的外设(例如SD卡或WiFi模块)将数据保存或传输到其他设备。 在开发过程中,需要注意一些常见的问题,例如硬件连接错误、摄像头驱动程序的编写和调试等。此外,为了实现更高性能的图像处理,可以借助STM32F103的DMA和硬件加速模块。 总而言之,OV2640摄像头STM32F103可以实现图像采集和处理的功能。通过适当的硬件连接和相应的编程,我们可以使用OV2640摄像头STM32F103上实现各种有趣的应用,如图像识别、监控系统等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值