ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

STM32中断与DMA通信编程

2021-11-06 23:30:52  阅读:195  来源: 互联网

标签:DMA HAL rxtx usart 中断 编程 STM32 UART


一、实验原理

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

  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

在这里插入图片描述

在这里插入图片描述

中断使能

在这里插入图片描述

将GPIO mode设置为下降沿

在这里插入图片描述

RCC设置如下

在这里插入图片描述

在Code Generator下勾选

在这里插入图片描述

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

2. 代码实现

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

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

在这里插入图片描述

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状态
	}}

在这里插入图片描述

3. 实验效果

将程序烧录进芯片
在这里插入图片描述

三、串口通信(中断)

1. 工程创建

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

在这里插入图片描述

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

在这里插入图片描述

其他设置相同

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;
	}
}//接受回调

在这里插入图片描述

在主函数中添加以下代码

		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);//使能接收中断
  }

在这里插入图片描述

3. 实验效果

串口调试助手

在这里插入图片描述

四、DMA方式

1. 工程创建

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

在这里插入图片描述

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

在这里插入图片描述

添加MEMTOMEM

在这里插入图片描述

设置时钟

在这里插入图片描述
之后生成代码即可

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));

在这里插入图片描述

3. 实验效果

仿真结果

在这里插入图片描述

串口助手

在这里插入图片描述

五、总结

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

六、参考文献

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

标签:DMA,HAL,rxtx,usart,中断,编程,STM32,UART
来源: https://blog.csdn.net/weixin_57770487/article/details/121186175

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有