STM32中断与DMA通信编程

一、实验原理

中断全过程分为中断发生→中断处理→中断返回。

  1. 中断发生:当CPU在处理某一事件A时,发生了另一事件B,请求CPU迅速去处理。
  2. 中断处理:当CPU收到请求后,暂停当前的工作,装去处理事件B。
  3. 中断返回:当CPU将事件B处理完毕后,再回到事件A中去被暂停的地方继续处理事件A。

中断可以解决快速的CPU与慢速的外部设备之间传送数据的矛盾,可以分时为多个外部设备服务,提高计算机利用率;能够及时处理应用系统的随机事件,增强系统的实时性。

DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。四种情况的数据传输如下:

外设到内存
内存到外设
内存到内存
外设到外设

普通模式
传输结束后(即要传输数据的数量达到零),将不再产生DMA操作。若
开始新的DMA传输,需在关闭DMA通道情况下,重新启动DMA传输。
循环模式
可用于处理环形缓冲区和连续数据流(例如ADC扫描模式)。当激活循
环模式后,每轮传输结束时,要传输的数据数量将自动用设置的初始值
进行加载, 并继续响应DMA请求。

二、中断控制LED亮灭

1. 工程创建

CubeMX新建工程,选好芯片后,将PA1设置为output,PB1设置为GPIO_EXTI1

STM32中断与DMA通信编程

STM32中断与DMA通信编程

中断使能

STM32中断与DMA通信编程

将GPIO mode设置为下降沿

STM32中断与DMA通信编程

RCC设置如下

STM32中断与DMA通信编程

在Code Generator下勾选

STM32中断与DMA通信编程

然后生成代码即可,打开工程

2. 代码实现

思路:PB1接开关,PA1接LED灯,刚开始LED常亮,当按下开关时,LED灭,将PA1的状态翻转过来。

我们在stm32f1xx_hal_gpio.c中可以查看系统默认的回调函数

STM32中断与DMA通信编程

weak属性的函数表示:如果该函数没有在其他文件中定义,则使用该函数:如果用户在其他地方定义了该函数,则使用用户定义的函数。

我们在mian函数中重新编写回调函数

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin==GPIO_PIN_1)	//判断外部中断源
	{
		HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1)//翻转PA1状态
	}}

STM32中断与DMA通信编程

3. 实验效果

将程序烧录进芯片
STM32中断与DMA通信编程

三、串口通信(中断)

1. 工程创建

新建工程,选择芯片后在Connectivity下找到USART1,Mode选择Asynchronous,然后勾选下面的使能

STM32中断与DMA通信编程

Parameter Settings中设置通信参数,即波特率115200,8位数据位,无奇偶校验,1位停止位,使能接收和发送,16倍过采样。

STM32中断与DMA通信编程

其他设置相同

2. 程序编写

思路:①发送数据:在主函数中0.5s进行一次发送hello windows,使用HAL_UART_Transmit_IT函数将接受到的字符原样发回,发送成功产生回调;②接受数据:接收数据后产生回调HAL_UART_RxCpltCallback,接收成功一次就将数据上发一次,然后重新开始接受数据。
定义结构体

//定义测试串口中断函数收发的结构体类型
typedef struct{
	UART_HandleTypeDef	*huart1;
	uint8_t							rx_buf[20];//接收缓冲区
	uint32_t						tx_count;//发送成功次数技术标志位
	uint32_t						rx_flag;//接收完成标志位
}rxtx_it_usart_t;
//声明一个结构体并进行初始化
rxtx_it_usart_t	rxtx_it_usart={
	.huart1=&huart1,
	};

串口中断回调函数

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	if(rxtx_it_usart.huart1==huart)
	{
		rxtx_it_usart.tx_count++;
	}
}//发送回调
void  HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(rxtx_it_usart.huart1==huart)
	{
		rxtx_it_usart .rx_flag=1;
	}
}//接受回调

STM32中断与DMA通信编程

在主函数中添加以下代码

		if((HAL_GetTick()-start_count)>500)//0.5秒发送一次
		{
			start_count=HAL_GetTick();
			HAL_UART_Transmit_IT(rxtx_it_usart.huart1,send_data,sizeof(send_data)-1);
		}
		if(rxtx_it_usart.rx_flag==1)//接收成功一次就将数据上发一次
		{
				rxtx_it_usart.rx_flag=0;//清除标志位
			printf("%s\r\n",rxtx_it_usart.rx_buf);//回显接收到的数据
			HAL_UART_Receive_IT(rxtx_it_usart.huart1,rxtx_it_usart.rx_buf,20);//使能接收中断
  }

STM32中断与DMA通信编程

3. 实验效果

串口调试助手

STM32中断与DMA通信编程

四、DMA方式

1. 工程创建

在USART1下首先将Mode设置为Asynchronous,然后点击两次Add,将串口接收和发送的DMA数据流都添加进去。

STM32中断与DMA通信编程

DMA数据流的中断使能由CubeMX自动勾选,我们需要勾选使能串口1的中断,中断优先级使用默认值

STM32中断与DMA通信编程

添加MEMTOMEM

STM32中断与DMA通信编程

设置时钟

STM32中断与DMA通信编程
之后生成代码即可

2. 程序编写

打开工程文件,在main.c中添加以下代码

首先设置发送数据"hello world!"

uint8_t send_data[]=" hello world!\r\n";  //定义发送数据

然后

  HAL_UART_Transmit_DMA(&huart1, (uint8_t *)send_data, sizeof(send_data));

STM32中断与DMA通信编程

3. 实验效果

仿真结果

STM32中断与DMA通信编程

串口助手

STM32中断与DMA通信编程

五、总结

本次实验其实还不是很难,所以没有设计复杂的函数。通过对stm32中文手册和库函数手册的学习,或通过网络资源学习,都能很好的学会。DMA传输过程不占用CPU资源,可以边传输边运行其他任务,更加高效。

六、参考文献

STM32CubeMX之串口使用(中断方式)

上一篇:STM32重定向


下一篇:你听说过史莱姆吗??【oj】