STM32完全学习——0V5640的JPEG模式采集

打印 上一主题 下一主题

主题 868|帖子 868|积分 2604

一、写在前面

我参考的是买开发板的时候,普中送的资料里面的源码,他那个是用标准库写的,我将他的代码移植到了HAL库,有一些不一样的地方。由于标准库和HAL库的差异造成的。
二、编程思路

首先初始化OV5640模块,使用的是SCCB总线,和I2C很像,具体的就不说了,再就是将OV5640设置成JPEG输出模式,然后就是调整OV5640输出的图像的大小。下来就是开启DMA传输。然后每捕获一帧图像,DCMI会产生一个帧中断,然后在中断里面处置处罚JPEG的数据,然后再回到主步伐,然后将图像数据通过串口发送出去,至于初始化那些CubMAX这个工具会帮我们做。
三、相干函数HAL库实现

我们的主步伐,主要用来开启DMA传输,而且将数据通过串口发送出去
  1. //JPEG测试
  2. //JPEG数据,通过串口1发送给电脑.
  3. void jpeg_test(void)
  4. {
  5.         u32 i,jpgstart,jpglen;
  6.         u8 *p;
  7.         u8 key,headok=0;
  8.         u8 effect=0,contrast=2;
  9.         u8 size = 2;                        //默认是QVGA 640*480尺寸
  10.         u8 msgbuf[15];                //消息缓存区
  11.         u8 res = 0;
  12.         //自动对焦初始化
  13.         OV5640_Focus_Init();
  14.        
  15.         OV5640_JPEG_Mode();                //JPEG模式
  16.        
  17.         OV5640_Light_Mode(0);        //自动模式
  18.         OV5640_Color_Saturation(3);//色彩饱和度0
  19.         OV5640_Brightness(4);        //亮度0
  20.         OV5640_Contrast(3);                //对比度0
  21.         OV5640_Sharpness(33);        //自动锐度
  22.         OV5640_Focus_Constant();//启动持续对焦
  23.         OV5640_OutSize_Set(4, 0, jpeg_img_size_tbl[size][0], jpeg_img_size_tbl[size][1]);//设置输出尺寸
  24.         DCMI_Start();                 //启动传输
  25.        
  26.         while(1)
  27.         {
  28.                
  29.                 if(jpeg_data_ok==1)        //已经采集完一帧图像了
  30.                 {  
  31.                         p = (u8*)jpeg_buf;
  32.                         jpglen=0;        //设置jpg文件大小为0
  33.                         headok=0;        //清除jpg头标记
  34.                         for(i=0; i<jpeg_data_len*4; i++) //查找0XFF,0XD8和0XFF,0XD9,获取jpg文件大小
  35.                         {
  36.                                
  37.                                 if((p[i]==0XFF) && (p[i+1]==0XD8))//找到FF D8
  38.                                 {
  39. //                                        printf("err3\n");
  40.                                         jpgstart = i;
  41.                                         headok = 1;        //标记找到jpg头(FF D8)
  42.                                 }
  43.                                 if((p[i]==0XFF) && (p[i+1]==0XD9) && headok)//找到头以后,再找FF D9
  44.                                 {
  45.                                         jpglen = i-jpgstart+2;
  46.                                         break;
  47.                                 }
  48.                         }
  49.                        
  50. //                        printf("err 89 7 6yu\n");
  51.                         if(jpglen)        //正常的jpeg数据
  52.                         {
  53. //                               
  54.                                 p += jpgstart;                        //偏移到0XFF,0XD8处
  55.                                 for(i=0; i<jpglen; i++)        //发送整个jpg文件
  56.                                 {
  57.                                         while((USART1->SR&0X40)==0);        //循环发送,直到发送完毕   
  58.                                         USART1->DR=p[i];   
  59.                                 }
  60.                         }
  61.                         DCMI_Start();
  62.                         jpeg_data_ok = 0;        //标记jpeg数据处理完了,可以让DMA去采集下一帧了.
  63.                 }       
  64.                 HAL_GPIO_TogglePin(GPIOF, LED0_Pin);
  65.         }     
  66. }
复制代码
 由于我这里的目标很单纯,以是有些参数直接就是定死的,先实现功能花里胡哨的功能,反面在调。
  1. void DCMI_Start(void)
  2. {
  3.         long tmp=0, num=0;
  4.         u16 temp = 0;
  5.         HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_CONTINUOUS, (u32)&jpeg_buf, jpeg_buf_size);
  6.        
  7. }
复制代码
 帧中断回调函数
  1. void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
  2. {
  3.         jpeg_data_process();         //jpeg数据处理       
  4. }
复制代码
 这个函数我改过,和普中的标准库,很不一样。由于在标准库里面,DMA使能和DCMI捕获他们两个是分开的,因此可以那样操作,但是在HAL库里面就不可,因此就做了如下更改。
  1. //处理JPEG数据
  2. //当采集完一帧JPEG数据后,调用此函数,切换JPEG BUF.开始下一帧采集.
  3. void jpeg_data_process(void)
  4. {
  5.         if(jpeg_data_ok == 0)        //jpeg数据还未采集完
  6.         {       
  7.                 HAL_DCMI_Stop(&hdcmi);
  8.                 jpeg_data_len = jpeg_buf_size-__HAL_DMA_GET_COUNTER(&hdma_dcmi);
  9.                 jpeg_data_ok = 1;                                 //标记JPEG数据采集完按成,等待其他函数处理
  10.         }
  11. }
复制代码
有了上面这些你会发现还不能正常运行,那是由于HAL库里面的题目,我发现我的代码虽然中断啥的都好着呢,但是传输的数据里面没有JPEG相干的头标记,然乎通过看源码发现,它里面处置处罚完之后直接将中断关闭了,但是呢没有清除中断的标记,我看其他的中断都将标记清晰了,然后就试着改了一下,发现果然可以正常,传输了。

 

 终极显示的图像

 虽然视频的刷新率很低很低,卡的要死,但是最起码可以显示,至于优化啥的那就自由发挥了。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天空闲话

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表