本帖最后由 colin2135 于 2019-1-8 22:00 编辑
FreeRTOS使用DCMI采集JPEG教程
话不多说,先上代码,地址:
FreeRTOS_OV2640.zip
(858.26 KB)
在很久很久之前,分享过一次使用STM32F446+OV2640采集JPEG的例子,大家的反响挺不错的。链接在这:https://bbs.21ic.com/icview-1156856-1-1.html
说来惭愧,stm32开发好多年了,一直处于裸奔开发,最近才开始学FreeRTOS,所以把上面的例程移植到了FreeRTOS下面。
主要硬件:
用到了的外设:
- 硬件的I2C
- MCO1,输出16M XCLK给OV2640
- DCMI 数字图像接口
- UART 用来和上位机通信
开发软件:TrueSTUDIO 9.1.0
选择好上面的外设后,通过STM32CubeMX生成。
图1 外设配置图
图2 升级1:画了一块底板
图3 升级2:加上WIFI模块
代码逻辑:
- 代码开始,先初始化串口和DCMI。
- 新建2个线程:串口线程、拍照线程;新建2个信号量:开始拍照、拍照完成
- 串口线程:等待上位机发送拍照信号,收到后释放开始拍照信号量。
- 拍照线程:等待释放拍照信号量,收到后,触发DCMI函数接收JPEG图像。
- 当收到DCMI的帧完成中断,释放拍照完成信号量,上传JPEG图像到上位机。
关键代码:
信号量:
osSemaphoreId sem_TakePhoto;//收到开始拍照信号量
osSemaphoreId sem_GetPhoto;//接收拍照完成信号量
串口线程:
void StartUartTask(void const * argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
HAL_UART_Receive_IT(UartHandle, RxTemp, 2);
for(;;)
{
//osDelay(1);
if (osSemaphoreWait(osSemaphore , osWaitForever) == osOK)
{
//HAL_UART_Transmit(UartHandle,RxTemp,1,0XFFFFF);
if(RxTemp[0] == 'a' && RxTemp[1] == 'a')
{
//启用拍照,释放拍照的信号量
ov2640_realseTakePhotoSem();
}
memset(RxTemp,0,2);
HAL_UART_Receive_IT(UartHandle,RxTemp, 2);
}
}
/* USER CODE END 5 */
}
拍照线程:
void StartOV2640Task(void const * argument)//拍照的线程
{
for(;;)
{
if (osSemaphoreWait(sem_TakePhoto , osWaitForever) == osOK)//等待串口释放拍照信号量
{
__HAL_DCMI_ENABLE_IT(DCMI_hdcmi, DCMI_IT_FRAME);//使用帧中断
memset((void *)JpegBuffer,0,sizeof(JpegBuffer));//把接收BUF清空
HAL_DCMI_Start_DMA(DCMI_hdcmi, DCMI_MODE_SNAPSHOT,(uint32_t)JpegBuffer, pictureBufferLength);//启动拍照
if(osSemaphoreWait(sem_GetPhoto , osWaitForever) == osOK)//等待DCMI释放一帧图像信号量
{
HAL_DCMI_Suspend(DCMI_hdcmi);//拍照完成,挂起DCMI
HAL_DCMI_Stop(DCMI_hdcmi);//拍照完成,停止DMA传输
int pictureLength =pictureBufferLength;
while(pictureLength > 0)//循环计算出接收的JPEG的大小
{
if(JpegBuffer[pictureLength-1] != 0x00000000)
{
break;
}
pictureLength--;
}
pictureLength*=4;//buf是uint32_t,下面发送是uint8_t,所以长度要*4
Uart_Send((uint8_t*)JpegBuffer, pictureLength);
}
}
}
}
上位机收到的拍照显示(送给大家个大橙子):
图4 上位机显示
|
很好的资源,学习啦~~