赞
踩
因为之前电赛使用到了Openmv作为摄像头,处理完数据后将数据传回STM32主控来进行后续的操作,也看了很多论坛上的文章,但总感觉代码结构都不是自己的风格,以此记录一下。
本文章STM32的配置,按照我之前的风格,都为从Cubemax配置生成。
OpenMv | STM32 |
---|---|
TX(P4) | RX |
GND | GND |
首先介绍一下OpenMv这边的代码
主要使用的是ustruct这个库来作为串口的发送,注意,如果是直接用OpenMv的串口write发送,单片机这边收到的数据是不好处理的。
首先OpenMv也是单片机,要对其串口进行配置。
from pyb import UART
uart = UART(3,115200) #定义串口3变量
uart.init(115200, bits=8, parity=None, stop=1) # 这里串口设置要和后面stm32的对应
主要发送函数为如下
def sending_data(cx,cy,cw,ch): global uart; """ Format C Type Python 字节数 b signed char integer 1 h short integer 2 i int integer 4 """ data = ustruct.pack("<bbhhhhb", #格式为俩个字符俩个短整型(2字节) 0x2C, #帧头1 0x12, #帧头2 int(cx), # up sample by 4 #数据1 int(cy), # up sample by 4 #数据2 int(cw), # up sample by 4 #数据1 int(ch), # up sample by 4 #数据2 0x5B) #帧尾 uart.write(data); #必须要传入一个字节数组
首先简单的时钟树配置,就不在这里讲了,只要按照自己使用的单片机芯片进行配置就好,如果不会的话,可以看我之前的文章。
这里主要讲讲串口及DMA的配置
这里我使用的是串口3,这里的配置要和上面OpenMv对应上
开启中断
开启接收DMA
配置完成后就可以生成代码了。
当然也可以把开启初始化放在别的地方。
/* USART3 init function */ void MX_USART3_UART_Init(void) { /* USER CODE BEGIN USART3_Init 0 */ /* USER CODE END USART3_Init 0 */ /* USER CODE BEGIN USART3_Init 1 */ /* USER CODE END USART3_Init 1 */ huart3.Instance = USART3; huart3.Init.BaudRate = 115200; huart3.Init.WordLength = UART_WORDLENGTH_8B; huart3.Init.StopBits = UART_STOPBITS_1; huart3.Init.Parity = UART_PARITY_NONE; huart3.Init.Mode = UART_MODE_TX_RX; huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart3.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart3) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART3_Init 2 */ // 加入DMA空闲中断 __HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE); HAL_UART_Receive_DMA(&huart3,OpennMv_Data.RxBuffer,RXBUFFER_LEN); /* USER CODE END USART3_Init 2 */ }
#define RXBUFFER_LEN 20
typedef struct User_USART
{
uint8_t Rx_flag;
uint8_t Rx_len; //接收长度
uint8_t frame_head[2]; //帧头
uint8_t frame_tail; //帧尾
int x,y,w,h; //处理数据
uint8_t RxBuffer[RXBUFFER_LEN]; //接收缓存
}User_USART;
/** * @brief This function handles USART3 global interrupt. */ void USART3_IRQHandler(void) { /* USER CODE BEGIN USART3_IRQn 0 */ // 空闲中断处理 uint32_t temp_flag = 0; uint32_t temp; temp_flag = __HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE); if((temp_flag!=RESET)) { __HAL_UART_CLEAR_IDLEFLAG(&huart3); temp = huart3.Instance->SR; temp = huart3.Instance->DR; HAL_UART_DMAStop(&huart3); temp = hdma_usart3_rx.Instance->NDTR; //F1的板子 temp = hdma_usart3_rx.Instance->CNDTR; OpennMv_Data.Rx_len = RXBUFFER_LEN-temp; OpenMvData_Process(OpennMv_Data.RxBuffer); //按照自己需求改写这个函数 OpennMv_Data.Rx_flag = 1; } HAL_UART_Receive_DMA(&huart3,OpennMv_Data.RxBuffer,RXBUFFER_LEN); /* USER CODE END USART3_IRQn 0 */ HAL_UART_IRQHandler(&huart3); /* USER CODE BEGIN USART3_IRQn 1 */ /* USER CODE END USART3_IRQn 1 */ }
//结构体初始化 void User_USART_Init(User_USART *Data) { for(uint8_t i=0; i < RXBUFFER_LEN; i++) Data->RxBuffer[i] = 0; Data->frame_head[0] = 0x2C; Data->frame_head[1] = 0x12; Data->frame_tail = 0x5B; Data->Rx_flag = 0; Data->Rx_len = 0; Data->x = 0; Data->y = 0; Data->w = 0; Data->h = 0; } void OpenMvData_Process(uint8_t *RxBuffer) { //判断帧头帧尾 if(RxBuffer[0] != OpennMv_Data.frame_head[0]) return; if(RxBuffer[1] != OpennMv_Data.frame_head[1]) return; if(RxBuffer[10] != OpennMv_Data.frame_tail) return; OpennMv_Data.x = (RxBuffer[3]<<8)|RxBuffer[2]; OpennMv_Data.y = (RxBuffer[5]<<8)|RxBuffer[4]; OpennMv_Data.w = (RxBuffer[7]<<8)|RxBuffer[6]; OpennMv_Data.h = (RxBuffer[9]<<8)|RxBuffer[8]; }
我在OpenMv中发送如下数据
i = i+1
sending_data(500,255,i,4)
print("is sending:",500,255,i,4)
pyb.delay(1000)
在单片机中成功接收并处理
下面放一下usart.c和my_usart.c,my_usart.h的全部代码作为参考
uart.c
/** ****************************************************************************** * @file usart.c * @brief This file provides code for the configuration * of the USART instances. ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2021 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usart.h" #include "my_usart.h" /* USER CODE BEGIN 0 */ extern User_USART OpennMv_Data; /* USER CODE END 0 */ UART_HandleTypeDef huart3; DMA_HandleTypeDef hdma_usart3_rx; /* USART3 init function */ void MX_USART3_UART_Init(void) { /* USER CODE BEGIN USART3_Init 0 */ /* USER CODE END USART3_Init 0 */ /* USER CODE BEGIN USART3_Init 1 */ /* USER CODE END USART3_Init 1 */ huart3.Instance = USART3; huart3.Init.BaudRate = 115200; huart3.Init.WordLength = UART_WORDLENGTH_8B; huart3.Init.StopBits = UART_STOPBITS_1; huart3.Init.Parity = UART_PARITY_NONE; huart3.Init.Mode = UART_MODE_TX_RX; huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart3.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart3) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART3_Init 2 */ __HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE); //开启空闲中断 HAL_UART_Receive_DMA(&huart3,OpennMv_Data.RxBuffer,RXBUFFER_LEN); //开启DMA的接收 /* USER CODE END USART3_Init 2 */ } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance==USART3) { /* USER CODE BEGIN USART3_MspInit 0 */ /* USER CODE END USART3_MspInit 0 */ /* USART3 clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**USART3 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USART3 DMA Init */ /* USART3_RX Init */ hdma_usart3_rx.Instance = DMA1_Stream1; hdma_usart3_rx.Init.Channel = DMA_CHANNEL_4; hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart3_rx.Init.Mode = DMA_NORMAL; hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW; hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; if (HAL_DMA_Init(&hdma_usart3_rx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart3_rx); /* USART3 interrupt Init */ HAL_NVIC_SetPriority(USART3_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART3_IRQn); /* USER CODE BEGIN USART3_MspInit 1 */ /* USER CODE END USART3_MspInit 1 */ } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) { if(uartHandle->Instance==USART3) { /* USER CODE BEGIN USART3_MspDeInit 0 */ /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); /**USART3 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); /* USART3 DMA DeInit */ HAL_DMA_DeInit(uartHandle->hdmarx); /* USART3 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART3_IRQn); /* USER CODE BEGIN USART3_MspDeInit 1 */ /* USER CODE END USART3_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
my_usart.c
#include "my_usart.h" User_USART OpennMv_Data; //接收数据 //初始化函数 void User_USART_Init(User_USART *Data) { for(uint8_t i=0; i < RXBUFFER_LEN; i++) Data->RxBuffer[i] = 0; Data->frame_head[0] = 0x2C; Data->frame_head[1] = 0x12; Data->frame_tail = 0x5B; Data->Rx_flag = 0; Data->Rx_len = 0; Data->x = 0; Data->y = 0; Data->w = 0; Data->h = 0; } void OpenMvData_Process(uint8_t *RxBuffer) { //检查帧头帧尾 if(RxBuffer[0] != OpennMv_Data.frame_head[0]) return; if(RxBuffer[1] != OpennMv_Data.frame_head[1]) return; if(RxBuffer[10] != OpennMv_Data.frame_tail) return; OpennMv_Data.x = (RxBuffer[3]<<8)|RxBuffer[2]; OpennMv_Data.y = (RxBuffer[5]<<8)|RxBuffer[4]; OpennMv_Data.w = (RxBuffer[7]<<8)|RxBuffer[6]; OpennMv_Data.h = (RxBuffer[9]<<8)|RxBuffer[8]; }
my_usart.h
#ifndef _MY_USART_H #define _MY_USART_H #include "main.h" #define RXBUFFER_LEN 20 typedef struct User_USART { uint8_t Rx_flag; //接收完成标志 uint8_t Rx_len; //接收长度 uint8_t frame_head[2]; //帧头 uint8_t frame_tail; //帧尾 int x,y,w,h; uint8_t RxBuffer[RXBUFFER_LEN]; //数据存储 }User_USART; void OpenMvData_Process(uint8_t *RxBuffer); void User_USART_Init(User_USART *Data); #endif
在实际操作过程中,有时会出现一些小问题,如OpenMv处理数据给stm32发送时,会出现干扰信号,先检查两者有没有共地,再检查软件编写问题。
这里简单说一下为什么要用空闲中断的方法处理,在实际操作中,OpenMv发送的数据很快,而其中也会含有杂乱信息,通过空闲中断的方法,可以便于快速处理掉异常信息。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。