嵌入式技术论坛
直播中

糖栗子

9年用户 667经验值
擅长:MEMS/传感技术
私信 关注
[问答]

stm32f103ze nano3.15使用串口DMA接收配置时报错的原因?

使用stm32f103ze,移植完成nano的3.1.5版本。在增加uart2的dma接收配置时,出现问题,代码图下

#include "drive_uart.h"
#define LEN_UART2_RECV_BUFF 100
UART_HandleTypeDef UART2_Handler; //UART2句柄
DMA_HandleTypeDef UART2RxDMA_Handler;
unsigned char g_uart2_buff[LEN_UART2_RECV_BUFF]={0};
unsigned char hdma_usart2_rx=0;
void uart2_init_console(u32 bound)
{
//UART 初始化设置
UART2_Handler.Instance=USART2; //USART2
UART2_Handler.Init.BaudRate=bound; //波特率
UART2_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为8位数据格式
UART2_Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位
UART2_Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位
UART2_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控
UART2_Handler.Init.Mode=UART_MODE_TX_RX;
HAL_UART_Init(&UART2_Handler);
}
void dma_usart2_rx_config()
{
__HAL_RCC_DMA1_CLK_ENABLE();
UART2RxDMA_Handler.Instance = DMA1_Channel6;
UART2RxDMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY; //外设到内存
UART2RxDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
UART2RxDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;
UART2RxDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
UART2RxDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
UART2RxDMA_Handler.Init.Mode = DMA_CIRCULAR;
UART2RxDMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;
HAL_DMA_DeInit(&UART2RxDMA_Handler);
HAL_DMA_Init(&UART2RxDMA_Handler);
__HAL_LINKDMA(&UART2_Handler, hdmatx, UART2RxDMA_Handler);
HAL_UART_Receive_DMA(&UART2_Handler, g_uart2_buff, LEN_UART2_RECV_BUFF);
}
unsigned char buffer_data_num_index()
{
return (LEN_UART2_RECV_BUFF - __HAL_DMA_GET_COUNTER(&UART2RxDMA_Handler));
}
void dma_usart2_init()
{
uart2_init_console(115200);
dma_usart2_rx_config();
}
其中 dma_usart2_init 在 main 函数中调用。当在 dma_usart2_rx_config 函数中增加 HAL_UART_Receive_DMA 时,程序启动时会报错,信息如下

\ | /

  • RT - Thread Operating System
    / | \ 3.1.5 build Aug 13 2023
    2006 - 2020 Copyright by rt-thread team
    psr: 0x01000000
    r00: 0x08001f5f
    r01: 0x00000000
    r02: 0x00000064
    r03: 0x00001000
    r04: 0x20000208
    r05: 0x00000064
    r06: 0xdeadbeef
    r07: 0xdeadb
    \ | /
  • RT - Thread Operating System
    / | \ 3.1.5 build Aug 13 2023
    2006 - 2020 Copyright by rt-thread team
    psr: 0x01000000
    r00: 0x08001f5f
    r01: 0x00000000
    r02: 0x00000064
    r03: 0x00001000
    r04: 0x20000208
    r05: 0x00000064
    r06: 0xdeadbeef
    r07: 0xdeadbeef
    r08: 0xdeadbeef
    r09: 0xdeadbeef
    r10: 0xdeadbeef
    r11: 0xdeadbeef
    r12: 0x00000008
    lr: 0x0800279f
    pc: 0x08001942
    hard fault on thread: main
    thread pri status sp stack size max used left tick error

tshell 21 ready 0x00000040 0x00000400 06% 0x0000000a 000
tidle 31 ready 0x00000044 0x00000100 26% 0x00000020 000
main 10 ready 0x00000044 0x00000400 23% 0x00000013 000
bus fault:
SCB_CFSR_BFSR:0x04 IMPRECISERR

回帖(1)

敷衍作笑谈

2023-10-11 11:27:34
.UART_HardwareFlowControl = UART_HWCONTROL_NONE,          //无硬件数据流控制
.UART_Mode = UART_MODE_TX_RX,                           //收发模式
.UART_Parity = UART_PARITY_NONE,                       //无校验位
.UART_StopBits = UART_STOPBITS_1,                      //一停止位
.UART_WordLength = UART_WORDLENGTH_8B,                  //数据位为8位
.UART_BaudRate = bound                                    //波特率
};

if(HAL_UART_Init(&UART2_Handler) != HAL_OK){
error_handler();  //初始化失败,死循环
}

//使能 UART 接收 DMA 方式
__HAL_RCC_DMA1_CLK_ENABLE();       //使能 DMA1 时钟
HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 3, 3);     //DMA 通道6中断通道设置
HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);            //DMA 通道6中断使能

UART2RxDMA_Handler.Instance = DMA1_Channel6;                     //DMA通道选择
UART2RxDMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;          //外设到内存
UART2RxDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;              //外设不增量
UART2RxDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;                //内存增量
UART2RxDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;   //外设数据宽度为8位
UART2RxDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;      //内存数据宽度为8位
UART2RxDMA_Handler.Init.Mode = DMA_NORMAL;                          //普通模式
UART2RxDMA_Handler.Init.Priority = DMA_PRIORITY_LOW;                //优先级为低
HAL_DMA_Init(&UART2RxDMA_Handler);                                  //初始化 DMA 外设

__HAL_LINKDMA(&UART2_Handler,hdmarx,UART2RxDMA_Handler);      //连接 UART2 的 DMA

HAL_UART_Receive_DMA(&UART2_Handler,g_uart2_buff,LEN_UART2_RECV_BUFF);   //启动 DMA 传输

}

这里需要注意的是,如果使用 DMA 收发,需要在 stm32f1xx_it.c 中添加 DMA 传输完成中断的处理函数 DMA1_Channel6_IRQHandler()。

初始写法是没有优先级等级的,可以无脑设置成最高的,但之后代码升级优化就会出现问题。这里直接复制下在 H7 和 F4 上正常的写法:

#define DMA_UART_RX_STREAM         DMA2_Stream2
#define DMA_UART_RX_CHANNEL        DMA_CHANNEL_4
#define DMA_UART_RX_IRQn           DMA2_Stream2_IRQn
#define DMA_UART_RX_IRQ_HANDLER     DMA2_Stream2_IRQHandler

#define DMA_UART_TX_STREAM         DMA2_Stream7
#define DMA_UART_TX_CHANNEL        DMA_CHANNEL_4
#define DMA_UART_TX_IRQn           DMA2_Stream7_IRQn
#define DMA_UART_TX_IRQ_HANDLER     DMA2_Stream7_IRQHandler

DMA_HandleTypeDef hdma_uart_rx;
DMA_HandleTypeDef hdma_uart_tx;

void MX_DMA_Init(void)
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();
  
  /* DMA interrupt init */
  /* DMA2_Stream2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA_UART_RX_IRQn, 3, 0);
  HAL_NVIC_EnableIRQ(DMA_UART_RX_IRQn);
  /* DMA2_Stream7_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA_UART_TX_IRQn, 3, 0);
  HAL_NVIC_EnableIRQ(DMA_UART_TX_IRQn);
  
}

void MX_USART2_UART_Init(uint32_t baud_rate)
{

  /* USART2 parameter configuration */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = baud_rate;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }

  /* Configure DMA channels */
  hdma_uart_rx.Instance = DMA_UART_RX_STREAM;
  hdma_uart_rx.Init.Channel = DMA_UART_RX_CHANNEL;
  hdma_uart_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
  hdma_uart_rx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_uart_rx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_uart_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_uart_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_uart_rx.Init.Mode = DMA_CIRCULAR;
  hdma_uart_rx.Init.Priority = DMA_PRIORITY_LOW;
  if (HAL_DMA_Init(&hdma_uart_rx) != HAL_OK)
  {
    Error_Handler();
  }

  __HAL_LINKDMA(&huart2, hdmarx, hdma_uart_rx);

  hdma_uart_tx.Instance = DMA_UART_TX_STREAM;
  hdma_uart_tx.Init.Channel = DMA_UART_TX_CHANNEL;
  hdma_uart_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
  hdma_uart_tx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_uart_tx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_uart_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_uart_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_uart_tx.Init.Mode = DMA_NORMAL;
  hdma_uart_tx.Init.Priority = DMA_PRIORITY_LOW;
  if (HAL_DMA_Init(&hdma_uart_tx) != HAL_OK)
  {
    Error_Handler();
  }

  __HAL_LINKDMA(&huart2, hdmatx, hdma_uart_tx);

}
以上就是 stm32f103ze nano3.1.5 版本串口 DMA 接收配置的详细配置方法和解决报错问题的相关材料。如果在移植的过程中仍有疑问或其他问题,可以参考以上内容进行解决。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分