STM32学习——DMA实验三、外设到内存搬运

该文介绍了如何使用STM32CubeMX配置DMA和串口中断,通过HAL库实现串口数据的DMA接收。在串口空闲中断IDLE触发后,计算并处理接收到的数据,然后重新启动DMA接收下一帧数据。过程中涉及的关键函数包括HAL_UART_Enable_IT、HAL_UART_Receive_DMA等。
摘要由CSDN通过智能技术生成

目录

实验要求

CubeMX配置

DMA配置:

 串口中断配置

用到的库函数

1. __HAL_UART_ENABLE_IT

2. HAL_UART_Receive_DMA

3. __HAL_UART_GET_FLAG

4. __HAL_UART_CLEAR_IDLEFLAG

5. HAL_UART_DMAStop

6. __HAL_DMA_GET_COUNTER

代码实现

main.c

main.h

stm32f1xx_it.c


实验要求

使用 DMA 的方式将串口接收缓存寄存器的值搬运到内存中,同时闪烁 LED1

CubeMX配置

DMA配置:

 串口中断配置


用到的库函数

1. __HAL_UART_ENABLE_IT

#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__)   ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) & UART_IT_MASK)): \
                                                           (((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 |= ((__INTERRUPT__) & UART_IT_MASK)): \
                                                           ((__HANDLE__)->Instance->CR3 |= ((__INTERRUPT__) & UART_IT_MASK)))
  • 参数一:HANDLE,串口句柄
  • 参数二:INTERRUPT,需要使能的中断
  • 返回值:无

2. HAL_UART_Receive_DMA

HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData,uint16_t Size)
  • 参数一:UART_HandleTypeDef *huart,串口句柄
  • 参数二:uint8_t *pData,接收缓存首地址
  • 参数三:uint16_t Size,接收缓存长度
  • 返回值:HAL_StatusTypeDefHAL状态(OKbusyERRORTIMEOUT

3. __HAL_UART_GET_FLAG

#define __HAL_UART_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR &(__FLAG__)) == (__FLAG__))
  • 参数一:HANDLE,串口句柄
  • 参数二:FLAG,需要查看的FLAG
  • 返回值:FLAG的值

4. __HAL_UART_CLEAR_IDLEFLAG

#define __HAL_UART_CLEAR_IDLEFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__)
  • 参数一:HANDLE,串口句柄
  • 返回值:无

5. HAL_UART_DMAStop

HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)
  • 参数一:UART_HandleTypeDef *huart,串口句柄
  • 返回值:HAL_StatusTypeDefHAL状态(OKbusyERRORTIMEOUT

6. __HAL_DMA_GET_COUNTER

#define __HAL_DMA_GET_COUNTER(__HANDLE__) ((__HANDLE__)->Instance->CNDTR)
  • 参数一:HANDLE,串口句柄
  • 返回值:未传输数据大小

    代码实现

如何判断串口接收是否完成?如何知道串口收到数据的长度?
使用 串口空闲中断 IDLE )!
  • 串口空闲时,触发空闲中断;
  • 空闲中断标志位由硬件置1,软件清零
利用串口空闲中断,可以用如下流程实现 DMA 控制的任意长数据接收:
  1. 使能IDLE空闲中断;
  2. 使能DMA接收中断;
  3. 收到串口接收中断,DMA不断传输数据到缓冲区;
  4. 一帧数据接收完毕,串口暂时空闲,触发串口空闲中断;
  5. 在中断服务函数中,清除中断标志位,关闭DMA传输(防止干扰);
  6. 计算刚才收到了多少个字节的数据。
  7. 处理缓冲区数据,开启DMA传输,开始下一帧接收。

main.c

uint8_t rcvBUF[BUF_SIZE] = {0};// 接收数据缓存数组
uint8_t rcvlen = 0;// 接收一帧数据的长度

mian函数里

__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);// 使能IDLE空闲中断
HAL_UART_Receive_DMA(&huart1,rcvBUF,BUF_SIZE);// 使能DMA接收中断

while (1)
{
	HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
	HAL_Delay(1000);
}

main.h

#define BUF_SIZE 100

stm32f1xx_it.c

extern uint8_t rcvBUF[BUF_SIZE];// 接收数据缓存数组
extern uint8_t rcvlen;// 接收一帧数据的长度

void USART1_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart1);
	if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) == SET)	 判断IDLE标志位是否被置位
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);// 清除标志位
		HAL_UART_DMAStop(&huart1);// 停止DMA传输,防止干扰
		uint8_t tmp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
		rcvlen =  BUF_SIZE - tmp;//计算数据长度
		HAL_UART_Transmit_DMA(&huart1,rcvBUF,rcvlen); //发送数据
		HAL_UART_Receive_DMA(&huart1,rcvBUF,BUF_SIZE);//再次开启DMA,接收下一帧数据
	}
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值