前言:STM32F407ZGT6控制OV2640下采集到JPG圖片格式的二進(jìn)制數(shù)據(jù),然后對二進(jìn)制數(shù)據(jù)進(jìn)行BASE64編碼,接著通過串口將數(shù)據(jù)傳輸給ESP8266并上傳至訓(xùn)練好的EASYDL的AI算法識別平臺進(jìn)行識別并返回垃圾種類與邊緣信息。
STM32與ov2640
ov2640簡紹
stm32f407zgt6之dcmi
stm32f407zgt6代碼
main.c
main.h
led.c
led.h
key.c
key.h
systic.c
systic.h
uart.c
uart.h
dcmi.c
dcmi.h
ov2640.c
ov2640.h
sccb.c
sccb.h
time.c
time.h
sys.c
sys.h
ov2640cfg.c
ov2640cfg.h
base64.c
base64.h
uart_2.c
uart_2.h
STM32與ESP8266
arduino中代碼
ESP8266與EasyDL
一、STM32與OV2640(庫函數(shù)版本)
1、OV2640簡紹
OV2640是ALIENTEK 推出的一款 200W 像素高清攝像頭模塊。該模塊采用 OmniVision 公司生產(chǎn)的一顆 1/4 寸的 CMOS UXGA(1632*1232)圖像傳感器:OV2640。ATK-OV2640 模塊采用該 OV2640 感器 作為核心部件,集成有源晶振和 LDO,接口簡單,使用非常方便。 ATK-OV2640 模塊的特點如下: 1.高靈敏度、低電壓適合嵌入式應(yīng)用 2.標(biāo)準(zhǔn)的 SCCB 接口,兼容 IIC 接口 3.支持 RawRGB、RGB(RGB565/RGB555)、GRB422、YUV(422/420)和 YCbCr(422) 輸出格式 4.支持 UXGA、SXGA、SVGA 以及按比例縮小到從 SXGA 到 40*30 的任何尺寸 5.支持自動曝光控制、自動增益控制、自動白平衡、自動消除燈光條紋、自動黑電平 校準(zhǔn)等自動控制功能。同時支持色飽和度、色相、伽馬、銳度等設(shè)置。 6.支持圖像縮放、平移和窗口設(shè)置 7.支持圖像壓縮,即可輸出 JPEG 圖像數(shù)據(jù) 8.自帶嵌入式微處理器 9.集成有源晶振,無需外部提供時鐘 10.集成 LDO,僅需提供 3.3V 電源即可正常工作

(一)OV2640原理圖
OV2640模塊自帶了 1.3V 和 2.8V 的穩(wěn)壓芯片,給 OV2640 供電,因此外 部僅需提供 3.3V 電壓 即可;同時自帶了一個 12M 的有源晶振,所以模塊不需要外部提供時 鐘。
2、STM32F407ZGT6之DCMI
STM32F407ZGT6 自帶了一個數(shù)字?jǐn)z像頭(DCMI)接口,該接口是一個同步并行接口,能夠 接收外部 8 位、10 位、12 位或 14 位 CMOS 攝像頭模塊發(fā)出的高速數(shù)據(jù)流??芍С植煌?的數(shù)據(jù)格式.
DCMI 接口是一個同步并行接口,可接收高速(可達(dá) 54 MB/s)數(shù)據(jù)流。該接口包含多達(dá) 14 條數(shù)據(jù)線和一條像素時鐘線(PIXCLK)。像素時鐘的極性可以編程,因此可以在像素時鐘的上升沿或下降沿捕獲數(shù)據(jù)。DCMI 接收到的攝像頭數(shù)據(jù)被放到一個 32 位數(shù)據(jù)寄存器(DCMI_DR)中,然后通過通用DMA 進(jìn)行傳輸。圖像緩沖區(qū)由 DMA 管理,而不是由攝像頭接口管理。
3、STM32F407ZGT6代碼
main.c文件
#include "main.h"
/*********************************************
*函數(shù)功能:處理JPEG數(shù)據(jù)
*函數(shù)形參:None
*函數(shù)返回值:None
*備注:當(dāng)采集完一幀JPEG數(shù)據(jù)后,調(diào)用此函數(shù),切換JPEG BUF.開始下一幀采集.
*********************************************/
void jpeg_data_process(void)
{
//jpeg數(shù)據(jù)還未采集完?
if(jpeg_data_ok==0)
{
//停止當(dāng)前傳輸
DMA_Cmd(DMA2_Stream1, DISABLE);
//等待DMA2_Stream1可配置
while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE)
{
;
}
//得到此次數(shù)據(jù)傳輸?shù)拈L度
jpeg_data_len=jpeg_buf_size-DMA_GetCurrDataCounter(DMA2_Stream1);
//標(biāo)記JPEG數(shù)據(jù)采集完按成,等待其他函數(shù)處理
jpeg_data_ok=1;
}
//上一次的jpeg數(shù)據(jù)已經(jīng)被處理了
if(jpeg_data_ok==2)
{
DMA2_Stream1->NDTR=jpeg_buf_size;
//傳輸長度為jpeg_buf_size*4字節(jié)
DMA_SetCurrDataCounter(DMA2_Stream1,jpeg_buf_size);
//重新傳輸
DMA_Cmd(DMA2_Stream1, ENABLE);
//標(biāo)記數(shù)據(jù)未采集
jpeg_data_ok=0;
}
}
/*********************************************
*函數(shù)功能:JPEG測試
*函數(shù)形參:None
*函數(shù)返回值:None
*備注:JPEG數(shù)據(jù),通過串口1發(fā)送給電腦.base64編碼后串口2發(fā)給esp8266
*********************************************/
void jpeg_test(void)
{
//u32 i;
u8 *p;
u32 a=0;
//base64表
char *base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//用于存放圖片數(shù)據(jù)
unsigned char counts[4*4690];
//用于分割數(shù)據(jù)
unsigned char counts_1[4690];
u16 count;
//默認(rèn)是QVGA 320*240尺寸 修改此值可以改變圖片分辨率大小
u8 size=3;
//消息緩存區(qū)
u8 msgbuf[15];
//串口打印當(dāng)前JPEG分辨率
sprintf((char*)msgbuf,"JPEG Size:%s",JPEG_SIZE_TBL[size]);
//JPEG模式
OV2640_JPEG_Mode();
//DCMI初始化
My_DCMI_Init();
//DCMI DMA初始化
DCMI_DMA_Init((u32)&jpeg_buf,jpeg_buf_size,DMA_MemoryDataSize_Word,DMA_MemoryInc_Enable);
//設(shè)置輸出尺寸
OV2640_OutSize_Set(jpeg_img_size_tbl[size][0],jpeg_img_size_tbl[size][1]);
//啟動傳輸
DCMI_Start();
while(1)
{
//已經(jīng)采集完一幀圖像了
if(jpeg_data_ok==1)
{
p=(u8*)jpeg_buf;
//取出第一個字符的前6位并找出對應(yīng)的結(jié)果字符
counts[count]=base64_table[p[a]>>2];
//將第一個字符的后位與第二個字符的前4位進(jìn)行組合并找到對應(yīng)的結(jié)果字符
counts[1+count]=base64_table[(p[a]&0x3)<<4 | (p[a+1]>>4)];
//將第二個字符的后4位與第三個字符的前2位組合并找出對應(yīng)的結(jié)果字符
counts[2+count]=base64_table[(p[a+1]&0xf)<<2 | (p[a+2]>>6)];
//取出第三個字符的后6位并找出結(jié)果字符
counts[3+count]=base64_table[p[a+2]&0x3f];
//3*8=4*6
count=count+4;
a=a+3;
p[3]=0xe0;//強(qiáng)行賦值
while(1){ //死循環(huán)進(jìn)行base64編碼
//取出第一個字符的前6位并找出對應(yīng)的結(jié)果字符
counts[count]=base64_table[p[a]>>2];
//將第一個字符的后位與第二個字符的前4位進(jìn)行組合并找到對應(yīng)的結(jié)果字符
counts[1+count]=base64_table[(p[a]&0x3)<<4 | (p[a+1]>>4)];
//將第二個字符的后4位與第三個字符的前2位組合并找出對應(yīng)的結(jié)果字符
counts[2+count]=base64_table[(p[a+1]&0xf)<<2 | (p[a+2]>>6)];
//取出第三個字符的后6位并找出結(jié)果字符
counts[3+count]=base64_table[p[a+2]&0x3f];
a=a+3;
count=count+4;
//若圖片編碼結(jié)束,跳出循環(huán)
if(p[a]==0&&p[a+1]==0&&p[a+2]==0&&p[a+3]==0&&p[a+4]==0&&p[a+5]==0&&p[a+6]==0&&p[a+7]==0&&p[a+8]==0)break;
}
//等待ESP8266
Delay_s(5);
? ? ? ? ? ? Uart2_Send_String("o");
Delay_s(2);
//分第一段
for(u32 i=0;i<(count/4);i++){
counts_1[i]=counts[i];
}
// printf("%s\r\n",counts_1);
Uart2_Send_String(counts_1);
Delay_s(2);
// 分第二段
for(u32 i=(count/4);i<((count/4)*2);i++){
counts_1[i-(count/4)]=counts[i];
}
//printf("%s\r\n",counts_1);
Uart2_Send_String(counts_1);
Delay_s(2);
// 分第三段
for(u32 i=((count/4)*2);i<((count/4)*3);i++){
counts_1[i-((count/4)*2)]=counts[i];
}
//printf("%s\r\n",counts_1);
Uart2_Send_String(counts_1);
Delay_s(2);
// 分第四段
for(u32 i=((count/4)*3);i<count+1;i++){
counts_1[i-((count/4)*3)]=counts[i];
}
//printf("%s\r\n",counts_1);
Uart2_Send_String(counts_1);
//printf("%s",counts);
//dma傳輸1次等于4字節(jié),所以乘以4.
//printf("%s",rev_buf_2);
//標(biāo)記jpeg數(shù)據(jù)處理完了,可以讓DMA去采集下一幀了.
jpeg_data_ok=2;
}
}
}
/*********************************************
*函數(shù)功能:主函數(shù)
*函數(shù)形參:None
*函數(shù)返回值:None
*備注:None
*********************************************/
int main(void)
{
// u8 t;
//設(shè)置系統(tǒng)中斷優(yōu)先級分組2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//初始化串口波特率為115200
Uart1_Init(115200);
//初始化串口2波特率為115200
Uart2_Init(115200);
//初始化LED
Led_Init();
//按鍵初始化
Key_Init();
//10Khz計數(shù),1秒鐘中斷一次
TIM3_Int_Init(10000-1,8400-1);
//初始化USMART
//usmart_dev.init(84);
//初始化OV2640
while(OV2640_Init())
{
printf("OV2640 ERR");
Delay_ms(200);
}
// printf("OV2640 OK");
while(1){
if(rev_ok_2 == 1){ //串口二接受到數(shù)據(jù)
rev_ok_2 = 0;
if(!strcmp((char *)rev_buf, "picture")){ //判斷接受到的數(shù)據(jù)是否為“picture”
jpeg_test();
//printf("%s",rev_buf_2);
}
}
}
}
main.h文件
#ifndef __MAIN_H_
#define __MAIN_H_
/********************頭文件************************/
#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "systick.h"
#include "uart.h"
#include "sys.h"
#include "uart_2.h"
#include "time.h"
#include "ov2640.h"
#include "dcmi.h"
#include "base64.h"
/********************宏定義************************/
extern uint8_t rev_buf_2[REV_BUF_LEN];
extern uint8_t rev_ok_2;
#define jpeg_buf_size 31*1024 //定義JPEG數(shù)據(jù)緩存jpeg_buf的大小(*4字節(jié))
__align(4) u32 jpeg_buf[jpeg_buf_size]; //JPEG數(shù)據(jù)緩存buf
volatile u32 jpeg_data_len=0; //buf中的JPEG有效數(shù)據(jù)長度
volatile u8 jpeg_data_ok=0; //JPEG數(shù)據(jù)采集完成標(biāo)志
//0,數(shù)據(jù)沒有采集完;
//1,數(shù)據(jù)采集完了,但是還沒處理;
//2,數(shù)據(jù)已經(jīng)處理完成了,可以開始下一幀接收
/*****************聲明外部變量*********************/
const u8*EFFECTS_TBL[7]={"Normal","Negative","B&W","Redish","Greenish","Bluish","Antique"}; //7種特效
const u8*JPEG_SIZE_TBL[9]={"QCIF","QQVGA","CIF","QVGA","VGA","SVGA","XGA","SXGA","UXGA"}; //JPEG圖片 9種尺寸
//JPEG尺寸支持列表
const u16 jpeg_img_size_tbl[][2]=
{
176,144, //QCIF
160,120, //QQVGA
352,288, //CIF
320,240, //QVGA
640,480, //VGA
800,600, //SVGA
1024,768, //XGA
1280,1024, //SXGA
1600,1200, //UXGA
};
/*******************函數(shù)聲明***********************/
void jpeg_test(void);
void jpeg_data_process(void);
void u32tostr(unsigned long dat,char *str);
#endif
led.c文件
#include "led.h"
/*********************************************
*函數(shù)功能:LED初始化
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: PF9 -- LED0
PF10 -- LED1 低電平燈亮
*********************************************/
void Led_Init(void)
{
//開啟GPIOF時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
//配置GPIO PF9和PF10推挽輸出
GPIO_InitTypeDef GPIO_InitStruct;
//輸出模式
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
//輸出類型:推挽
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
//引腳號
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
//上下拉 上拉
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
//輸出速度
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOF, &GPIO_InitStruct);
}
led.h文件
#ifndef __LED_H_
#define __LED_H_
/********************頭文件************************/
#include "stm32f4xx.h"
/********************宏定義************************/
#define LED0_ON GPIO_ResetBits(GPIOF, GPIO_Pin_9)
#define LED0_OFF GPIO_SetBits(GPIOF, GPIO_Pin_9)
#define LED1_ON GPIO_ResetBits(GPIOF, GPIO_Pin_10)
#define LED1_OFF GPIO_SetBits(GPIOF, GPIO_Pin_10)
/*****************聲明外部變量*********************/
/*******************函數(shù)聲明***********************/
void Led_Init(void);
#endif
key.c文件
#include "key.h"
/*********************************************
*函數(shù)功能:KEY初始化
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: KEY0 -- PE4
KEY1 -- PA0
高電平按鍵按下
*********************************************/
void Key_Init(void)
{
//開啟GPIOA,GPIOE時鐘
RCC->AHB1ENR |= (0x1 << 4);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//配置GPIO PA0和PE4浮空輸入
GPIO_InitTypeDef GPIO_InitStruct;
//PA0
//輸入模式
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
//引腳號
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
//無上下拉
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStruct);
//PE4
//輸入模式
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
//引腳號
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
//無上下拉
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOE, &GPIO_InitStruct);
}
/*********************************************
*函數(shù)功能:檢測按鍵是否按下
*函數(shù)形參:None
*函數(shù)返回值:按下的按鍵值
*備注:KEY0按下返回1
KEY1按下返回2
無按鍵按下返回0
*********************************************/
uint8_t Key_Scan(void)
{
if(KEY0 == 1){
//粗略延時10ms
Delay_Key(10);
if(KEY0 == 1){
return 1;
}
}
if(KEY1 == 1){
//粗略延時10ms
Delay_Key(10);
if(KEY1 == 1){
return 2;
}
}
return 0;
}
/*********************************************
*函數(shù)功能:粗略延時函數(shù)
*函數(shù)形參:延時ms值
*函數(shù)返回值:None
*備注:168MHz 168 000 000
*********************************************/
static void Delay_Key(uint16_t ms)
{
uint16_t i = 0;
uint16_t j = 0;
for(i = 0; i < ms; ++i)
{
for(j = 0; j < 1000; ++j)
{
uint8_t temp = 168;
while(temp--);
}
}
}
key.h
#ifndef __KEY_H_
#define __KEY_H_
/********************頭文件************************/
#include "stm32f4xx.h"
/********************宏定義************************/
#define KEY0 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)
#define KEY1 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)
/*****************聲明外部變量*********************/
/*******************函數(shù)聲明***********************/
void Key_Init(void);
uint8_t Key_Scan(void);
static void Delay_Key(uint16_t ms);
#endif
systick.c
#include "systick.h"
/*********************************************
*函數(shù)功能:Systick 1s定時
*函數(shù)形參:None
*函數(shù)返回值:None
*備注:21MHz時鐘源
*********************************************/
void Delay_1S(void)
{
Delay_ms(500);
Delay_ms(500);
}
/*********************************************
*函數(shù)功能:Systick s級定時
*函數(shù)形參:uint8_t s
*函數(shù)返回值:None
*備注:21MHz時鐘源
*********************************************/
void Delay_s(uint16_t s)
{
uint8_t i = 0;
for(i = 0; i < s; ++i){
Delay_1S();
}
}
/*********************************************
*函數(shù)功能:Systick ms級定時
*函數(shù)形參:uint16_t ms
*函數(shù)返回值:None
*備注:21MHz時鐘源 定時范圍0~1000
*********************************************/
void Delay_ms(uint16_t ms)
{
//控制定時范圍
if(ms > 1000){
ms = 1000;
}
if(ms > 500)
{
Delay_ms(ms - 500);
ms = 500;
}
//選擇Systick時鐘
SysTick->CTRL &= ~(0x1 << 2);
//設(shè)置重載值
SysTick->LOAD = 21000*ms;//24位遞減計數(shù)器 最大值16777216
//載入重載值
SysTick->VAL = 0;
//使能計數(shù)器
SysTick->CTRL |= (0x1 << 0);
//等待定時時間到
while(!(SysTick->CTRL & (0x1 << 16)));
//關(guān)閉定時器使能
SysTick->CTRL &= ~(0x1 << 0);
}
/*********************************************
*函數(shù)功能:Systick us級定時
*函數(shù)形參:uint16_t us
*函數(shù)返回值:None
*備注:21MHz時鐘源
*********************************************/
void Delay_us(uint16_t us)
{
//控制定時范圍
if(us > 1000){
us = 1000;
}
//選擇Systick時鐘
SysTick->CTRL &= ~(0x1 << 2);
//設(shè)置重載值
SysTick->LOAD = 21*us;//24位遞減計數(shù)器 最大值16777216
//載入重載值
SysTick->VAL = 0;
//使能計數(shù)器
SysTick->CTRL |= (0x1 << 0);
//等待定時時間到
while(!(SysTick->CTRL & (0x1 << 16)));
//關(guān)閉定時器使能
SysTick->CTRL &= ~(0x1 << 0);
}
/*********************************************
*函數(shù)功能:Systick 延時函數(shù)
*函數(shù)形參:uint16_t ys
*函數(shù)返回值:None
*備注:9MHz時鐘源 以毫秒為單位
*********************************************/
void Delay_Systick(uint16_t ys)
{
uint16_t s = 0;
uint16_t ms = 0;
s = ys/1000;
ms = ys%1000;
if(s){
Delay_s(s);
}
if(ms){
Delay_ms(ms);
}
}
systick.h文件
#ifndef __SYSTICK_H_
#define __SYSTICK_H_
/********************頭文件************************/
#include "stm32f4xx.h"
/********************宏定義************************/
/*****************聲明外部變量*********************/
/*******************函數(shù)聲明***********************/
void Delay_1S(void);
void Delay_s(uint16_t s);
void Delay_ms(uint16_t ms);
void Delay_us(uint16_t us);
void Delay_Systick(uint16_t ys);
#endif
uart.c文件
#include "uart.h"
/*********************************************
*函數(shù)功能:UART1初始化
*函數(shù)形參:uint32_t band 波特率
*函數(shù)返回值:None
*備注:PA9 -- TX
PA10 -- RX
*********************************************/
void Uart1_Init(uint32_t band)
{
//開啟GPIOA時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//開啟UART1時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//配置GPIO
//PA9和PA10為復(fù)用模式
GPIO_InitTypeDef GPIO_InitStruct;
//輸出模式
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
//引腳號
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
GPIO_Init(GPIOA, &GPIO_InitStruct);
//配置UART1
USART_InitTypeDef USART_InitStruct;
//波特率
USART_InitStruct.USART_BaudRate = band;
//禁止硬件流控
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//使能發(fā)送和接收
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
//關(guān)閉奇偶校驗
USART_InitStruct.USART_Parity = USART_Parity_No;
//1位停止位
USART_InitStruct.USART_StopBits = USART_StopBits_1;
//8位數(shù)據(jù)位
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &USART_InitStruct);
//使能接收中斷
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
//設(shè)置中斷優(yōu)先級 串口優(yōu)先級設(shè)置為最高,以防接收中被打斷
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(7-2, 0, 1));
//使能NVIC響應(yīng)
NVIC_EnableIRQ(USART1_IRQn);
//使能UART1
USART_Cmd(USART1, ENABLE);
}
uint8_t rev_buf[REV_BUF_LEN];
uint8_t rev_ok;
//編寫中斷服務(wù)函數(shù)
void USART1_IRQHandler(void)
{
static uint8_t i = 0;
//讀數(shù)據(jù)寄存器非空
if(USART1->SR & (0x1 << 5)){
rev_buf[i++] = USART1->DR;//讀取數(shù)據(jù)寄存器信息,清空標(biāo)志位
while(USART1->SR & (0x1 << 5));//等待標(biāo)志位清零
}else if(USART1->SR & (0x1 << 4)){//檢測到總線空閑
//清標(biāo)志位
if(USART1->SR)
;
if(USART1->DR)
;
while(USART1->SR & (0x1 << 4));//等待標(biāo)志位清零
rev_buf[i] = '\0';//字符串結(jié)尾
i = 0;
rev_ok = 1;//接收完成
}
}
/*********************************************
*函數(shù)功能:UART1發(fā)送字符串函數(shù)
*函數(shù)形參:uint8_t *str 要發(fā)送的字符串
*函數(shù)返回值:None
*備注:None
*********************************************/
void Uart1_Send_String(uint8_t *str)
{
while(*str){
//等待發(fā)送數(shù)據(jù)寄存器為空
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
USART_SendData(USART1, *str);
str++;
}
}
#pragma import(__use_no_semihosting_swi) //取消半主機(jī)狀態(tài)
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
int fputc(int ch, FILE *f) {
while((USART1->SR &(0X01<<7))==0);//等待發(fā)送緩沖區(qū)為空
USART1->DR=ch;
return (ch);
}
int ferror(FILE *f) {
/* Your implementation of ferror */
return EOF;
}
void _ttywrch(int ch) {
while((USART1->SR &(0X01<<7))==0);
USART1->DR=ch;
}
void _sys_exit(int return_code) {
label: goto label; /* endless loop */
}
uart.h文件
#ifndef __UART_H_
#define __UART_H_
/********************頭文件************************/
#include "stm32f4xx.h"
#include "stdio.h"
/********************宏定義************************/
#define REV_BUF_LEN (256)
/*****************聲明外部變量*********************/
extern uint8_t rev_buf[REV_BUF_LEN];
extern uint8_t rev_ok;
/*******************函數(shù)聲明***********************/
void Uart1_Init(uint32_t band);
void Uart1_Send_String(uint8_t *str);
#endif
dcmi.c文件
#include "dcmi.h"
u8 ov_frame=0; //幀率
/*********************************************
*函數(shù)功能:DCMI中斷服務(wù)函數(shù)
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: None
*********************************************/
void DCMI_IRQHandler(void)
{
//捕獲到一幀圖像
if(DCMI_GetITStatus(DCMI_IT_FRAME)==SET)
{
//jpeg數(shù)據(jù)處理
jpeg_data_process();
//清除幀中斷
DCMI_ClearITPendingBit(DCMI_IT_FRAME);
LED1_ON;
ov_frame++;
}
}
//DCMI DMA配置
//DMA_Memory0BaseAddr:存儲器地址 將要存儲攝像頭數(shù)據(jù)的內(nèi)存地址(也可以是外設(shè)地址)
//DMA_BufferSize:存儲器長度 0~65535
//DMA_MemoryDataSize:存儲器位寬
//DMA_MemoryDataSize:存儲器位寬 @defgroup DMA_memory_data_size :DMA_MemoryDataSize_Byte/DMA_MemoryDataSize_HalfWord/DMA_MemoryDataSize_Word
//DMA_MemoryInc:存儲器增長方式 @defgroup DMA_memory_incremented_mode /** @defgroup DMA_memory_incremented_mode : DMA_MemoryInc_Enable/DMA_MemoryInc_Disable
void DCMI_DMA_Init(u32 DMA_Memory0BaseAddr,u16 DMA_BufferSize,u32 DMA_MemoryDataSize,u32 DMA_MemoryInc)
{
DMA_InitTypeDef DMA_InitStructure;
//DMA2時鐘使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
DMA_DeInit(DMA2_Stream1);
//等待DMA2_Stream1可配置
while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE)
{
;
}
/* 配置 DMA Stream */
//通道1 DCMI通道
DMA_InitStructure.DMA_Channel = DMA_Channel_1;
//外設(shè)地址為:DCMI->DR
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&DCMI->DR;
//DMA 存儲器0地址
DMA_InitStructure.DMA_Memory0BaseAddr = DMA_Memory0BaseAddr;
//外設(shè)到存儲器模式
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
//數(shù)據(jù)傳輸量
DMA_InitStructure.DMA_BufferSize = DMA_BufferSize;
//外設(shè)非增量模式
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//存儲器增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc;
//外設(shè)數(shù)據(jù)長度:32位
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
//存儲器數(shù)據(jù)長度
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize;
// 使用循環(huán)模式
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
//高優(yōu)先級
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
//FIFO模式
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
//使用全FIFO
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
//外設(shè)突發(fā)單次傳輸
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
//存儲器突發(fā)單次傳輸
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
//初始化DMA Stream
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
}
/*********************************************
*函數(shù)功能:DCMI初始化
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: None
*********************************************/
void My_DCMI_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DCMI_InitTypeDef DCMI_InitStructure;
//使能GPIOA B C E 時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOE, ENABLE);
//使能DCMI時鐘
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI,ENABLE);
//PA4、PA6初始化設(shè)置
//PA4、PA6 復(fù)用功能輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_6;
//復(fù)用功能輸出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
//推挽輸出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//100MHz
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
//上拉
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
//初始化
GPIO_Init(GPIOA, &GPIO_InitStructure);
// PB6、PB7 復(fù)用功能輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_6;
//初始化
GPIO_Init(GPIOB, &GPIO_InitStructure);
//PC6/7/8/9/11 復(fù)用功能輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_11;
//初始化
GPIO_Init(GPIOC, &GPIO_InitStructure);
//PE5/6 復(fù)用功能輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;
//初始化
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource4,GPIO_AF_DCMI); //PA4,AF13 DCMI_HSYNC
GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_DCMI); //PA6,AF13 DCMI_PCLK
GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_DCMI); //PB7,AF13 DCMI_VSYNC
GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_DCMI); //PC6,AF13 DCMI_D0
GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_DCMI); //PC7,AF13 DCMI_D1
GPIO_PinAFConfig(GPIOC,GPIO_PinSource8,GPIO_AF_DCMI); //PC8,AF13 DCMI_D2
GPIO_PinAFConfig(GPIOC,GPIO_PinSource9,GPIO_AF_DCMI); //PC9,AF13 DCMI_D3
GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_DCMI);//PC11,AF13 DCMI_D4
GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_DCMI); //PB6,AF13 DCMI_D5
GPIO_PinAFConfig(GPIOE,GPIO_PinSource5,GPIO_AF_DCMI); //PE5,AF13 DCMI_D6
GPIO_PinAFConfig(GPIOE,GPIO_PinSource6,GPIO_AF_DCMI); //PE6,AF13 DCMI_D7
//清除原來的設(shè)置
DCMI_DeInit();
//連續(xù)模式
DCMI_InitStructure.DCMI_CaptureMode=DCMI_CaptureMode_Continuous;
//全幀捕獲
DCMI_InitStructure.DCMI_CaptureRate=DCMI_CaptureRate_All_Frame;
//8位數(shù)據(jù)格式
DCMI_InitStructure.DCMI_ExtendedDataMode= DCMI_ExtendedDataMode_8b;
//HSYNC 低電平有效
DCMI_InitStructure.DCMI_HSPolarity= DCMI_HSPolarity_Low;
//PCLK 上升沿有效
DCMI_InitStructure.DCMI_PCKPolarity= DCMI_PCKPolarity_Rising;
//硬件同步HSYNC,VSYNC
DCMI_InitStructure.DCMI_SynchroMode= DCMI_SynchroMode_Hardware;
//VSYNC 低電平有效
DCMI_InitStructure.DCMI_VSPolarity=DCMI_VSPolarity_Low;
DCMI_Init(&DCMI_InitStructure);
//開啟幀中斷
DCMI_ITConfig(DCMI_IT_FRAME,ENABLE);
//DCMI使能
DCMI_Cmd(ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;
//搶占優(yōu)先級1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
//子優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;
//IRQ通道使能
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//根據(jù)指定的參數(shù)初始化VIC寄存器、
NVIC_Init(&NVIC_InitStructure);
}
/*********************************************
*函數(shù)功能:DCMI,啟動傳輸
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: None
*********************************************/
void DCMI_Start(void)
{
//開啟DMA2,Stream1
DMA_Cmd(DMA2_Stream1, ENABLE);
//DCMI捕獲使能
DCMI_CaptureCmd(ENABLE);
}
/*********************************************
*函數(shù)功能:DCMI,關(guān)閉傳輸
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: None
*********************************************/
void DCMI_Stop(void)
{
//DCMI捕獲使關(guān)閉
DCMI_CaptureCmd(DISABLE);
//等待傳輸結(jié)束
while(DCMI->CR&0X01);
//關(guān)閉DMA2,Stream1
DMA_Cmd(DMA2_Stream1,DISABLE);
}
dcmi.h文件
#ifndef __DCMI_H_
#define __DCMI_H_
/********************頭文件************************/
#include "dcmi.h"
#include "led.h"
#include "ov2640.h"
/********************宏定義************************/
//u8 ov_frame=0; //幀率
/*****************聲明外部變量*********************/
/*******************函數(shù)聲明***********************/
extern void jpeg_data_process(void); //JPEG數(shù)據(jù)處理函數(shù)
void My_DCMI_Init(void);
void DCMI_DMA_Init(u32 DMA_Memory0BaseAddr,u16 DMA_BufferSize,u32 DMA_MemoryDataSize,u32 DMA_MemoryInc);
void DCMI_Start(void);
void DCMI_Stop(void);
#endif
ov2640.c文件
#include "ov2640.h"
/*********************************************
*函數(shù)功能:初始化OV2640
*函數(shù)形參:None
*函數(shù)返回值:返回值:0,成功 其他,錯誤代碼
*備注: 配置完以后,輸出默認(rèn)尺寸的圖片!
*********************************************/
u8 OV2640_Init(void)
{
u16 i=0;
u16 reg;
//配置IO
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
//GPIOG9,15初始化設(shè)置
//PG9,15推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_15;
//推挽輸出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
//推挽輸出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//50MHz
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//上拉
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
//初始化
GPIO_Init(GPIOG, &GPIO_InitStructure);
//POWER ON
OV2640_PWDN=0;
Delay_ms(10);
//復(fù)位OV2640
OV2640_RST=0;
Delay_ms(10);
//結(jié)束復(fù)位
OV2640_RST=1;
//初始化SCCB 的IO口
SCCB_Init();
//操作sensor寄存器
SCCB_WR_Reg(OV2640_DSP_RA_DLMT, 0x01);
//軟復(fù)位OV2640
SCCB_WR_Reg(OV2640_SENSOR_COM7, 0x80);
Delay_ms(50);
//讀取廠家ID 高八位
reg=SCCB_RD_Reg(OV2640_SENSOR_MIDH);
reg<<=8;
//讀取廠家ID 低八位
reg|=SCCB_RD_Reg(OV2640_SENSOR_MIDL);
if(reg!=OV2640_MID)
{
printf("MID:%d\r\n",reg);
return 1;
}
//讀取廠家ID 高八位
reg=SCCB_RD_Reg(OV2640_SENSOR_PIDH);
reg<<=8;
//讀取廠家ID 低八位
reg|=SCCB_RD_Reg(OV2640_SENSOR_PIDL);
if(reg!=OV2640_PID)
{
printf("HID:%d\r\n",reg);
return 2;
}
//初始化 OV2640,采用SXGA分辨率(1600*1200)
for(i=0;i<sizeof(ov2640_sxga_init_reg_tbl)/2;i++)
{
SCCB_WR_Reg(ov2640_sxga_init_reg_tbl[i][0],ov2640_sxga_init_reg_tbl[i][1]);
}
return 0x00; //ok
}
/*********************************************
*函數(shù)功能:OV2640切換為JPEG模式
*函數(shù)形參:None
*函數(shù)返回值:None
*備注:None
*********************************************/
void OV2640_JPEG_Mode(void)
{
u16 i=0;
//設(shè)置: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]);
}
//設(shè)置:輸出JPEG數(shù)據(jù)
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]);
}
}
/*********************************************
*函數(shù)功能:OV2640自動曝光等級設(shè)置
*函數(shù)形參:None
*函數(shù)返回值:None
*備注:level:0~4
*********************************************/
void OV2640_Auto_Exposure(u8 level)
{
u8 i;
u8 *p=(u8*)OV2640_AUTOEXPOSURE_LEVEL[level];
for(i=0;i<4;i++)
{
SCCB_WR_Reg(p[i*2],p[i*2+1]);
}
}
/*********************************************
*函數(shù)功能:白平衡設(shè)置
*函數(shù)形參:None
*函數(shù)返回值:None
*備注://0:自動
//1:太陽sunny
//2,陰天cloudy
//3,辦公室office
//4,家里home
*********************************************/
void OV2640_Light_Mode(u8 mode)
{
u8 regccval=0X5E;//Sunny
u8 regcdval=0X41;
u8 regceval=0X54;
switch(mode)
{
case 0://auto
SCCB_WR_Reg(0XFF,0X00);
SCCB_WR_Reg(0XC7,0X10);//AWB ON
return;
case 2://cloudy
regccval=0X65;
regcdval=0X41;
regceval=0X4F;
break;
case 3://office
regccval=0X52;
regcdval=0X41;
regceval=0X66;
break;
case 4://home
regccval=0X42;
regcdval=0X3F;
regceval=0X71;
break;
}
SCCB_WR_Reg(0XFF,0X00);
SCCB_WR_Reg(0XC7,0X40); //AWB OFF
SCCB_WR_Reg(0XCC,regccval);
SCCB_WR_Reg(0XCD,regcdval);
SCCB_WR_Reg(0XCE,regceval);
}
/*********************************************
*函數(shù)功能:色度設(shè)置
*函數(shù)形參:None
*函數(shù)返回值:None
*備注://0:-2
//1:-1
//2,0
//3,+1
//4,+2
*********************************************/
void OV2640_Color_Saturation(u8 sat)
{
u8 reg7dval=((sat+2)<<4)|0X08;
SCCB_WR_Reg(0XFF,0X00);
SCCB_WR_Reg(0X7C,0X00);
SCCB_WR_Reg(0X7D,0X02);
SCCB_WR_Reg(0X7C,0X03);
SCCB_WR_Reg(0X7D,reg7dval);
SCCB_WR_Reg(0X7D,reg7dval);
}
/*********************************************
*函數(shù)功能:亮度設(shè)置
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: //0:(0X00)-2
//1:(0X10)-1
//2,(0X20) 0
//3,(0X30)+1
//4,(0X40)+2
*********************************************/
void OV2640_Brightness(u8 bright)
{
SCCB_WR_Reg(0xff, 0x00);
SCCB_WR_Reg(0x7c, 0x00);
SCCB_WR_Reg(0x7d, 0x04);
SCCB_WR_Reg(0x7c, 0x09);
SCCB_WR_Reg(0x7d, bright<<4);
SCCB_WR_Reg(0x7d, 0x00);
}
/*********************************************
*函數(shù)功能:對比度設(shè)置
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: //0:-2
//1:-1
//2,0
//3,+1
//4,+2
*********************************************/
void OV2640_Contrast(u8 contrast)
{
u8 reg7d0val=0X20;//默認(rèn)為普通模式
u8 reg7d1val=0X20;
switch(contrast)
{
case 0://-2
reg7d0val=0X18;
reg7d1val=0X34;
break;
case 1://-1
reg7d0val=0X1C;
reg7d1val=0X2A;
break;
case 3://1
reg7d0val=0X24;
reg7d1val=0X16;
break;
case 4://2
reg7d0val=0X28;
reg7d1val=0X0C;
break;
}
SCCB_WR_Reg(0xff,0x00);
SCCB_WR_Reg(0x7c,0x00);
SCCB_WR_Reg(0x7d,0x04);
SCCB_WR_Reg(0x7c,0x07);
SCCB_WR_Reg(0x7d,0x20);
SCCB_WR_Reg(0x7d,reg7d0val);
SCCB_WR_Reg(0x7d,reg7d1val);
SCCB_WR_Reg(0x7d,0x06);
}
/*********************************************
*函數(shù)功能:特效設(shè)置
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: //0:普通模式
//1,負(fù)片
//2,黑白
//3,偏紅色
//4,偏綠色
//5,偏藍(lán)色
//6,復(fù)古
*********************************************/
void OV2640_Special_Effects(u8 eft)
{
u8 reg7d0val=0X00;//默認(rèn)為普通模式
u8 reg7d1val=0X80;
u8 reg7d2val=0X80;
switch(eft)
{
case 1://負(fù)片
reg7d0val=0X40;
break;
case 2://黑白
reg7d0val=0X18;
break;
case 3://偏紅色
reg7d0val=0X18;
reg7d1val=0X40;
reg7d2val=0XC0;
break;
case 4://偏綠色
reg7d0val=0X18;
reg7d1val=0X40;
reg7d2val=0X40;
break;
case 5://偏藍(lán)色
reg7d0val=0X18;
reg7d1val=0XA0;
reg7d2val=0X40;
break;
case 6://復(fù)古
reg7d0val=0X18;
reg7d1val=0X40;
reg7d2val=0XA6;
break;
}
SCCB_WR_Reg(0xff,0x00);
SCCB_WR_Reg(0x7c,0x00);
SCCB_WR_Reg(0x7d,reg7d0val);
SCCB_WR_Reg(0x7c,0x05);
SCCB_WR_Reg(0x7d,reg7d1val);
SCCB_WR_Reg(0x7d,reg7d2val);
}
/*********************************************
*函數(shù)功能:彩條測試
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: //sw:0,關(guān)閉彩條
// 1,開啟彩條(注意OV2640的彩條是疊加在圖像上面的)
*********************************************/
void OV2640_Color_Bar(u8 sw)
{
u8 reg;
SCCB_WR_Reg(0XFF,0X01);
reg=SCCB_RD_Reg(0X12);
reg&=~(1<<1);
if(sw)reg|=1<<1;
SCCB_WR_Reg(0X12,reg);
}
/*********************************************
*函數(shù)功能:設(shè)置圖像輸出窗口
*函數(shù)形參:u16 sx,u16 sy,u16 width,u16 height
*函數(shù)返回值:None
*備注: //sx,sy,起始地址
//width,height:寬度(對應(yīng):horizontal)和高度(對應(yīng):vertical)
*********************************************/
void OV2640_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;
SCCB_WR_Reg(0XFF,0X01);
temp=SCCB_RD_Reg(0X03); //讀取Vref之前的值
temp&=0XF0;
temp|=((endy&0X03)<<2)|(sy&0X03);
SCCB_WR_Reg(0X03,temp); //設(shè)置Vref的start和end的最低2位
SCCB_WR_Reg(0X19,sy>>2); //設(shè)置Vref的start高8位
SCCB_WR_Reg(0X1A,endy>>2); //設(shè)置Vref的end的高8位
temp=SCCB_RD_Reg(0X32); //讀取Href之前的值
temp&=0XC0;
temp|=((endx&0X07)<<3)|(sx&0X07);
SCCB_WR_Reg(0X32,temp); //設(shè)置Href的start和end的最低3位
SCCB_WR_Reg(0X17,sx>>3); //設(shè)置Href的start高8位
SCCB_WR_Reg(0X18,endx>>3); //設(shè)置Href的end的高8位
}
/*********************************************
*函數(shù)功能:設(shè)置圖像輸出大小
*函數(shù)形參:u16 width,u16 height
*函數(shù)返回值:None
*備注: /OV2640輸出圖像的大小(分辨率),完全由改函數(shù)確定
//width,height:寬度(對應(yīng):horizontal)和高度(對應(yīng):vertical),width和height必須是4的倍數(shù)
//返回值:0,設(shè)置成功
// 其他,設(shè)置失敗
*********************************************/
u8 OV2640_OutSize_Set(u16 width,u16 height)
{
u16 outh;
u16 outw;
u8 temp;
if(width%4)return 1;
if(height%4)return 2;
outw=width/4;
outh=height/4;
SCCB_WR_Reg(0XFF,0X00);
SCCB_WR_Reg(0XE0,0X04);
SCCB_WR_Reg(0X5A,outw&0XFF); //設(shè)置OUTW的低八位
SCCB_WR_Reg(0X5B,outh&0XFF); //設(shè)置OUTH的低八位
temp=(outw>>8)&0X03;
temp|=(outh>>6)&0X04;
SCCB_WR_Reg(0X5C,temp); //設(shè)置OUTH/OUTW的高位
SCCB_WR_Reg(0XE0,0X00);
return 0;
}
/*********************************************
*函數(shù)功能:設(shè)置圖像開窗大小
*函數(shù)形參:uu16 offx,u16 offy,u16 width,u16 height
*函數(shù)返回值:None
*備注: //由:OV2640_ImageSize_Set確定傳感器輸出分辨率從大小.
//該函數(shù)則在這個范圍上面進(jìn)行開窗,用于OV2640_OutSize_Set的輸出
//注意:本函數(shù)的寬度和高度,必須大于等于OV2640_OutSize_Set函數(shù)的寬度和高度
// OV2640_OutSize_Set設(shè)置的寬度和高度,根據(jù)本函數(shù)設(shè)置的寬度和高度,由DSP
// 自動計算縮放比例,輸出給外部設(shè)備.
//width,height:寬度(對應(yīng):horizontal)和高度(對應(yīng):vertical),width和height必須是4的倍數(shù)
//返回值:0,設(shè)置成功
// 其他,設(shè)置失敗
*********************************************/
u8 OV2640_ImageWin_Set(u16 offx,u16 offy,u16 width,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); //設(shè)置H_SIZE的低八位
SCCB_WR_Reg(0X52,vsize&0XFF); //設(shè)置V_SIZE的低八位
SCCB_WR_Reg(0X53,offx&0XFF); //設(shè)置offx的低八位
SCCB_WR_Reg(0X54,offy&0XFF); //設(shè)置offy的低八位
temp=(vsize>>1)&0X80;
temp|=(offy>>4)&0X70;
temp|=(hsize>>5)&0X08;
temp|=(offx>>8)&0X07;
SCCB_WR_Reg(0X55,temp); //設(shè)置H_SIZE/V_SIZE/OFFX,OFFY的高位
SCCB_WR_Reg(0X57,(hsize>>2)&0X80); //設(shè)置H_SIZE/V_SIZE/OFFX,OFFY的高位
SCCB_WR_Reg(0XE0,0X00);
return 0;
}
/*********************************************
*函數(shù)功能:該函數(shù)設(shè)置圖像尺寸大小,也就是所選格式的輸出分辨率
*函數(shù)形參:u16 width,u16 height
*函數(shù)返回值:None
*備注: //該函數(shù)設(shè)置圖像尺寸大小,也就是所選格式的輸出分辨率
//UXGA:1600*1200,SVGA:800*600,CIF:352*288
//width,height:圖像寬度和圖像高度
//返回值:0,設(shè)置成功
// 其他,設(shè)置失敗
*********************************************/
u8 OV2640_ImageSize_Set(u16 width,u16 height)
{
u8 temp;
SCCB_WR_Reg(0XFF,0X00);
SCCB_WR_Reg(0XE0,0X04);
SCCB_WR_Reg(0XC0,(width)>>3&0XFF); //設(shè)置HSIZE的10:3位
SCCB_WR_Reg(0XC1,(height)>>3&0XFF); //設(shè)置VSIZE的10:3位
temp=(width&0X07)<<3;
temp|=height&0X07;
temp|=(width>>4)&0X80;
SCCB_WR_Reg(0X8C,temp);
SCCB_WR_Reg(0XE0,0X00);
return 0;
}
ov2640.h文件
#ifndef __OV2640_H_
#define __OV2640_H_
/********************頭文件************************/
#include "ov2640.h"
#include "sys.h"
#include "time.h"
#include "systick.h"
#include "uart.h"
#include "sccb.h"
#include "ov2640cfg.h"
/********************宏定義************************/
#define OV2640_PWDN PGout(9) //POWER DOWN控制信號
#define OV2640_RST PGout(15) //復(fù)位控制信號
//
#define OV2640_MID 0X7FA2
#define OV2640_PID 0X2642
//當(dāng)選擇DSP地址(0XFF=0X00)時,OV2640的DSP寄存器地址映射表
#define OV2640_DSP_R_BYPASS 0x05
#define OV2640_DSP_Qs 0x44
#define OV2640_DSP_CTRL 0x50
#define OV2640_DSP_HSIZE1 0x51
#define OV2640_DSP_VSIZE1 0x52
#define OV2640_DSP_XOFFL 0x53
#define OV2640_DSP_YOFFL 0x54
#define OV2640_DSP_VHYX 0x55
#define OV2640_DSP_DPRP 0x56
#define OV2640_DSP_TEST 0x57
#define OV2640_DSP_ZMOW 0x5A
#define OV2640_DSP_ZMOH 0x5B
#define OV2640_DSP_ZMHH 0x5C
#define OV2640_DSP_BPADDR 0x7C
#define OV2640_DSP_BPDATA 0x7D
#define OV2640_DSP_CTRL2 0x86
#define OV2640_DSP_CTRL3 0x87
#define OV2640_DSP_SIZEL 0x8C
#define OV2640_DSP_HSIZE2 0xC0
#define OV2640_DSP_VSIZE2 0xC1
#define OV2640_DSP_CTRL0 0xC2
#define OV2640_DSP_CTRL1 0xC3
#define OV2640_DSP_R_DVP_SP 0xD3
#define OV2640_DSP_IMAGE_MODE 0xDA
#define OV2640_DSP_RESET 0xE0
#define OV2640_DSP_MS_SP 0xF0
#define OV2640_DSP_SS_ID 0x7F
#define OV2640_DSP_SS_CTRL 0xF8
#define OV2640_DSP_MC_BIST 0xF9
#define OV2640_DSP_MC_AL 0xFA
#define OV2640_DSP_MC_AH 0xFB
#define OV2640_DSP_MC_D 0xFC
#define OV2640_DSP_P_STATUS 0xFE
#define OV2640_DSP_RA_DLMT 0xFF
//當(dāng)選擇傳感器地址(0XFF=0X01)時,OV2640的DSP寄存器地址映射表
#define OV2640_SENSOR_GAIN 0x00
#define OV2640_SENSOR_COM1 0x03
#define OV2640_SENSOR_REG04 0x04
#define OV2640_SENSOR_REG08 0x08
#define OV2640_SENSOR_COM2 0x09
#define OV2640_SENSOR_PIDH 0x0A
#define OV2640_SENSOR_PIDL 0x0B
#define OV2640_SENSOR_COM3 0x0C
#define OV2640_SENSOR_COM4 0x0D
#define OV2640_SENSOR_AEC 0x10
#define OV2640_SENSOR_CLKRC 0x11
#define OV2640_SENSOR_COM7 0x12
#define OV2640_SENSOR_COM8 0x13
#define OV2640_SENSOR_COM9 0x14
#define OV2640_SENSOR_COM10 0x15
#define OV2640_SENSOR_HREFST 0x17
#define OV2640_SENSOR_HREFEND 0x18
#define OV2640_SENSOR_VSTART 0x19
#define OV2640_SENSOR_VEND 0x1A
#define OV2640_SENSOR_MIDH 0x1C
#define OV2640_SENSOR_MIDL 0x1D
#define OV2640_SENSOR_AEW 0x24
#define OV2640_SENSOR_AEB 0x25
#define OV2640_SENSOR_W 0x26
#define OV2640_SENSOR_REG2A 0x2A
#define OV2640_SENSOR_FRARL 0x2B
#define OV2640_SENSOR_ADDVSL 0x2D
#define OV2640_SENSOR_ADDVHS 0x2E
#define OV2640_SENSOR_YAVG 0x2F
#define OV2640_SENSOR_REG32 0x32
#define OV2640_SENSOR_ARCOM2 0x34
#define OV2640_SENSOR_REG45 0x45
#define OV2640_SENSOR_FLL 0x46
#define OV2640_SENSOR_FLH 0x47
#define OV2640_SENSOR_COM19 0x48
#define OV2640_SENSOR_ZOOMS 0x49
#define OV2640_SENSOR_COM22 0x4B
#define OV2640_SENSOR_COM25 0x4E
#define OV2640_SENSOR_BD50 0x4F
#define OV2640_SENSOR_BD60 0x50
#define OV2640_SENSOR_REG5D 0x5D
#define OV2640_SENSOR_REG5E 0x5E
#define OV2640_SENSOR_REG5F 0x5F
#define OV2640_SENSOR_REG60 0x60
#define OV2640_SENSOR_HISTO_LOW 0x61
#define OV2640_SENSOR_HISTO_HIGH 0x62
/*****************聲明外部變量*********************/
//自動曝光設(shè)置參數(shù)表,支持5個等級
const static u8 OV2640_AUTOEXPOSURE_LEVEL[5][8]=
{
{
0xFF,0x01,
0x24,0x20,
0x25,0x18,
0x26,0x60,
},
{
0xFF,0x01,
0x24,0x34,
0x25,0x1c,
0x26,0x00,
},
{
0xFF,0x01,
0x24,0x3e,
0x25,0x38,
0x26,0x81,
},
{
0xFF,0x01,
0x24,0x48,
0x25,0x40,
0x26,0x81,
},
{
0xFF,0x01,
0x24,0x58,
0x25,0x50,
0x26,0x92,
},
};
/*******************函數(shù)聲明***********************/
u8 OV2640_Init(void);
void OV2640_JPEG_Mode(void);
void OV2640_RGB565_Mode(void);
void OV2640_Auto_Exposure(u8 level);
void OV2640_Light_Mode(u8 mode);
void OV2640_Color_Saturation(u8 sat);
void OV2640_Brightness(u8 bright);
void OV2640_Contrast(u8 contrast);
void OV2640_Special_Effects(u8 eft);
void OV2640_Color_Bar(u8 sw);
void OV2640_Window_Set(u16 sx,u16 sy,u16 width,u16 height);
u8 OV2640_OutSize_Set(u16 width,u16 height);
u8 OV2640_ImageWin_Set(u16 offx,u16 offy,u16 width,u16 height);
u8 OV2640_ImageSize_Set(u16 width,u16 height);
/
#endif
sccb.c文件
#include "sccb.h"
/*********************************************
*函數(shù)功能:初始化SCCB接口
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: None
*********************************************/
void SCCB_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//使能GPIOD時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
//GPIOF9,F10初始化設(shè)置
//PD6,7 推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
//PD6,7 推挽輸出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
//推挽輸出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//100MHz
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//上拉
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
//初始化
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_SetBits(GPIOD,GPIO_Pin_6|GPIO_Pin_7);
SCCB_SDA_OUT();
}
/*********************************************
*函數(shù)功能:SCCB起始信號
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: //當(dāng)時鐘為高的時候,數(shù)據(jù)線的高到低,為SCCB起始信號
//在激活狀態(tài)下,SDA和SCL均為低電平
*********************************************/
void SCCB_Start(void)
{
SCCB_SDA=1; //數(shù)據(jù)線高電平
SCCB_SCL=1; //在時鐘線高的時候數(shù)據(jù)線由高至低
Delay_us(50);
SCCB_SDA=0;
Delay_us(50);
SCCB_SCL=0; //數(shù)據(jù)線恢復(fù)低電平,單操作函數(shù)必要
}
/*********************************************
*函數(shù)功能:SCCB停止信號
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: //當(dāng)時鐘為高的時候,數(shù)據(jù)線的低到高,為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);
}
/*********************************************
*函數(shù)功能:產(chǎn)生NA信號
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: //當(dāng)時鐘為高的時候,數(shù)據(jù)線的低到高,為SCCB停止信號
//空閑狀況下,SDA,SCL均為高電平
*********************************************/
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);
}
/*********************************************
*函數(shù)功能:SCCB,寫入一個字節(jié)
*函數(shù)形參:u8 dat
*函數(shù)返回值:返回值:0,成功;1,失敗
*備注: None
*********************************************/
u8 SCCB_WR_Byte(u8 dat)
{
u8 j,res;
for(j=0;j<8;j++) //循環(huán)8次發(fā)送數(shù)據(jù)
{
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(); //設(shè)置SDA為輸入
Delay_us(50);
SCCB_SCL=1; //接收第九位,以判斷是否發(fā)送成功
Delay_us(50);
if(SCCB_READ_SDA)res=1; //SDA=1發(fā)送失敗,返回1
else res=0; //SDA=0發(fā)送成功,返回0
SCCB_SCL=0;
SCCB_SDA_OUT(); //設(shè)置SDA為輸出
return res;
}
/*********************************************
*函數(shù)功能:SCCB 讀取一個字節(jié)
*函數(shù)形參:NONE
*函數(shù)返回值://返回值:讀到的數(shù)據(jù)
*備注: //在SCL的上升沿,數(shù)據(jù)鎖存
*********************************************/
u8 SCCB_RD_Byte(void)
{
u8 temp=0,j;
//設(shè)置SDA為輸入
SCCB_SDA_IN();
//循環(huán)8次接收數(shù)據(jù)
for(j=8;j>0;j--)
{
Delay_us(50);
SCCB_SCL=1;
temp=temp<<1;
if(SCCB_READ_SDA)temp++;
Delay_us(50);
SCCB_SCL=0;
}
//設(shè)置SDA為輸出
SCCB_SDA_OUT();
return temp;
}
/*********************************************
*函數(shù)功能:寫寄存器
*函數(shù)形參:u8 reg,u8 data
*函數(shù)返回值:
*備注: //返回值: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; //寫數(shù)據(jù)
SCCB_Stop();
return res;
}
/*********************************************
*函數(shù)功能:讀寄存器
*函數(shù)形參:u8 reg
*函數(shù)返回值:
*備注: 返回值:讀到的寄存器值
*********************************************/
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);
//設(shè)置寄存器地址后,才是讀
SCCB_Start();
SCCB_WR_Byte(SCCB_ID|0X01); //發(fā)送讀命令
Delay_us(100);
val=SCCB_RD_Byte(); //讀取數(shù)據(jù)
SCCB_No_Ack();
SCCB_Stop();
return val;
}
sccb.h文件
#ifndef __SCCB_H_
#define __SCCB_H_
/********************頭文件************************/
#include "sccb.h"
#include "sys.h"
#include "systick.h"
/********************宏定義************************/
//IO方向設(shè)置
#define SCCB_SDA_IN() {GPIOD->MODER&=~(3<<(7*2));GPIOD->MODER|=0<<7*2;} //PD7 輸入
#define SCCB_SDA_OUT() {GPIOD->MODER&=~(3<<(7*2));GPIOD->MODER|=1<<7*2;} //PD7 輸出
//IO操作函數(shù)
#define SCCB_SCL PDout(6) //SCL
#define SCCB_SDA PDout(7) //SDA
#define SCCB_READ_SDA PDin(7) //輸入SDA
#define SCCB_ID 0X60 //OV2640的ID
/*****************聲明外部變量*********************/
/*******************函數(shù)聲明***********************/
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
time.c文件
#include "time.h"
/*********************************************
*函數(shù)功能:通用定時器3中斷初始化
*函數(shù)形參:None
*函數(shù)返回值:None
*備注: //arr:自動重裝值。
//psc:時鐘預(yù)分頻數(shù)
//定時器溢出時間計算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定時器工作頻率,單位:Mhz
//這里使用的是定時器3!
*********************************************/
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); ///使能TIM3時鐘
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //定時器分頻
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計數(shù)模式
TIM_TimeBaseInitStructure.TIM_Period=arr; //自動重裝載值
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允許定時器3更新中斷
TIM_Cmd(TIM3,ENABLE); //使能定時器3
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定時器3中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //搶占優(yōu)先級1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//定時器3中斷服務(wù)函數(shù)
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中斷
{
// printf("frame:%d\r\n",ov_frame);//打印幀率
// printf("jpeg_data_len:%d\r\n",jpeg_data_len);//打印幀率
ov_frame=0;
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中斷標(biāo)志位
}
time.h文件
#ifndef __TIME_H_
#define __TIME_H_
/********************頭文件************************/
#include "stm32f4xx.h"
#include "led.h"
#include "uart.h"
/********************宏定義************************/
/*****************聲明外部變量*********************/
extern u8 ov_frame;
extern volatile u32 jpeg_data_len;
/*******************函數(shù)聲明***********************/
void TIM3_Int_Init(u16 arr,u16 psc);
#endif
sys.c文件
#include "sys.h"
//
//本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途
//ALIENTEK STM32F407開發(fā)板
//系統(tǒng)時鐘初始化
//包括時鐘設(shè)置/中斷管理/GPIO設(shè)置等
//正點原子@ALIENTEK
//技術(shù)論壇:www.openedv.com
//創(chuàng)建日期:2014/5/2
//版本:V1.0
//版權(quán)所有,盜版必究。
//Copyright(C) 廣州市星翼電子科技有限公司 2014-2024
//All rights reserved
//********************************************************************************
//修改說明
//無
//
//THUMB指令不支持匯編內(nèi)聯(lián)
//采用如下方法實現(xiàn)執(zhí)行匯編指令WFI
__asm void WFI_SET(void)
{
WFI;
}
//關(guān)閉所有中斷(但是不包括fault和NMI中斷)
__asm void INTX_DISABLE(void)
{
CPSID I
BX LR
}
//開啟所有中斷
__asm void INTX_ENABLE(void)
{
CPSIE I
BX LR
}
//設(shè)置棧頂?shù)刂?//addr:棧頂?shù)刂?__asm void MSR_MSP(u32 addr)
{
MSR MSP, r0 //set Main Stack value
BX r14
}
sys.h文件
#ifndef __SYS_H
#define __SYS_H
#include "stm32f4xx.h"
//
//本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途
//ALIENTEK STM32F407開發(fā)板
//系統(tǒng)時鐘初始化
//正點原子@ALIENTEK
//技術(shù)論壇:www.openedv.com
//創(chuàng)建日期:2014/5/2
//版本:V1.0
//版權(quán)所有,盜版必究。
//Copyright(C) 廣州市星翼電子科技有限公司 2014-2024
//All rights reserved
//********************************************************************************
//修改說明
//無
//
//0,不支持ucos
//1,支持ucos
#define SYSTEM_SUPPORT_OS 0 //定義系統(tǒng)文件夾是否支持UCOS
//位帶操作,實現(xiàn)51類似的GPIO控制功能
//具體實現(xiàn)思想,參考<<CM3權(quán)威指南>>第五章(87頁~92頁).M4同M3類似,只是寄存器地址變了.
//IO口操作宏定義
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr (GPIOB_BASE+20) //0x40020414
#define GPIOC_ODR_Addr (GPIOC_BASE+20) //0x40020814
#define GPIOD_ODR_Addr (GPIOD_BASE+20) //0x40020C14
#define GPIOE_ODR_Addr (GPIOE_BASE+20) //0x40021014
#define GPIOF_ODR_Addr (GPIOF_BASE+20) //0x40021414
#define GPIOG_ODR_Addr (GPIOG_BASE+20) //0x40021814
#define GPIOH_ODR_Addr (GPIOH_BASE+20) //0x40021C14
#define GPIOI_ODR_Addr (GPIOI_BASE+20) //0x40022014
#define GPIOA_IDR_Addr (GPIOA_BASE+16) //0x40020010
#define GPIOB_IDR_Addr (GPIOB_BASE+16) //0x40020410
#define GPIOC_IDR_Addr (GPIOC_BASE+16) //0x40020810
#define GPIOD_IDR_Addr (GPIOD_BASE+16) //0x40020C10
#define GPIOE_IDR_Addr (GPIOE_BASE+16) //0x40021010
#define GPIOF_IDR_Addr (GPIOF_BASE+16) //0x40021410
#define GPIOG_IDR_Addr (GPIOG_BASE+16) //0x40021810
#define GPIOH_IDR_Addr (GPIOH_BASE+16) //0x40021C10
#define GPIOI_IDR_Addr (GPIOI_BASE+16) //0x40022010
//IO口操作,只對單一的IO口!
//確保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //輸出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //輸入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //輸出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //輸入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //輸出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //輸入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //輸出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //輸入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //輸出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //輸入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //輸出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //輸入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //輸出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //輸入
#define PHout(n) BIT_ADDR(GPIOH_ODR_Addr,n) //輸出
#define PHin(n) BIT_ADDR(GPIOH_IDR_Addr,n) //輸入
#define PIout(n) BIT_ADDR(GPIOI_ODR_Addr,n) //輸出
#define PIin(n) BIT_ADDR(GPIOI_IDR_Addr,n) //輸入
//以下為匯編函數(shù)
void WFI_SET(void); //執(zhí)行WFI指令
void INTX_DISABLE(void);//關(guān)閉所有中斷
void INTX_ENABLE(void); //開啟所有中斷
void MSR_MSP(u32 addr); //設(shè)置堆棧地址
#endif
ov2640cfg.c文件
#include "ov2640cfg.h"
//
OV2640 SXGA初始化寄存器序列表
此模式下幀率為15幀
SXGA(1600*1200)
// const u8 ov2640_sxga_init_reg_tbl[][2]=
//{
// 0xff, 0x00,
// 0x2c, 0xff,
// 0x2e, 0xdf,
// 0xff, 0x01,
// 0x3c, 0x32,
// //
// 0x11, 0x00,
// 0x09, 0x02,
// 0x04, 0xD8,//水平鏡像,垂直翻轉(zhuǎn)
// 0x13, 0xe5,
// 0x14, 0x48,
// 0x2c, 0x0c,
// 0x33, 0x78,
// 0x3a, 0x33,
// 0x3b, 0xfB,
// //
// 0x3e, 0x00,
// 0x43, 0x11,
// 0x16, 0x10,
// //
// 0x39, 0x92,
// //
// 0x35, 0xda,
// 0x22, 0x1a,
// 0x37, 0xc3,
// 0x23, 0x00,
// 0x34, 0xc0,
// 0x36, 0x1a,
// 0x06, 0x88,
// 0x07, 0xc0,
// 0x0d, 0x87,
// 0x0e, 0x41,
// 0x4c, 0x00,
//
// 0x48, 0x00,
// 0x5B, 0x00,
// 0x42, 0x03,
// //
// 0x4a, 0x81,
// 0x21, 0x99,
// //
// 0x24, 0x40,
// 0x25, 0x38,
// 0x26, 0x82,
// 0x5c, 0x00,
// 0x63, 0x00,
// 0x46, 0x00,
// 0x0c, 0x3c,
// //
// 0x61, 0x70,
// 0x62, 0x80,
// 0x7c, 0x05,
// //
// 0x20, 0x80,
// 0x28, 0x30,
// 0x6c, 0x00,
// 0x6d, 0x80,
// 0x6e, 0x00,
// 0x70, 0x02,
// 0x71, 0x94,
// 0x73, 0xc1,
// 0x3d, 0x34,
// 0x5a, 0x57,
// //
// 0x12, 0x00,//UXGA 1600*1200
//
// 0x17, 0x11,
// 0x18, 0x75,
// 0x19, 0x01,
// 0x1a, 0x97,
// 0x32, 0x36,
// 0x03, 0x0f,
// 0x37, 0x40,
// //
// 0x4f, 0xca,
// 0x50, 0xa8,
// 0x5a, 0x23,
// 0x6d, 0x00,
// 0x6d, 0x38,
// //
// 0xff, 0x00,
// 0xe5, 0x7f,
// 0xf9, 0xc0,
// 0x41, 0x24,
// 0xe0, 0x14,
// 0x76, 0xff,
// 0x33, 0xa0,
// 0x42, 0x20,
// 0x43, 0x18,
// 0x4c, 0x00,
// 0x87, 0xd5,
// 0x88, 0x3f,
// 0xd7, 0x03,
// 0xd9, 0x10,
// 0xd3, 0x82,
// //
// 0xc8, 0x08,
// 0xc9, 0x80,
// //
// 0x7c, 0x00,
// 0x7d, 0x00,
// 0x7c, 0x03,
// 0x7d, 0x48,
// 0x7d, 0x48,
// 0x7c, 0x08,
// 0x7d, 0x20,
// 0x7d, 0x10,
// 0x7d, 0x0e,
// //
// 0x90, 0x00,
// 0x91, 0x0e,
// 0x91, 0x1a,
// 0x91, 0x31,
// 0x91, 0x5a,
// 0x91, 0x69,
// 0x91, 0x75,
// 0x91, 0x7e,
// 0x91, 0x88,
// 0x91, 0x8f,
// 0x91, 0x96,
// 0x91, 0xa3,
// 0x91, 0xaf,
// 0x91, 0xc4,
// 0x91, 0xd7,
// 0x91, 0xe8,
// 0x91, 0x20,
// //
// 0x92, 0x00,
// 0x93, 0x06,
// 0x93, 0xe3,
// 0x93, 0x05,
// 0x93, 0x05,
// 0x93, 0x00,
// 0x93, 0x04,
// 0x93, 0x00,
// 0x93, 0x00,
// 0x93, 0x00,
// 0x93, 0x00,
// 0x93, 0x00,
// 0x93, 0x00,
// 0x93, 0x00,
// //
// 0x96, 0x00,
// 0x97, 0x08,
// 0x97, 0x19,
// 0x97, 0x02,
// 0x97, 0x0c,
// 0x97, 0x24,
// 0x97, 0x30,
// 0x97, 0x28,
// 0x97, 0x26,
// 0x97, 0x02,
// 0x97, 0x98,
// 0x97, 0x80,
// 0x97, 0x00,
// 0x97, 0x00,
// //
// 0xc3, 0xef,
//
// 0xa4, 0x00,
// 0xa8, 0x00,
// 0xc5, 0x11,
// 0xc6, 0x51,
// 0xbf, 0x80,
// 0xc7, 0x10,
// 0xb6, 0x66,
// 0xb8, 0xA5,
// 0xb7, 0x64,
// 0xb9, 0x7C,
// 0xb3, 0xaf,
// 0xb4, 0x97,
// 0xb5, 0xFF,
// 0xb0, 0xC5,
// 0xb1, 0x94,
// 0xb2, 0x0f,
// 0xc4, 0x5c,
// //
// 0xc0, 0xc8,
// 0xc1, 0x96,
// 0x8c, 0x00,
// 0x86, 0x3d,
// 0x50, 0x00,
// 0x51, 0x90,
// 0x52, 0x2c,
// 0x53, 0x00,
// 0x54, 0x00,
// 0x55, 0x88,
//
// 0x5a, 0x90,
// 0x5b, 0x2C,
// 0x5c, 0x05,
//
// 0xd3, 0x05,//auto設(shè)置要小心
// //
// 0xc3, 0xed,
// 0x7f, 0x00,
//
// 0xda, 0x09,
//
// 0xe5, 0x1f,
// 0xe1, 0x67,
// 0xe0, 0x00,
// 0xdd, 0x7f,
// 0x05, 0x00,
//};
OV2640 SVGA初始化寄存器序列表
此模式下,幀率可以達(dá)到30幀
SVGA 800*600
//const u8 ov2640_svga_init_reg_tbl[][2]=
//{
// 0xff, 0x00,
// 0x2c, 0xff,
// 0x2e, 0xdf,
// 0xff, 0x01,
// 0x3c, 0x32,
// //
// 0x11, 0x00,
// 0x09, 0x02,
// 0x04, 0xD8,//水平鏡像,垂直翻轉(zhuǎn)
// 0x13, 0xe5,
// 0x14, 0x48,
// 0x2c, 0x0c,
// 0x33, 0x78,
// 0x3a, 0x33,
// 0x3b, 0xfB,
// //
// 0x3e, 0x00,
// 0x43, 0x11,
// 0x16, 0x10,
// //
// 0x39, 0x92,
// //
// 0x35, 0xda,
// 0x22, 0x1a,
// 0x37, 0xc3,
// 0x23, 0x00,
// 0x34, 0xc0,
// 0x36, 0x1a,
// 0x06, 0x88,
// 0x07, 0xc0,
// 0x0d, 0x87,
// 0x0e, 0x41,
// 0x4c, 0x00,
// 0x48, 0x00,
// 0x5B, 0x00,
// 0x42, 0x03,
// //
// 0x4a, 0x81,
// 0x21, 0x99,
// //
// 0x24, 0x40,
// 0x25, 0x38,
// 0x26, 0x82,
// 0x5c, 0x00,
// 0x63, 0x00,
// 0x46, 0x22,
// 0x0c, 0x3c,
// //
// 0x61, 0x70,
// 0x62, 0x80,
// 0x7c, 0x05,
// //
// 0x20, 0x80,
// 0x28, 0x30,
// 0x6c, 0x00,
// 0x6d, 0x80,
// 0x6e, 0x00,
// 0x70, 0x02,
// 0x71, 0x94,
// 0x73, 0xc1,
//
// 0x3d, 0x34,
// 0x5a, 0x57,
// //根據(jù)分辨率不同而設(shè)置
// 0x12, 0x40,//SVGA 800*600
// 0x17, 0x11,
// 0x18, 0x43,
// 0x19, 0x00,
// 0x1a, 0x4b,
// 0x32, 0x09,
// 0x37, 0xc0,
// //
// 0x4f, 0xca,
// 0x50, 0xa8,
// 0x5a, 0x23,
// 0x6d, 0x00,
// 0x3d, 0x38,
// //
// 0xff, 0x00,
// 0xe5, 0x7f,
// 0xf9, 0xc0,
// 0x41, 0x24,
// 0xe0, 0x14,
// 0x76, 0xff,
// 0x33, 0xa0,
// 0x42, 0x20,
// 0x43, 0x18,
// 0x4c, 0x00,
// 0x87, 0xd5,
// 0x88, 0x3f,
// 0xd7, 0x03,
// 0xd9, 0x10,
// 0xd3, 0x82,
// //
// 0xc8, 0x08,
// 0xc9, 0x80,
// //
// 0x7c, 0x00,
// 0x7d, 0x00,
// 0x7c, 0x03,
// 0x7d, 0x48,
// 0x7d, 0x48,
// 0x7c, 0x08,
// 0x7d, 0x20,
// 0x7d, 0x10,
// 0x7d, 0x0e,
// //
// 0x90, 0x00,
// 0x91, 0x0e,
// 0x91, 0x1a,
// 0x91, 0x31,
// 0x91, 0x5a,
// 0x91, 0x69,
// 0x91, 0x75,
// 0x91, 0x7e,
// 0x91, 0x88,
// 0x91, 0x8f,
// 0x91, 0x96,
// 0x91, 0xa3,
// 0x91, 0xaf,
// 0x91, 0xc4,
// 0x91, 0xd7,
// 0x91, 0xe8,
// 0x91, 0x20,
// //
// 0x92, 0x00,
// 0x93, 0x06,
// 0x93, 0xe3,
// 0x93, 0x05,
// 0x93, 0x05,
// 0x93, 0x00,
// 0x93, 0x04,
// 0x93, 0x00,
// 0x93, 0x00,
// 0x93, 0x00,
// 0x93, 0x00,
// 0x93, 0x00,
// 0x93, 0x00,
// 0x93, 0x00,
// //
// 0x96, 0x00,
// 0x97, 0x08,
// 0x97, 0x19,
// 0x97, 0x02,
// 0x97, 0x0c,
// 0x97, 0x24,
// 0x97, 0x30,
// 0x97, 0x28,
// 0x97, 0x26,
// 0x97, 0x02,
// 0x97, 0x98,
// 0x97, 0x80,
// 0x97, 0x00,
// 0x97, 0x00,
// //
// 0xc3, 0xed,
// 0xa4, 0x00,
// 0xa8, 0x00,
// 0xc5, 0x11,
// 0xc6, 0x51,
// 0xbf, 0x80,
// 0xc7, 0x10,
// 0xb6, 0x66,
// 0xb8, 0xA5,
// 0xb7, 0x64,
// 0xb9, 0x7C,
// 0xb3, 0xaf,
// 0xb4, 0x97,
// 0xb5, 0xFF,
// 0xb0, 0xC5,
// 0xb1, 0x94,
// 0xb2, 0x0f,
// 0xc4, 0x5c,
// //根據(jù)分辨率不同而設(shè)置
// 0xc0, 0x64,
// 0xc1, 0x4B,
// 0x8c, 0x00,
// 0x86, 0x3D,
// 0x50, 0x00,
// 0x51, 0xC8,
// 0x52, 0x96,
// 0x53, 0x00,
// 0x54, 0x00,
// 0x55, 0x00,
// 0x5a, 0xC8,
// 0x5b, 0x96,
// 0x5c, 0x00,
//
// 0xd3, 0x02,//auto設(shè)置要小心
// //
// 0xc3, 0xed,
// 0x7f, 0x00,
//
// 0xda, 0x09,
//
// 0xe5, 0x1f,
// 0xe1, 0x67,
// 0xe0, 0x00,
// 0xdd, 0x7f,
// 0x05, 0x00,
//};
//const u8 ov2640_jpeg_reg_tbl[][2]=
//{
// 0xff, 0x01,
// 0xe0, 0x14,
// 0xe1, 0x77,
// 0xe5, 0x1f,
// 0xd7, 0x03,
// 0xda, 0x10,
// 0xe0, 0x00,
//};
//const u8 ov2640_yuv422_reg_tbl[][2]=
//{
// 0xFF, 0x00,
// 0xDA, 0x10,
// 0xD7, 0x03,
// 0xDF, 0x00,
// 0x33, 0x80,
// 0x3C, 0x40,
// 0xe1, 0x77,
// 0x00, 0x00,
//};
ov2640cfg.h文件
#ifndef _OV2640CFG_H
#define _OV2640CFG_H
#include "ov2640.h"
#include "stm32f4xx.h"
//
//OV2640 SXGA初始化寄存器序列表
//此模式下幀率為15幀
//SXGA(1600*1200)
static const u8 ov2640_sxga_init_reg_tbl[][2]=
{
0xff, 0x00,
0x2c, 0xff,
0x2e, 0xdf,
0xff, 0x01,
0x3c, 0x32,
//
0x11, 0x00,
0x09, 0x02,
0x04, 0xD8,//水平鏡像,垂直翻轉(zhuǎn)
0x13, 0xe5,
0x14, 0x48,
0x2c, 0x0c,
0x33, 0x78,
0x3a, 0x33,
0x3b, 0xfB,
//
0x3e, 0x00,
0x43, 0x11,
0x16, 0x10,
//
0x39, 0x92,
//
0x35, 0xda,
0x22, 0x1a,
0x37, 0xc3,
0x23, 0x00,
0x34, 0xc0,
0x36, 0x1a,
0x06, 0x88,
0x07, 0xc0,
0x0d, 0x87,
0x0e, 0x41,
0x4c, 0x00,
0x48, 0x00,
0x5B, 0x00,
0x42, 0x03,
//
0x4a, 0x81,
0x21, 0x99,
//
0x24, 0x40,
0x25, 0x38,
0x26, 0x82,
0x5c, 0x00,
0x63, 0x00,
0x46, 0x00,
0x0c, 0x3c,
//
0x61, 0x70,
0x62, 0x80,
0x7c, 0x05,
//
0x20, 0x80,
0x28, 0x30,
0x6c, 0x00,
0x6d, 0x80,
0x6e, 0x00,
0x70, 0x02,
0x71, 0x94,
0x73, 0xc1,
0x3d, 0x34,
0x5a, 0x57,
//
0x12, 0x00,//UXGA 1600*1200
0x17, 0x11,
0x18, 0x75,
0x19, 0x01,
0x1a, 0x97,
0x32, 0x36,
0x03, 0x0f,
0x37, 0x40,
//
0x4f, 0xca,
0x50, 0xa8,
0x5a, 0x23,
0x6d, 0x00,
0x6d, 0x38,
//
0xff, 0x00,
0xe5, 0x7f,
0xf9, 0xc0,
0x41, 0x24,
0xe0, 0x14,
0x76, 0xff,
0x33, 0xa0,
0x42, 0x20,
0x43, 0x18,
0x4c, 0x00,
0x87, 0xd5,
0x88, 0x3f,
0xd7, 0x03,
0xd9, 0x10,
0xd3, 0x82,
//
0xc8, 0x08,
0xc9, 0x80,
//
0x7c, 0x00,
0x7d, 0x00,
0x7c, 0x03,
0x7d, 0x48,
0x7d, 0x48,
0x7c, 0x08,
0x7d, 0x20,
0x7d, 0x10,
0x7d, 0x0e,
//
0x90, 0x00,
0x91, 0x0e,
0x91, 0x1a,
0x91, 0x31,
0x91, 0x5a,
0x91, 0x69,
0x91, 0x75,
0x91, 0x7e,
0x91, 0x88,
0x91, 0x8f,
0x91, 0x96,
0x91, 0xa3,
0x91, 0xaf,
0x91, 0xc4,
0x91, 0xd7,
0x91, 0xe8,
0x91, 0x20,
//
0x92, 0x00,
0x93, 0x06,
0x93, 0xe3,
0x93, 0x05,
0x93, 0x05,
0x93, 0x00,
0x93, 0x04,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
//
0x96, 0x00,
0x97, 0x08,
0x97, 0x19,
0x97, 0x02,
0x97, 0x0c,
0x97, 0x24,
0x97, 0x30,
0x97, 0x28,
0x97, 0x26,
0x97, 0x02,
0x97, 0x98,
0x97, 0x80,
0x97, 0x00,
0x97, 0x00,
//
0xc3, 0xef,
0xa4, 0x00,
0xa8, 0x00,
0xc5, 0x11,
0xc6, 0x51,
0xbf, 0x80,
0xc7, 0x10,
0xb6, 0x66,
0xb8, 0xA5,
0xb7, 0x64,
0xb9, 0x7C,
0xb3, 0xaf,
0xb4, 0x97,
0xb5, 0xFF,
0xb0, 0xC5,
0xb1, 0x94,
0xb2, 0x0f,
0xc4, 0x5c,
//
0xc0, 0xc8,
0xc1, 0x96,
0x8c, 0x00,
0x86, 0x3d,
0x50, 0x00,
0x51, 0x90,
0x52, 0x2c,
0x53, 0x00,
0x54, 0x00,
0x55, 0x88,
0x5a, 0x90,
0x5b, 0x2C,
0x5c, 0x05,
0xd3, 0x05,//auto設(shè)置要小心
//
0xc3, 0xed,
0x7f, 0x00,
0xda, 0x09,
0xe5, 0x1f,
0xe1, 0x67,
0xe0, 0x00,
0xdd, 0x7f,
0x05, 0x00,
};
//OV2640 SVGA初始化寄存器序列表
//此模式下,幀率可以達(dá)到30幀
//SVGA 800*600
static const u8 ov2640_svga_init_reg_tbl[][2]=
{
0xff, 0x00,
0x2c, 0xff,
0x2e, 0xdf,
0xff, 0x01,
0x3c, 0x32,
//
0x11, 0x00,
0x09, 0x02,
0x04, 0xD8,//水平鏡像,垂直翻轉(zhuǎn)
0x13, 0xe5,
0x14, 0x48,
0x2c, 0x0c,
0x33, 0x78,
0x3a, 0x33,
0x3b, 0xfB,
//
0x3e, 0x00,
0x43, 0x11,
0x16, 0x10,
//
0x39, 0x92,
//
0x35, 0xda,
0x22, 0x1a,
0x37, 0xc3,
0x23, 0x00,
0x34, 0xc0,
0x36, 0x1a,
0x06, 0x88,
0x07, 0xc0,
0x0d, 0x87,
0x0e, 0x41,
0x4c, 0x00,
0x48, 0x00,
0x5B, 0x00,
0x42, 0x03,
//
0x4a, 0x81,
0x21, 0x99,
//
0x24, 0x40,
0x25, 0x38,
0x26, 0x82,
0x5c, 0x00,
0x63, 0x00,
0x46, 0x22,
0x0c, 0x3c,
//
0x61, 0x70,
0x62, 0x80,
0x7c, 0x05,
//
0x20, 0x80,
0x28, 0x30,
0x6c, 0x00,
0x6d, 0x80,
0x6e, 0x00,
0x70, 0x02,
0x71, 0x94,
0x73, 0xc1,
0x3d, 0x34,
0x5a, 0x57,
//根據(jù)分辨率不同而設(shè)置
0x12, 0x40,//SVGA 800*600
0x17, 0x11,
0x18, 0x43,
0x19, 0x00,
0x1a, 0x4b,
0x32, 0x09,
0x37, 0xc0,
//
0x4f, 0xca,
0x50, 0xa8,
0x5a, 0x23,
0x6d, 0x00,
0x3d, 0x38,
//
0xff, 0x00,
0xe5, 0x7f,
0xf9, 0xc0,
0x41, 0x24,
0xe0, 0x14,
0x76, 0xff,
0x33, 0xa0,
0x42, 0x20,
0x43, 0x18,
0x4c, 0x00,
0x87, 0xd5,
0x88, 0x3f,
0xd7, 0x03,
0xd9, 0x10,
0xd3, 0x82,
//
0xc8, 0x08,
0xc9, 0x80,
//
0x7c, 0x00,
0x7d, 0x00,
0x7c, 0x03,
0x7d, 0x48,
0x7d, 0x48,
0x7c, 0x08,
0x7d, 0x20,
0x7d, 0x10,
0x7d, 0x0e,
//
0x90, 0x00,
0x91, 0x0e,
0x91, 0x1a,
0x91, 0x31,
0x91, 0x5a,
0x91, 0x69,
0x91, 0x75,
0x91, 0x7e,
0x91, 0x88,
0x91, 0x8f,
0x91, 0x96,
0x91, 0xa3,
0x91, 0xaf,
0x91, 0xc4,
0x91, 0xd7,
0x91, 0xe8,
0x91, 0x20,
//
0x92, 0x00,
0x93, 0x06,
0x93, 0xe3,
0x93, 0x05,
0x93, 0x05,
0x93, 0x00,
0x93, 0x04,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
0x93, 0x00,
//
0x96, 0x00,
0x97, 0x08,
0x97, 0x19,
0x97, 0x02,
0x97, 0x0c,
0x97, 0x24,
0x97, 0x30,
0x97, 0x28,
0x97, 0x26,
0x97, 0x02,
0x97, 0x98,
0x97, 0x80,
0x97, 0x00,
0x97, 0x00,
//
0xc3, 0xed,
0xa4, 0x00,
0xa8, 0x00,
0xc5, 0x11,
0xc6, 0x51,
0xbf, 0x80,
0xc7, 0x10,
0xb6, 0x66,
0xb8, 0xA5,
0xb7, 0x64,
0xb9, 0x7C,
0xb3, 0xaf,
0xb4, 0x97,
0xb5, 0xFF,
0xb0, 0xC5,
0xb1, 0x94,
0xb2, 0x0f,
0xc4, 0x5c,
//根據(jù)分辨率不同而設(shè)置
0xc0, 0x64,
0xc1, 0x4B,
0x8c, 0x00,
0x86, 0x3D,
0x50, 0x00,
0x51, 0xC8,
0x52, 0x96,
0x53, 0x00,
0x54, 0x00,
0x55, 0x00,
0x5a, 0xC8,
0x5b, 0x96,
0x5c, 0x00,
0xd3, 0x02,//auto設(shè)置要小心
//
0xc3, 0xed,
0x7f, 0x00,
0xda, 0x09,
0xe5, 0x1f,
0xe1, 0x67,
0xe0, 0x00,
0xdd, 0x7f,
0x05, 0x00,
};
static const u8 ov2640_jpeg_reg_tbl[][2]=
{
0xff, 0x01,
0xe0, 0x14,
0xe1, 0x77,
0xe5, 0x1f,
0xd7, 0x03,
0xda, 0x10,
0xe0, 0x00,
};
static const u8 ov2640_yuv422_reg_tbl[][2]=
{
0xFF, 0x00,
0xDA, 0x10,
0xD7, 0x03,
0xDF, 0x00,
0x33, 0x80,
0x3C, 0x40,
0xe1, 0x77,
0x00, 0x00,
};
#endif
base64.c文件
#include "base64.h"
//unsigned char counts[4*4096];
//u16 count=0;
unsigned char *base64_encode( const char *str) // const char *str
{
long len;
long str_len;
unsigned char *res;
int i,j;
//定義base64編碼表
char *base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//計算經(jīng)過base64編碼后的字符串長度
str_len=strlen(str);
if(str_len % 3 == 0)
len=str_len/3*4;
else
len=(str_len/3+1)*4;
res=malloc(sizeof(unsigned char)*len+1);
res[len]='\0';
//以3個8位字符為一組進(jìn)行編碼
for(i=0,j=0;i<len-2;j+=3,i+=4)
{
res[i]=base64_table[str[j]>>2]; //取出第一個字符的前6位并找出對應(yīng)的結(jié)果字符
res[i+1]=base64_table[(str[j]&0x3)<<4 | (str[j+1]>>4)]; //將第一個字符的后位與第二個字符的前4位進(jìn)行組合并找到對應(yīng)的結(jié)果字符
res[i+2]=base64_table[(str[j+1]&0xf)<<2 | (str[j+2]>>6)]; //將第二個字符的后4位與第三個字符的前2位組合并找出對應(yīng)的結(jié)果字符
res[i+3]=base64_table[str[j+2]&0x3f]; //取出第三個字符的后6位并找出結(jié)果字符
}
// switch(str_len % 3)
// {
// case 1:
// res[i-2]='=';
// res[i-1]='=';
// break;
// case 2:
// res[i-1]='=';
// break;
// }
return res;
}
int base64( u8 a,u8 b,u8 c)
{
char *base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char *res;
//printf("\r\n%x",a);
//printf("%x",b);
//printf("%x ",c);
res[0]=base64_table[a>>2]; //取出第一個字符的前6位并找出對應(yīng)的結(jié)果字符
res[1]=base64_table[(a&0x3)<<4 | (b>>4)]; //將第一個字符的后位與第二個字符的前4位進(jìn)行組合并找到對應(yīng)的結(jié)果字符
res[2]=base64_table[(b&0xf)<<2 | (c>>6)]; //將第二個字符的后4位與第三個字符的前2位組合并找出對應(yīng)的結(jié)果字符
res[3]=base64_table[c&0x3f]; //取出第三個字符的后6位并找出結(jié)果字符
// res[4]='\0';
//strcat(counts,res);
printf("%s",res);
//count=count+4;
return 1;
}
//void OutPut(void){
printf("%s",counts);
printf("\r\n%d",count);
// count = 0;
//}
base64.h文件
#ifndef __BASE64_H_
#define __BASE64_H_
/********************頭文件************************/
#include "stm32f4xx.h"
#include "stdio.h"
#include "string.h"
#include <stdlib.h>
/********************宏定義************************/
/*****************聲明外部變量*********************/
/*******************函數(shù)聲明***********************/
unsigned char *base64_encode( const char *str);//const char
int base64( u8 a,u8 b,u8 c);
void OutPut(void);
#endif
uart_2.c文件
#include "uart_2.h"
/*********************************************
*函數(shù)功能:UART1初始化
*函數(shù)形參:uint32_t band 波特率
*函數(shù)返回值:None
*備注:PA2 -- RX
PA3 -- TX
*********************************************/
void Uart2_Init(uint32_t band)
{
//開啟GPIOA時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//開啟UART1時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
//配置GPIO
//PA2和PA3為復(fù)用模式
GPIO_InitTypeDef GPIO_InitStruct;
//輸出模式
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
//引腳號
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
GPIO_Init(GPIOA, &GPIO_InitStruct);
//配置UART1
USART_InitTypeDef USART_InitStruct;
//波特率
USART_InitStruct.USART_BaudRate = band;
//禁止硬件流控
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//使能發(fā)送和接收
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
//關(guān)閉奇偶校驗
USART_InitStruct.USART_Parity = USART_Parity_No;
//1位停止位
USART_InitStruct.USART_StopBits = USART_StopBits_1;
//8位數(shù)據(jù)位
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_Init(USART2, &USART_InitStruct);
//使能接收中斷
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
//設(shè)置中斷優(yōu)先級 串口優(yōu)先級設(shè)置為最高,以防接收中被打斷
NVIC_SetPriority(USART2_IRQn, NVIC_EncodePriority(7-2, 0, 0));
//使能NVIC響應(yīng)
NVIC_EnableIRQ(USART2_IRQn);
//使能UART1
USART_Cmd(USART2, ENABLE);
}
uint8_t rev_buf_2[REV_BUF_LEN];
uint8_t rev_ok_2;
//編寫中斷服務(wù)函數(shù)
void USART2_IRQHandler(void)
{
static uint8_t i = 0;
//讀數(shù)據(jù)寄存器非空
if(USART2->SR & (0x1 << 5)){
rev_buf_2[i++] = USART2->DR;//讀取數(shù)據(jù)寄存器信息,清空標(biāo)志位
while(USART2->SR & (0x1 << 5));//等待標(biāo)志位清零
}else if(USART2->SR & (0x1 << 4)){//檢測到總線空閑
//清標(biāo)志位
if(USART2->SR)
;
if(USART2->DR)
;
while(USART2->SR & (0x1 << 4));//等待標(biāo)志位清零
rev_buf_2[i] = '\0';//字符串結(jié)尾
i = 0;
rev_ok_2 = 1;//接收完成
}
}
/*********************************************
*函數(shù)功能:UART2發(fā)送字符串函數(shù)
*函數(shù)形參:uint8_t *str 要發(fā)送的字符串
*函數(shù)返回值:None
*備注:None
*********************************************/
void Uart2_Send_String(uint8_t *str)
{
while(*str){
//等待發(fā)送數(shù)據(jù)寄存器為空
while(!USART_GetFlagStatus(USART2, USART_FLAG_TXE));
USART_SendData(USART2, *str);
str++;
}
}
uart_2.h文件
#ifndef __UART_2_H_
#define __UART_2_H_
/********************頭文件************************/
#include "stm32f4xx.h"
#include "stdio.h"
/********************宏定義************************/
#define REV_BUF_LEN (256)
/*****************聲明外部變量*********************/
extern uint8_t rev_buf_2[REV_BUF_LEN];
extern uint8_t rev_ok_2;
/*******************函數(shù)聲明***********************/
void Uart2_Init(uint32_t band);
void Uart2_Send_String(uint8_t *str);
#endif
二、STM32與ESP8266
當(dāng)ESP8266向stm32發(fā)送數(shù)據(jù)“picture”并且stm32接收到時stm32會控制ov2640拍得jpeg格式的圖片。當(dāng)stm32取得二進(jìn)制數(shù)據(jù)時會進(jìn)行base64編碼,當(dāng)編碼后會對數(shù)據(jù)進(jìn)行分段(4段防止過長使得數(shù)據(jù)丟失)。此時esp8266會等待接收數(shù)據(jù),一共會檢測四次并接收四次。
arduino
#include <ESP8266WiFi.h>
String buffers;//用于存放接收到的數(shù)據(jù)
int b=0;//串口接收
int a=0;//用來判斷物體的種類
char* output;//用來存放服務(wù)器響應(yīng)數(shù)據(jù)
#define SSID "12345678"http://改為你自己的WiFi名稱
#define PASSWORD "1qaz1qaz"http://改為你自己的密碼
#define ACCESS_TOKEN "24.70cf22c4e99c1228ff5d3cd1cca80766.2592000.1657886015."http://改為你自己的access_token教程見下文
#define Json_begin "{\"image\": \""
#define Json_end "\",\"threshold\": 0.1}"http://此處0.1為置信度可以改0~1之間
//串口接收函數(shù)
int uart(){
while(Serial.available()>0){
if(Serial.available()>0){buffers=Serial.readString();b++;}
}
}
//采用https方法訪問百度服務(wù)器
static void Baidu_AI(){
//判斷接收到信息的數(shù)據(jù)長度
uint32_t len = buffers.length();
Serial.print(len);
WiFiClientSecure client;
client.setInsecure();
delay(1000);
if(client.connect("aip.baidubce.com",443)){
Serial.println("Connection succeeded");
//注意下面代碼中的空格很重要 此處的***********************也要換為自己的詳見下文
client.println("POST ***********************?access_token=" + String(ACCESS_TOKEN) + " HTTP/1.1");
client.println(F("Host: aip.baidubce.com"));
client.println("Content-Length: " + String(len + strlen(Json_begin Json_end)));
client.println(F("Content-Type: application/json"));
client.println();
client.print(F(Json_begin));
client.print(buffers);
client.print(F(Json_end));
//Serial.println("Waiting for response...");
uint8_t i_i = 0;
while (!client.available()){
i_i += 1;
delay(100);
if(i_i > 200){ //超時
Serial.println("No response...");
break;
}
}
String body;//響應(yīng)體
while (client.available()){
body= client.readString();
//Serial.print(body);
output= const_cast<char*>(body.c_str());
Serial.print(output);//串口輸出服務(wù)器響應(yīng)結(jié)果
//Serial.print(char(client.read()));
}
client.stop();
//Serial.println();
}else Serial.println("Connection failed");
}
void setup() {
//初始化串口
Serial.begin(115200);
//連接WIFI
WiFi.begin(SSID,PASSWORD);
while (WiFi.status() != WL_CONNECTED){
//Serial.println("Waitting for wifi connection...");
delay(500);
}
Serial.println("wifi已近連接");
}
void loop() {
while(Serial.available()>0){ //是否串口有輸入
if((Serial.read()=='o')&&b==0){ 判斷串口接收是否為"o"
String buffers_s;//整合分段接收的數(shù)據(jù)
while(1){
uart();
if(b==1){
Serial.println(buffers);
output=const_cast<char*>(buffers.c_str());
if(output[1]=='9'&&output[2]=='j'){ //用于判斷接收到的數(shù)據(jù)是否為"/9j"開頭,用于精確定位開頭
buffers_s=buffers_s+buffers;
b=2;}
else {b=0;}
//Serial.println(buffers);
}
else if(b==3){
buffers_s=buffers_s+buffers;
//delay(100);
b=4;
//Serial.println(buffers);
}
else if(b==5){
buffers_s=buffers_s+buffers;
//delay(100);
b=6;
//Serial.println(buffers);
}
else if(b==7){
buffers_s=buffers_s+buffers;
b=0;
break;
}
//Serial.println(b);
}
buffers=buffers_s;
Serial.println();
Serial.println();
Serial.println(buffers);
Baidu_AI();
}
}
}
上邊的代碼中最重要的就是需要更換一些信息。有WiFi名稱,WiFi密碼,你自己專屬的access_token碼,此碼有效期為一個月,過時需要更換,還有就是需要更換訪問鏈接就是代碼中的*******************要被更換掉。
三、ESP8266與EasyDL
此時主要是需要在EASYDL平臺部署模型,這里就不詳細(xì)進(jìn)行簡紹了,可以直接找官方的教程有文檔形式的有視頻教學(xué)過程,這里寫一下重要的過程。首先獲取access_token的過程是
首先當(dāng)你部署好模型并且發(fā)布以后找到在線服務(wù)點擊控制臺進(jìn)去以后應(yīng)是

點擊公有云部署中的應(yīng)用列表如下

此時可以找到API Key與Secret Key要注意的是復(fù)制Secret Key時要注意空格
將你上邊的API Key與Secret Key替換下邊的這個鏈接里的就行,然后將替換以后的鏈接在瀏覽器上打開就行,這時你可以找到access_token碼注意是“”里邊的
https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=API Key&client_secret=Secret Key
此時回到easydl平臺的在線服務(wù)點擊服務(wù)詳情會看到接口地址https://aip.baidubce.com/rpc/2.0/ai_custom/v1/detection/xiadoz像這樣一樣,你們的和我的后半部分不太一樣,這是因為模型的名字不一樣。至此arduino中的代碼只差訪問鏈接也就是代碼中的*******************需要被接口地址中的紅色部分替換。
至此所有的操作就完成了,代碼方面也就這些東西,對于easydl方面官方都有。對于接線方面有些記不清楚了。(其實也不多)對于攝像頭有專門的排線,對于esp8266與stm32就只有串口通訊而已,如果沒記錯的話應(yīng)該是串口二,代碼中應(yīng)該有注釋。希望大家可以仔細(xì)看一遍,看一遍也是一種學(xué)習(xí)的過程,直接ctrl c ctrl v是對自己的不負(fù)責(zé)任。關(guān)于其他方面的功能歡迎大家開發(fā),開發(fā)好以后放在評論區(qū),大家共同進(jìn)步。既然你點進(jìn)這篇文章,我希望它對你有幫助。文章來源:http://www.zghlxwxcb.cn/news/detail-445271.html
感謝你的閱讀,若有問題歡迎雅正。文章來源地址http://www.zghlxwxcb.cn/news/detail-445271.html
到了這里,關(guān)于STM32F407ZGT6控制ESP8266與OV2640下的百度智能圖片識別的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!