因为这个bug,搞了一整天。串口1接收,使用DMA,如果配置为 NORMAL 模式,只能接收一次,后面数据不变。如果使用 CIRCLAR 模式,能够连续接收,但是不正确。
结合多方博客,终于解决问题,稳如老狗。
使用 CIRCLAR 模式,中断配置里解锁等操作,附上文件供参考,实现串口1 DMA收发传输。
#include "debug.h"
#define EX_DATA_LEN 32
struct XYZ_t des_pos_ = {0,0,0};
uint8_t get_cmd = 0;
uint8_t pos_vel_buf[EX_DATA_LEN] = {'\0'};
UART_HandleTypeDef usart1;
DMA_HandleTypeDef usart1_tx_dma;
DMA_HandleTypeDef usart1_rx_dma;
void DebugInit(uint32_t bound)
{
GPIO_InitTypeDef GPIO_Initure;
DEBUG_ENCLK();
GPIO_Initure.Pin = DEBUG_PIN;
GPIO_Initure.Mode = GPIO_MODE_AF_PP;
GPIO_Initure.Pull = GPIO_PULLUP;
GPIO_Initure.Speed = GPIO_SPEED_FAST;
GPIO_Initure.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(DEBUG_GPIO,&GPIO_Initure);
__HAL_RCC_DMA2_CLK_ENABLE();
__HAL_LINKDMA(&usart1,hdmatx,usart1_tx_dma);
usart1_tx_dma.Instance = DMA2_Stream7;
usart1_tx_dma.Init.Channel = DMA_CHANNEL_4;
usart1_tx_dma.Init.Direction = DMA_MEMORY_TO_PERIPH;
usart1_tx_dma.Init.PeriphInc = DMA_PINC_DISABLE;
usart1_tx_dma.Init.MemInc = DMA_MINC_ENABLE;
usart1_tx_dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
usart1_tx_dma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
usart1_tx_dma.Init.Mode = DMA_NORMAL;
usart1_tx_dma.Init.Priority = DMA_PRIORITY_MEDIUM;
usart1_tx_dma.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
usart1_tx_dma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
usart1_tx_dma.Init.MemBurst = DMA_MBURST_SINGLE;
usart1_tx_dma.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_DeInit(&usart1_tx_dma);
HAL_DMA_Init(&usart1_tx_dma);
usart1_rx_dma.Instance = DMA2_Stream2;
usart1_rx_dma.Init.Channel = DMA_CHANNEL_4;
usart1_rx_dma.Init.Direction = DMA_PERIPH_TO_MEMORY;
usart1_rx_dma.Init.PeriphInc = DMA_PINC_DISABLE;
usart1_rx_dma.Init.MemInc = DMA_MINC_ENABLE;
usart1_rx_dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
usart1_rx_dma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
usart1_rx_dma.Init.Mode = DMA_CIRCULAR;
usart1_rx_dma.Init.Priority = DMA_PRIORITY_LOW;
usart1_rx_dma.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_DeInit(&usart1_rx_dma);
HAL_DMA_Init(&usart1_rx_dma);
__HAL_LINKDMA(&usart1,hdmarx,usart1_rx_dma);
usart1.Instance = USART1;
usart1.Init.BaudRate = bound;
usart1.Init.WordLength = UART_WORDLENGTH_8B;
usart1.Init.StopBits = UART_STOPBITS_1;
usart1.Init.Parity = UART_PARITY_NONE;
usart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
usart1.Init.Mode = UART_MODE_TX_RX;
usart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&usart1);
HAL_NVIC_EnableIRQ(USART1_IRQn);
HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
printf("Usart1 init success\r\n");
}
void DMA2_Stream2_IRQHandler(void)
{
HAL_DMA_IRQHandler(&usart1_rx_dma);
}
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&usart1);
usart1.State = HAL_UART_STATE_READY;
usart1_rx_dma.State = HAL_DMA_STATE_READY;
__HAL_UNLOCK(&usart1_rx_dma);
if((__HAL_UART_GET_FLAG(&usart1,UART_FLAG_IDLE) != RESET))
{
__HAL_UART_CLEAR_IDLEFLAG(&usart1);
get_cmd = 1;
}
}
void PrintDataTask(void *arg)
{
printf("All the bugs will be killed\r\n");
DelayMs(20);
}
void GetDesirePosVelTask(void *arg)
{
uint16_t len;
memset(pos_vel_buf, '\0', EX_DATA_LEN);
__HAL_UART_ENABLE_IT(&usart1, UART_IT_IDLE);
HAL_UART_Receive_DMA(&usart1, (uint8_t*)pos_vel_buf, EX_DATA_LEN);
while (1)
{
if (get_cmd == 1)
{
get_cmd = 0;
des_pos_.x = (float)Str2Double(&pos_vel_buf[2], 3) * 0.1f;
des_pos_.y = (float)Str2Double(&pos_vel_buf[5], 3) * 0.1f;
des_pos_.z = (float)Str2Double(&pos_vel_buf[8], 3) * 0.1f;
printf("recv: %s, %.1f, %.1f, %.1f", pos_vel_buf, des_pos_.x, des_pos_.y, des_pos_.z);
memset(pos_vel_buf, '\0', EX_DATA_LEN);
DelayMs(10);
HAL_UART_Receive_DMA(&usart1, (uint8_t*)pos_vel_buf, EX_DATA_LEN);
}
else
{
DelayMs(10);
}
}
}
struct XYZ_t GetExDesirePosApi(void)
{
return des_pos_;
}
#if 1
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
FILE __stdout;
void _sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);
USART1->DR = (uint8_t) ch;
return ch;
}
#endif
|