以下是OV2640 STM32直驱的关键代码。
dma.c:
[mw_shl_code=c,true]//SRAM --> LCD_RAM dma配置
//caddr:数据源地址
//16位,从SRAM传输到LCD_RAM.
void MYDMA_SRAMLCD_Init(u32 caddr)
{
RCC->AHBENR|=1<<1; //开启DMA2时钟
DMA2_Channel5->CPAR=caddr; //DMA2,源存储器地址
DMA2_Channel5->CMAR=(u32)&LCD->LCD_RAM; //目标地址为LCD_RAM
DMA2_Channel5->CNDTR=0; //DMA2,传输数据量,暂定为0
DMA2_Channel5->CCR=0X00000000; //复位
DMA2_Channel5->CCR|=0<<4; //从外设读
DMA2_Channel5->CCR|=0<<5; //普通模式
DMA2_Channel5->CCR|=1<<6; //外设地址增量模式
DMA2_Channel5->CCR|=0<<7; //存储器非增量模式
DMA2_Channel5->CCR|=1<<8; //外设数据宽度为16位
DMA2_Channel5->CCR|=1<<10; //存储器数据宽度16位
DMA2_Channel5->CCR|=1<<12; //中等优先级
DMA2_Channel5->CCR|=1<<14; //存储器到存储器模式(不需要外部请求)
}
//开启一次SRAM到LCD的DMA的传输
void MYDMA_SRAMLCD_Enable(void)
{
DMA2_Channel5->CCR&=~(1<<0); //关闭DMA传输
DMA2_Channel5->CNDTR=lcddev.width; //设置传输长度
DMA2_Channel5->CCR|=1<<0; //开启DMA传输
}
[/mw_shl_code]
main函数:
[mw_shl_code=c,true]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_speed_ctrl();
MYDMA_SRAMLCD_Init((u32)ov2640_framebuf);
while(1)
{
while(OV2640_VSYNC) //等待帧信号
{
key=KEY_Scan(0); //不支持连按
if(key==KEY0_PRES||key==KEY1_PRES)
{
LED1=0; //DS1亮
if(sd_ok) //SD卡正常才可以拍照
{
if(key==KEY0_PRES) //BMP拍照
{
camera_new_pathname(pname,0); //得到文件名
res=bmp_encode(pname,0,0,lcddev.width,lcddev.height,0);
}else if(key==KEY1_PRES) //JPG拍照
{
camera_new_pathname(pname,1); //得到文件名
res=ov2640_jpg_photo(pname);
OV2640_OutSize_Set(lcddev.width,lcddev.height);
ov2640_speed_ctrl();
}
if(res)//拍照有误
{
Show_Str(30,130,240,16,"写入文件错误!",16,0);
}else
{
Show_Str(30,130,240,16,"拍照成功!",16,0);
Show_Str(30,150,240,16,"保存为:",16,0);
Show_Str(30+42,150,240,16,pname,16,0);
BEEP=1; //蜂鸣器短叫,提示拍照完成
delay_ms(100);
}
}else //提示SD卡错误
{
Show_Str(40,130,240,12,"SD卡错误!",12,0);
Show_Str(40,150,240,12,"拍照功能不可用!",12,0);
}
LED1=1; //DS1灭
BEEP=0; //关闭蜂鸣器
delay_ms(1800);
}
}
LCD_SetCursor(0,0); //设置坐标
LCD_WriteRAM_Prepare(); //开始写入GRAM
linecnt=0; //行统计清零
pixcnt=0; //像素计数器清零
while(linecnt<lcddev.height)
{
while(OV2640_HREF)
{
while(OV2640_PCLK==0);
ov2640_framebuf[pixcnt++]=OV2640_DATA;
while(OV2640_PCLK==1);
while(OV2640_PCLK==0);
ov2640_framebuf[pixcnt++]=OV2640_DATA;
while(OV2640_PCLK==1);
}
if(pixcnt)
{
MYDMA_SRAMLCD_Enable(); //启动DMA数据传输
pixcnt=0;
linecnt++;
}
}
ov_frame++;
LED0=!LED0;
}
}[/mw_shl_code]
|