一、前言
这几天在用cubemx移植ov2640,数据输出到屏幕始终是蓝色的,百思不得其解,终于我找到了个大坑,那就是之前把lcd显示的方向改成了横屏(一定要设置成竖屏!),接下来进入正题,本文想实现的功能为将摄像头的数据显示到屏幕。
图1 LCD方向设置错误
二、前提条件
如果你能搜到这篇文章,那么就默认你的lcd驱动是正常的,我这里采用FMC驱动屏幕,屏幕和摄像头的代码均从正点原子移植。
三、接线图
原理图略过,直接看怎么接线。
注意事项:
1.3.3V
2.OV_SCL和OV_SDA 都用软件IIC驱动
3.NC表示不用接
4.其他引脚由cubemx配置
图2 接线
四、cubemx配置
DCMI的配置参考这位哥的,之后生成工程
五、代码移植
参考正点原子例程,用到了如下驱动。我这边分享一下,大家可以自己去官方下载,可以下载stm32f429阿波罗开发板的资料-->摄像头实验,驱动刚刚更新过,比较规范。
正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档
下面我来告诉大家需要修改的地方
1.sccb.h 修改这两个引脚,参考看上面原理图 排针3 排针5的位置,自己选择引脚驱动软件IIC
2. main.c USER CODE BEGIN 2的位置 进行ov2640初始化,看看是否初始化成功。
while (ov2640_init()) /* 初始化OV2640 */
{
lcd_show_string(30, 130, 240, 24, 24, "OV2640 ERROR", RED);
delay_ms(200);
lcd_fill(30, 130, 239, 170, WHITE);
delay_ms(200);
LD2_Toggle;
}
lcd_show_string(30, 185, 200, 24, 24, "OV2640 OK", RED);
ov2640_flash_intctrl(); /* 闪光灯控制 */
烧写!如果屏幕上显示OV2640 OK,则进行下一步。
3. main.c USER CODE BEGIN PV 添加
extern DCMI_HandleTypeDef g_dcmi_handle;
4. cubemx 生成的 dcmi.c USER CODE BEGIN 0里
/* USER CODE BEGIN 0 */
#include "./lcd/lcd.h"
#include "./LED/bsp_led.h"
#include "stdio.h"
extern void jpeg_data_process(void);
/* USER CODE END 0 */
5.cubemx 生成的 dcmi.c 31行这里,把hdcmi替换成g_dcmi_handle(替换所有)
6. cubemx 生成的 dcmi.c USER CODE BEGIN 1里
/* USER CODE BEGIN 1 */
/**
* @brief DCMI,启动传输
* @param 无
* @retval 无
*/
void dcmi_start(void)
{
lcd_set_cursor(0, 0); /* 设置坐标到原点 */
lcd_write_ram_prepare(); /* 开始写入GRAM */
__HAL_DMA_ENABLE(&hdma_dcmi); /* 使能DMA */
DCMI->CR |= DCMI_CR_CAPTURE; /* DCMI捕获使能 */
}
/**
* @brief DCMI中断回调服务函数
* @param g_dcmi_handle:DCMI句柄
* @note 捕获到一帧图像处理
* @retval 无
*/
void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
{
if(DCMI == hdcmi->Instance)
{
__HAL_DCMI_CLEAR_FLAG(&g_dcmi_handle, DCMI_FLAG_FRAMERI); /* 清除帧中断 */
jpeg_data_process(); /* jpeg数据处理 */
LD2_Toggle; /* LED2闪烁 */
// g_ov_frame++;
/* 重新使能帧中断,因为HAL_DCMI_IRQHandler()函数会关闭帧中断 */
__HAL_DCMI_ENABLE_IT(&g_dcmi_handle, DCMI_IT_FRAME);
}
}
/* USER CODE END 1 */
7. main.c USER CODE BEGIN 0添加这两个函数
**
* @brief 处理JPEG数据
* @note 在DCMI_IRQHandler中断服务函数里面被调用
* RGB565模式只有下面这两句
* @param 无
* @retval 无
*/
void jpeg_data_process(void)
{
lcd_set_cursor(0, 0);
lcd_write_ram_prepare(); /* 开始写入GRAM */
}
/**
* @brief RGB565测试
* @note RGB数据直接显示在LCD上面
* @retval 无
*/
void rgb565_test(void)
{
ov2640_rgb565_mode(); /* RGB565模式 */
DCMI->IER = 0x0;
__HAL_DCMI_ENABLE_IT(&g_dcmi_handle, DCMI_IT_FRAME); /* 使能帧中断 */
__HAL_DCMI_ENABLE(&g_dcmi_handle); /* 使能DCMI */
__HAL_DMA_DISABLE_IT(&hdma_dcmi, DMA_IT_TC); /* 先关闭DMA传输完成中断,否则在使用MCU屏幕的时候会出现花屏的情况 */
__HAL_UNLOCK(&hdma_dcmi);
HAL_DCMI_Start_DMA(&g_dcmi_handle,DCMI_MODE_CONTINUOUS,(uint32_t)&LCD->LCD_RAM,1); //DCMI启动DMA通道
HAL_DMA_Start(&hdma_dcmi, (uint32_t)&DCMI->DR, (uint32_t)&LCD->LCD_RAM, 1);
ov2640_outsize_set(lcddev.width, lcddev.height); /* 满屏缩放显示 */
dcmi_start(); /* 启动传输 */
}
8.最后在主函数调用,我这里放在USER CODE END 2前面
之后就移植完毕了,可以烧写看看运行结果。
六、程序优化
大家可以看到代码移植的第5步,我把cubemx生成的替换了,是因为DCMI的回调函数有个hdcmi参数,会冲突,目前我还不知道如何修改,知道的小伙伴可以在评论区留言......
帧率优化,参考b站的视频,我还没试成功。
JPEG和帧率的显示大家再参考正点原子代码吧,可以看看b站视频。
七、结束语
设置竖屏在lcd_init的lcd_display_dir(0),一定要设置成竖屏!!!
移植有问题的可以在评论区留言。