找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4783|回复: 2
收起左侧

STM32 OV7670拍照程序

[复制链接]
ID:383374 发表于 2018-11-29 00:42 | 显示全部楼层 |阅读模式
基于OV7670拍照程序,100%可用

制作出来的实物图如下:
IMG.jpg

单片机源程序如下:
  1. #include "sys.h"
  2. #include "ov7670.h"
  3. #include "ov7670cfg.h"
  4. #include "timer.h"          
  5. #include "delay.h"
  6. #include "usart.h"                         
  7. #include "sccb.h"       
  8. #include "exti.h"

  9.             
  10. //初始化OV7670
  11. //返回0:成功
  12. //返回其他值:错误代码
  13. u8 OV7670_Init(void)
  14. {
  15.         u8 temp;
  16.         u16 i=0;          
  17.         //设置IO
  18.         GPIO_InitTypeDef  GPIO_InitStructure;
  19.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG|RCC_APB2Periph_AFIO, ENABLE);         //使能相关端口时钟

  20.         GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_8;         //PA8 输入 上拉
  21.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  22.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  23.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  24.         GPIO_SetBits(GPIOA,GPIO_Pin_8);
  25.                
  26.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;                                 // 端口配置
  27.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
  28.         GPIO_Init(GPIOB, &GPIO_InitStructure);
  29.         GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4);       

  30.        
  31.         GPIO_InitStructure.GPIO_Pin  = 0xff; //PC0~7 输入 上拉
  32.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  33.         GPIO_Init(GPIOC, &GPIO_InitStructure);
  34.          
  35.        
  36.   GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6;  
  37.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  38.         GPIO_Init(GPIOD, &GPIO_InitStructure);
  39.         GPIO_SetBits(GPIOD,GPIO_Pin_6);
  40.        
  41.         GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_14|GPIO_Pin_15;  
  42.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  43.         GPIO_Init(GPIOG, &GPIO_InitStructure);
  44.         GPIO_SetBits(GPIOG,GPIO_Pin_14|GPIO_Pin_15);
  45.        
  46.   GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);        //SWD

  47.         SCCB_Init();                        //初始化SCCB 的IO口                     
  48.         if(SCCB_WR_Reg(0x12,0x80))return 1;        //复位SCCB          
  49.         delay_ms(50);  
  50.         //读取产品型号
  51.         temp=SCCB_RD_Reg(0x0b);   
  52.         if(temp!=0x73)return 2;  
  53.         temp=SCCB_RD_Reg(0x0a);   
  54.         if(temp!=0x76)return 2;
  55.         //初始化序列          
  56.         for(i=0;i<sizeof(ov7670_init_reg_tbl)/sizeof(ov7670_init_reg_tbl[0]);i++)
  57.         {
  58.                    SCCB_WR_Reg(ov7670_init_reg_tbl[i][0],ov7670_init_reg_tbl[i][1]);
  59.           }
  60.            return 0x00;         //ok
  61. }
  62. ////////////////////////////////////////////////////////////////////////////
  63. //OV7670功能设置
  64. //白平衡设置
  65. //0:自动
  66. //1:太阳sunny
  67. //2,阴天cloudy
  68. //3,办公室office
  69. //4,家里home
  70. void OV7670_Light_Mode(u8 mode)
  71. {
  72.         u8 reg13val=0XE7;//默认就是设置为自动白平衡
  73.         u8 reg01val=0;
  74.         u8 reg02val=0;
  75.         switch(mode)
  76.         {
  77.                 case 1://sunny
  78.                         reg13val=0XE5;
  79.                         reg01val=0X5A;
  80.                         reg02val=0X5C;
  81.                         break;       
  82.                 case 2://cloudy
  83.                         reg13val=0XE5;
  84.                         reg01val=0X58;
  85.                         reg02val=0X60;
  86.                         break;       
  87.                 case 3://office
  88.                         reg13val=0XE5;
  89.                         reg01val=0X84;
  90.                         reg02val=0X4c;
  91.                         break;       
  92.                 case 4://home
  93.                         reg13val=0XE5;
  94.                         reg01val=0X96;
  95.                         reg02val=0X40;
  96.                         break;       
  97.         }
  98.         SCCB_WR_Reg(0X13,reg13val);//COM8设置
  99.         SCCB_WR_Reg(0X01,reg01val);//AWB蓝色通道增益
  100.         SCCB_WR_Reg(0X02,reg02val);//AWB红色通道增益
  101. }                                  
  102. //色度设置
  103. //0:-2
  104. //1:-1
  105. //2,0
  106. //3,1
  107. //4,2
  108. void OV7670_Color_Saturation(u8 sat)
  109. {
  110.         u8 reg4f5054val=0X80;//默认就是sat=2,即不调节色度的设置
  111.         u8 reg52val=0X22;
  112.         u8 reg53val=0X5E;
  113.         switch(sat)
  114.         {
  115.                 case 0://-2
  116.                         reg4f5054val=0X40;           
  117.                         reg52val=0X11;
  118.                         reg53val=0X2F;                  
  119.                         break;       
  120.                 case 1://-1
  121.                         reg4f5054val=0X66;            
  122.                         reg52val=0X1B;
  123.                         reg53val=0X4B;          
  124.                         break;       
  125.                 case 3://1
  126.                         reg4f5054val=0X99;          
  127.                         reg52val=0X28;
  128.                         reg53val=0X71;          
  129.                         break;       
  130.                 case 4://2
  131.                         reg4f5054val=0XC0;          
  132.                         reg52val=0X33;
  133.                         reg53val=0X8D;          
  134.                         break;       
  135.         }
  136.         SCCB_WR_Reg(0X4F,reg4f5054val);        //色彩矩阵系数1
  137.         SCCB_WR_Reg(0X50,reg4f5054val);        //色彩矩阵系数2
  138.         SCCB_WR_Reg(0X51,0X00);                        //色彩矩阵系数3  
  139.         SCCB_WR_Reg(0X52,reg52val);                //色彩矩阵系数4
  140.         SCCB_WR_Reg(0X53,reg53val);                //色彩矩阵系数5
  141.         SCCB_WR_Reg(0X54,reg4f5054val);        //色彩矩阵系数6  
  142.         SCCB_WR_Reg(0X58,0X9E);                        //MTXS
  143. }
  144. //亮度设置
  145. //0:-2
  146. //1:-1
  147. //2,0
  148. //3,1
  149. //4,2
  150. void OV7670_Brightness(u8 bright)
  151. {
  152.         u8 reg55val=0X00;//默认就是bright=2
  153.           switch(bright)
  154.         {
  155.                 case 0://-2
  156.                         reg55val=0XB0;                  
  157.                         break;       
  158.                 case 1://-1
  159.                         reg55val=0X98;                  
  160.                         break;       
  161.                 case 3://1
  162.                         reg55val=0X18;                  
  163.                         break;       
  164.                 case 4://2
  165.                         reg55val=0X30;                  
  166.                         break;       
  167.         }
  168.         SCCB_WR_Reg(0X55,reg55val);        //亮度调节
  169. }
  170. //对比度设置
  171. //0:-2
  172. //1:-1
  173. //2,0
  174. //3,1
  175. //4,2
  176. void OV7670_Contrast(u8 contrast)
  177. {
  178.         u8 reg56val=0X40;//默认就是contrast=2
  179.           switch(contrast)
  180.         {
  181.                 case 0://-2
  182.                         reg56val=0X30;                  
  183.                         break;       
  184.                 case 1://-1
  185.                         reg56val=0X38;                  
  186.                         break;       
  187.                 case 3://1
  188.                         reg56val=0X50;                  
  189.                         break;       
  190.                 case 4://2
  191.                         reg56val=0X60;                  
  192.                         break;       
  193.         }
  194.         SCCB_WR_Reg(0X56,reg56val);        //对比度调节
  195. }
  196. //特效设置
  197. //0:普通模式   
  198. //1,负片
  199. //2,黑白   
  200. //3,偏红色
  201. //4,偏绿色
  202. //5,偏蓝色
  203. //6,复古            
  204. void OV7670_Special_Effects(u8 eft)
  205. {
  206.         u8 reg3aval=0X04;//默认为普通模式
  207.         u8 reg67val=0XC0;
  208.         u8 reg68val=0X80;
  209.         switch(eft)
  210.         {
  211.                 case 1://负片
  212.                         reg3aval=0X24;
  213.                         reg67val=0X80;
  214.                         reg68val=0X80;
  215.                         break;       
  216.                 case 2://黑白
  217.                         reg3aval=0X14;
  218.                         reg67val=0X80;
  219.                         reg68val=0X80;
  220.                         break;       
  221.                 case 3://偏红色
  222.                         reg3aval=0X14;
  223.                         reg67val=0Xc0;
  224.                         reg68val=0X80;
  225.                         break;       
  226.                 case 4://偏绿色
  227.                         reg3aval=0X14;
  228.                         reg67val=0X40;
  229.                         reg68val=0X40;
  230.                         break;       
  231.                 case 5://偏蓝色
  232.                         reg3aval=0X14;
  233.                         reg67val=0X80;
  234.                         reg68val=0XC0;
  235.                         break;       
  236.                 case 6://复古
  237.                         reg3aval=0X14;
  238.                         reg67val=0XA0;
  239.                         reg68val=0X40;
  240.                         break;         
  241.         }
  242.         SCCB_WR_Reg(0X3A,reg3aval);//TSLB设置
  243.         SCCB_WR_Reg(0X68,reg67val);//MANU,手动U值
  244.         SCCB_WR_Reg(0X67,reg68val);//MANV,手动V值
  245. }       
  246. //设置图像输出窗口
  247. //对QVGA设置。
  248. void OV7670_Window_Set(u16 sx,u16 sy,u16 width,u16 height)
  249. {
  250.         u16 endx;
  251.         u16 endy;
  252.         u8 temp;
  253.         endx=sx+width*2;        //V*2
  254.         endy=sy+height*2;
  255.         if(endy>784)endy-=784;
  256.         temp=SCCB_RD_Reg(0X03);                                //读取Vref之前的值
  257.         temp&=0XF0;
  258.         temp|=((endx&0X03)<<2)|(sx&0X03);
  259.         SCCB_WR_Reg(0X03,temp);                                //设置Vref的start和end的最低2位
  260.         SCCB_WR_Reg(0X19,sx>>2);                        //设置Vref的start高8位
  261.         SCCB_WR_Reg(0X1A,endx>>2);                        //设置Vref的end的高8位

  262.         temp=SCCB_RD_Reg(0X32);                                //读取Href之前的值
  263.         temp&=0XC0;
  264.         temp|=((endy&0X07)<<3)|(sy&0X07);
  265.         SCCB_WR_Reg(0X17,sy>>3);                        //设置Href的start高8位
  266.         SCCB_WR_Reg(0X18,endy>>3);                        //设置Href的end的高8位
  267. }
复制代码


  1. #include "sys.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "led.h"                           
  5. #include "lcd.h"  
  6. #include "key.h"     
  7. #include "usmart.h"
  8. #include "malloc.h"
  9. #include "sdio_sdcard.h"  
  10. #include "w25qxx.h"   
  11. #include "ff.h"  
  12. #include "exfuns.h"   
  13. #include "text.h"
  14. #include "piclib.h"        
  15. #include "string.h"               
  16. #include "math.h"         
  17. #include "ov7670.h"
  18. #include "beep.h"
  19. #include "timer.h"
  20. #include "exti.h"



  21. extern u8 ov_sta;        //在exit.c里面定义
  22. extern u8 ov_frame;        //在timer.c里面定义           
  23. //更新LCD显示
  24. void camera_refresh(void)
  25. {
  26.         u32 j;
  27.          u16 color;         
  28.         if(ov_sta)//有帧中断更新?
  29.         {
  30.                 LCD_Scan_Dir(U2D_L2R);                //从上到下,从左到右  
  31.                 if(lcddev.id==0X1963)LCD_Set_Window((lcddev.width-240)/2,(lcddev.height-320)/2,240,320);//将显示区域设置到屏幕中央
  32.                 else if(lcddev.id==0X5510||lcddev.id==0X5310)LCD_Set_Window((lcddev.width-320)/2,(lcddev.height-240)/2,320,240);//将显示区域设置到屏幕中央
  33.                 LCD_WriteRAM_Prepare();     //开始写入GRAM        
  34.                 OV7670_RRST=0;                                //开始复位读指针
  35.                 OV7670_RCK_L;
  36.                 OV7670_RCK_H;
  37.                 OV7670_RCK_L;
  38.                 OV7670_RRST=1;                                //复位读指针结束
  39.                 OV7670_RCK_H;
  40.                 for(j=0;j<76800;j++)
  41.                 {
  42.                         OV7670_RCK_L;
  43.                         color=GPIOC->IDR&0XFF;        //读数据
  44.                         OV7670_RCK_H;
  45.                         color<<=8;  
  46.                         OV7670_RCK_L;
  47.                         color|=GPIOC->IDR&0XFF;        //读数据
  48.                         OV7670_RCK_H;
  49.                         LCD->LCD_RAM=color;   
  50.                 }                                                            
  51.                  ov_sta=0;                                        //清零帧中断标记
  52.                 ov_frame++;
  53.                 LCD_Scan_Dir(DFT_SCAN_DIR);        //恢复默认扫描方向
  54.         }
  55. }           
  56. //文件名自增(避免覆盖)
  57. //组合成:形如"0:PHOTO/PIC13141.bmp"的文件名
  58. void camera_new_pathname(u8 *pname)
  59. {         
  60.         u8 res;                                         
  61.         u16 index=0;
  62.         while(index<0XFFFF)
  63.         {
  64.                 sprintf((char*)pname,"0:PHOTO/PIC%05d.bmp",index);
  65.                 res=f_open(ftemp,(const TCHAR*)pname,FA_READ);//尝试打开这个文件
  66.                 if(res==FR_NO_FILE)break;                //该文件名不存在=正是我们需要的.
  67.                 index++;
  68.         }
  69. }



  70. int main(void)
  71. {         
  72.         u8 res;                                                         
  73.         u8 *pname;                                //带路径的文件名
  74.         u8 key;                                        //键值                  
  75.         u8 i;                                                
  76.         u8 sd_ok=1;                                //0,sd卡不正常;1,SD卡正常.
  77.          
  78.         delay_init();                     //延时函数初始化         
  79.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
  80.         uart_init(115200);                 //串口初始化为115200
  81.          usmart_dev.init(72);                //初始化USMART               
  82.          LED_Init();                                          //初始化与LED连接的硬件接口
  83.         KEY_Init();                                        //初始化按键
  84.         LCD_Init();                                           //初始化LCD  
  85.         BEEP_Init();                        //蜂鸣器初始化         
  86.         W25QXX_Init();                                //初始化W25Q128
  87.          my_mem_init(SRAMIN);                //初始化内部内存池
  88.         exfuns_init();                                //为fatfs相关变量申请内存  
  89.          f_mount(fs[0],"0:",1);                 //挂载SD卡
  90.          f_mount(fs[1],"1:",1);                 //挂载FLASH.
  91.         POINT_COLOR=RED;      
  92.          while(font_init())                                 //检查字库
  93.         {            
  94.                 LCD_ShowString(30,50,200,16,16,"Font Error!");
  95.                 delay_ms(200);                                 
  96.                 LCD_Fill(30,50,240,66,WHITE);//清除显示            
  97.         }           
  98.          Show_Str(30,50,200,16,"战舰STM32F1开发板",16,0);                                             
  99.         Show_Str(30,70,200,16,"照相机实验",16,0);                                             
  100.         Show_Str(30,90,200,16,"KEY0:拍照",16,0);                                             
  101.         Show_Str(30,110,200,16,"正点原子@ALIENTEK",16,0);                                             
  102.         Show_Str(30,130,200,16,"2015年1月20日",16,0);
  103.         res=f_mkdir("0:/PHOTO");                //创建PHOTO文件夹
  104.         if(res!=FR_EXIST&&res!=FR_OK)         //发生了错误
  105.         {                    
  106.                 Show_Str(30,150,240,16,"SD卡错误!",16,0);
  107.                 delay_ms(200);                                 
  108.                 Show_Str(30,170,240,16,"拍照功能将不可用!",16,0);
  109.                 sd_ok=0;         
  110.         }else
  111.         {
  112.                 Show_Str(30,150,240,16,"SD卡正常!",16,0);
  113.                 delay_ms(200);                                 
  114.                 Show_Str(30,170,240,16,"KEY0:拍照",16,0);
  115.                 sd_ok=1;            
  116.         }                                                                                                                                       
  117.          pname=mymalloc(SRAMIN,30);        //为带路径的文件名分配30个字节的内存                    
  118.          while(pname==NULL)                        //内存分配出错
  119.          {            
  120.                 Show_Str(30,190,240,16,"内存分配失败!",16,0);
  121.                 delay_ms(200);                                 
  122.                 LCD_Fill(30,190,240,146,WHITE);//清除显示            
  123.                 delay_ms(200);                                 
  124.         }                                                                                             
  125.         while(OV7670_Init())//初始化OV7670
  126.         {
  127.                 Show_Str(30,190,240,16,"OV7670 错误!",16,0);
  128.                 delay_ms(200);
  129.             LCD_Fill(30,190,239,206,WHITE);
  130.                 delay_ms(200);
  131.         }
  132.          Show_Str(30,190,200,16,"OV7670 正常",16,0);
  133.         delay_ms(1500);                          
  134.         TIM6_Int_Init(10000,7199);                        //10Khz计数频率,1秒钟中断                                                                          
  135.         EXTI8_Init();                                                //使能定时器捕获
  136.         OV7670_Window_Set(12,176,240,320);        //设置窗口         
  137.           OV7670_CS=0;        
  138.         LCD_Clear(BLACK);
  139.          while(1)
  140.         {        
  141.                 key=KEY_Scan(0);//不支持连按
  142.                 if(key==KEY0_PRES)
  143.                 {
  144.                         if(sd_ok)
  145.                         {
  146.                                 LED1=0;        //点亮DS1,提示正在拍照
  147.                                 camera_new_pathname(pname);//得到文件名                    
  148.                                 if(bmp_encode(pname,(lcddev.width-240)/2,(lcddev.height-320)/2,240,320,0))//拍照有误
  149.                                 {
  150.                                         Show_Str(40,130,240,12,"写入文件错误!",12,0);                 
  151.                                 }else
  152.                                 {
  153.                                         Show_Str(40,130,240,12,"拍照成功!",12,0);
  154.                                         Show_Str(40,150,240,12,"保存为:",12,0);
  155.                                          Show_Str(40+42,150,240,12,pname,12,0);                    
  156.                                          BEEP=1;        //蜂鸣器短叫,提示拍照完成
  157.                                         delay_ms(100);
  158.                                  }
  159.                         }else //提示SD卡错误
  160.                         {                                            
  161.                                 Show_Str(40,130,240,12,"SD卡错误!",12,0);
  162.                                  Show_Str(40,150,240,12,"拍照功能不可用!",12,0);                           
  163.                          }
  164.                           BEEP=0;//关闭蜂鸣器
  165.                         LED1=1;//关闭DS1
  166.                         delay_ms(1800);//等待1.8秒钟
  167.                         LCD_Clear(BLACK);
  168.                 }else delay_ms(5);
  169.                  camera_refresh();//更新显示
  170.                 i++;
  171.                 if(i==40)//DS0闪烁.
  172.                 {
  173.                         i=0;
  174.                         LED0=!LED0;
  175.                  }
  176.         }                                                                                               
  177. }
复制代码

所有资料51hei提供下载:
OV7670照相.rar (1.65 MB, 下载次数: 99)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:435355 发表于 2018-12-21 19:45 | 显示全部楼层
请问楼主的摄像头是带有fifo吗,是什么型号的?
回复

使用道具 举报

ID:561209 发表于 2019-6-12 19:53 | 显示全部楼层
请问楼主的摄像头是带有fifo吗,是什么型号的?
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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