学前班
最后登录1970-1-1
在线时间 小时
注册时间2017-4-8
|
20火花
功能: 使用ov2640摄像头,将拍到的图片以rgb888格式保存至sd卡中
基本思路:
1. 修改系统代码,将堆大小设置为8M;
2. 修改分散脚本,使堆的地址为0xD0000000(sdram起始地址);
2. 动态分配内存,并进行系列初始化,dma传输的目标的地址为动态创建内存的首地址;
3. 使能dcmi并使能dcmi捕捉,延时1s后,关闭dcmi、dcmi捕捉和dma传输;
4. 调用函数,将图像转换为rgb888;
5. 使用文件系统,将rgb888写入sd卡;
所遇问题:
在上位机中查看rgb888.bmp,最下方约30行显示正常,其余上部分全部花屏,参见图片
此处是正常的,以上均为花屏
请留意:
sdram已经过测试,堆的使用没有任何问题,最大可以分配 (0x800000-0xC) byte,略小于8M
核心代码:
bmp_rgb565_to_rgb888:
tmp_ptr = new_data_ptr + HEAD_INFO_SIZE;
for(i = 0; i < img_height; i++)
{
data_ptr = data_addr + i*img_width;
for(j = 0; j < img_width; j++)
{
*tmp_ptr++ = (data_ptr[j] & 0x001F) << 3;
*tmp_ptr++ = ((data_ptr[j] & 0x07E0) >> 5) << 2;
*tmp_ptr++ = ((data_ptr[j] & 0xF800) >> 11) << 3;
}
}
上述转换在上位机上使用是没有任何问题的
中断服务程序:
void DMA2_Stream1_IRQHandler(void)
{
if(SET == DMA_GetITStatus(DMA2_Stream1,DMA_IT_TCIF1))
{
current_height++;
total_height++;
if(current_height == g_img_height)
{
current_height = 0;
}
tmp = (uint32_t)g_dma_target_addr +
g_img_width*2*(g_img_height-current_height-1);
OV2640_DMA_Config(tmp, g_dma_buf_size);
DMA_ClearITPendingBit(DMA2_Stream1,DMA_IT_TCIF1);
}
}
void DCMI_IRQHandler(void)
{
if(SET == DCMI_GetITStatus(DCMI_IT_FRAME))
{
current_height = 0;
flag++;
DCMI->ICR = DCMI_IT_FRAME;
//DCMI_ClearITPendingBit(DCMI_IT_FRAME);
}
}
主函数:
int main(void)
{
BL8782_PDN_INIT();
OV2640_HW_Init();
OV2640_IDTypeDef ov2640_id;
OV2640_ReadID(&ov2640_id);
if(ov2640_id.PIDH != 0x26)
{
DISP_ERR("not detected camera, please check the connection again \n");
return -1;
}
DISP("Manufacturer_ID1 = %x \nManufacturer_ID2 = %x \n",
ov2640_id.Manufacturer_ID1, ov2640_id.Manufacturer_ID2);
sdram_bulk_reset();
uint16_t *initail_data_ptr = (uint16_t *)malloc(g_img_size);
if(!initail_data_ptr)
{
DISP_ERR(ERR_MALLOC);
return -1;
}
g_dma_target_addr = initail_data_ptr;
OV2640_Init();
OV2640_UXGAConfig();
DCMI_Cmd(ENABLE);
DCMI_CaptureCmd(ENABLE);
sleep(1);
DISP("flag = %d \ncurrent_height = %d \ntotal_height = %d \n",
flag, current_height, total_height);
DCMI_Cmd(DISABLE);
DCMI_CaptureCmd(DISABLE);
DMA_Cmd(DMA2_Stream1, DISABLE);
DISP("success disable \n");
uint8_t *rgb888_ptr = NULL;
rgb888_ptr = bmp_rgb565_to_rgb888(g_img_width, g_img_height, g_dma_target_addr);
if(!rgb888_ptr)
{
DISP_ERR("error in bmp_rgb565_to_rgb888 \n");
free(g_dma_target_addr);
return -1;
}
uint32_t fnum = 0;
res_sd = f_mount(&fs,"0:",1);
if(res_sd == FR_NO_FILESYSTEM)
{
DISP("no file system in sd card, ready to format \n");
res_sd=f_mkfs("0:",0,0);
if(res_sd == FR_OK)
{
DISP("success formatting\n");
res_sd = f_mount(NULL,"0:",1);
res_sd = f_mount(&fs,"0:",1);
}
else
{
DISP("failed to format \n");
return -1;
}
}
else if(res_sd != FR_OK)
{
DISP("failed to mount, error code: %d \n", res_sd);
DISP("ensure card inserted to the board \n");
DISP("ensure 3V3_WIFI connetted to 3V3 instead of GND \n");
return -1;
}
else
{
DISP("success mounting\n");
}
DISP("ready to write the file to card... \n");
uint32_t real_width = COUNT_REAL_WIDTH(g_img_width*24);
uint32_t real_size = real_width * g_img_height;
res_sd = f_open(&fnew, "0:test.bmp", FA_CREATE_ALWAYS | FA_WRITE );
if (res_sd == FR_OK)
{
DISP("success creating bmp file in sd card \n");
res_sd = f_write(&fnew, rgb888_ptr, real_size+HEAD_INFO_SIZE, &fnum);
if((res_sd == FR_OK) && (fnum == real_size+HEAD_INFO_SIZE))
{
DISP("success writing data to bmp file \n");
}
else
{
DISP("error in f_write:%d \n", res_sd);
}
f_close(&fnew);
}
else
{
DISP_ERR("error in fopen");
}
f_mount(NULL,"0:",1);
free(rgb888_ptr);
free(g_dma_target_addr);
DISP("end of project \n");
return 0;
}
|
|