STM32中断和DMA通信实践记录
一、DMA的基本介绍
DMA,全称Direct Memory Access,即直接存储器访问。
DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU,
CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,是不是能够更好的利用CPU的资源呢?
因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理,
DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作–计算、控制等。
二、通过cubemx实现DMA中断通信
1、配置管脚
芯片为stm32f103c8tx,需要使用的管脚有pa9(usart1_tx),pa10(usart1_rx),以及一个控制led灯亮灭的管脚(通过DMA中断),我选择的是pa5。
2.配置usart
usart1配置如下:
波特率为115200,8位数据位,1位停止位,无校验位。
3.DMA及其他配置
在DMA Setting中,点击add,即可自动添加可以启用的DMA通道,然后启用nvic,rcc设置为使用外部时钟,时钟配置根据自己使用的芯片参数进行配置。设置好项目位置和名称,生成代码然后打开项目。
4.相关用户代码配置。
在main函数之前创建全局变量Senbuff数组,存放接收的数据,定义count和flag,保存串口接收数据状态,在while循环之前加以下代码
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能串口空闲中断
HAL_UART_Receive_DMA(&huart1, Senbuff,len);
//开启DMA接收,不加此自启后接收一次空字符
之后,自定义中断处理函数。函数如下
void MX_RXCallBack(UART_HandleTypeDef *huart)
{
uint8_t tmp_flag,temp;
tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE);
if((tmp_flag != RESET))
{
__HAL_UART_CLEAR_FLAG(&huart1,tmp_flag);
HAL_UART_DMAStop(&huart1);
temp=__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
HAL_UART_Receive_DMA(&huart1,Senbuff,len);
count= len - temp;
}
flag = 1;
//led灯闪烁一次
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);
}
while循环中函数代码如下:
while(1)
{
if(flag){
HAL_UART_Transmit_DMA(&huart1,Senbuff,len);
HAL_Delay(100);
//重置数据接收区
flag=0;
memset(Senbuff,0,count);
}
}
测试与预期一致。