STM32中断与DMA通信编程

一、STM32中断使用

NVIC 中断优先级管理
Nested Vectored Interrupt Controller,嵌套向量中断控制器。

CM3支持256个中断,16个内核中断,240个外部中断,256级可编程中断设置。

STM32使用了其中一部分,16个内核中断,107系列有68个可屏蔽中断(103系列只有60个),16级可编程的中断优先级。


中断寄存器
ISER[8],Interrupt Set-Enable Registers,中断使能寄存器组,用8个32位寄存器控制(256个可编程中断),每个位控制一个中断。由于STM32f103只有60个可屏蔽中断,于是只用了 ISER[0] 和 ISER[1] 64个中断中的前60位。

ISER[0] 的 bit0 至 bit31 对应中断0至31,ISER[1] 的 bit0 至 bit27 对应中断32至59,使能某个中断就将对应的 ISER 置1

ICER[8],Interrupt Clear-Enable Register,中断除能寄存器组。中断对应与ISER相同,但作用是置1清除中断使能

ISPR[8],Interrupt Set-Pending Register,中断挂起控制寄存器组。置1将正在进行的中断挂起,暂停等待执行,执行同级或更高级别的中断

ICPR[8],Interrupt Clear-Pending Register,中断解挂控制寄存器组,置1将挂起的中断解挂

IABR[8],Interrupt Active Bit Register,中断激活标志位寄存器组,只读寄存器,为1表示该位对应的中断正在被执行

IP[240],Interrupt Priority Registers,中断优先级控制寄存器组,相当重要! STM32的中断分组与其密切相关。

IP[240]有240个8bit寄存器组成,每个可屏蔽中断占用8bit,总共可表示240个可屏蔽中断,STM32f1使用其中60个,IP[59]至IP[0]分别对应中断59至0。每个可屏蔽中断只用高4位,分为抢占优先级和响应优先级,抢占优先级在前、响应优先级在后,各占几位由SCB->AIRCR中的中断分组设置。采用库函数==NVIC_PriorityGroupConfig () ==配置。


如果组设置为3,则每个中断的中断优先寄存器高4位中前3位是抢占优先级,优先级级别0-7;低1位是响应优先级,优先级级别0-1。

 

STM32的中断向量有抢占属性和响应属性,属性编号越小,优先级别越高。

抢占属性是打断其他中断的属性,有这个属性就有嵌套中断。由库函数NVIC_IRQChannelPreemptionPriority() 进行参数配置。

响应属性应用在抢占属性相同时(前提),两个中断向量的抢占优先级相同时,如果同时到达,则优先处理响应优先级高的中断。由库函数NVIC_IRQChannelSubPriority() 进行参数配置。
 

先建立新工程,选择自己的芯片,然后点击start project

修改RCC的设置,将High Speed Clock选择为“Crystal......”

修改SYS,将Debug选择“Serial Wire”

点击GPIO,选择管脚,这里我选择PB5为我的led管脚并设置为GPIO_Output,再将PA1设置为 GPIO_EXTI1.

设置PA1如图

 

设置PB5如图

 

点击NVIC并进行如下修改

 

修改时钟,修改如图所示

 

 接下来生成工程和代码就行了

 

在keil5里面打开刚刚建立好的工程,并修改main函数

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Callback could be implemented in the user file
   */
}

 最终结果

 

 二、串口中断实现串口通信

1.创建工程,选择芯片;

2.修改RCC

3.设置USART1,点击Mode,选择Asynchronous设置中断,在NVIC Settings中点击Enabled

 

修改时钟

创建,生成代码

 打开工程,修改代码

stm32f1xx_hal.c文件添加头文件

#include <stdio.h>
extern UART_HandleTypeDef huart1;   //声明串口

 

重新改写fget和fput函数

/**
  * 函数功能: 重定向c库函数printf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
/**
  * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

 

 在修改main函数

printf("hello windows!\r\n");
HAL_Delay(1000);

 

 添加定义,接收串口数据

#include "stdio.h"
#include <string.h>
 
#define RXBUFFERSIZE  256     //最大接收字节数
char RxBuffer[RXBUFFERSIZE];   //接收数据
uint8_t aRxBuffer;			//接收中断缓冲
uint8_t Uart1_Rx_Cnt = 0;		//接收缓冲计数

 

在主函数main.c文件中添加开启接收中断的语句

HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);

 添加中断回调函数

/* USER CODE BEGIN 4 */
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback could be implemented in the user file
   */
 
	if(Uart1_Rx_Cnt >= 255)  //溢出判断
	{
		Uart1_Rx_Cnt = 0;
		memset(RxBuffer,0x00,sizeof(RxBuffer));
		HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10,0xFFFF); 	
        
	}
	else
	{
		RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer;   //接收数据转存
	
		if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
		{
			HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
            while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
			Uart1_Rx_Cnt = 0;
			memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组
		}
	}
	
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断
}
/* USER CODE END 4 */

 

烧录仿真 

 

三、STM32采用串口DMA方式发送数据

建立工程,选择芯片

修改SYS,在Debug中选择Serial....

在RCC中把High  Speed Clock设置为Crystal/Ceramic

在Connectivity中选择YUSART1,勾选如下

在点击DMA Setting中的Add,添加如下

修改时钟如下:

生成代码:

打开工程在main函数里添加代码

uint8_t Senbuff[] = "Hello windows!\n";  //定义一个数组,将想要发送的数据放到数组中去

同时在main函数的里在添加代码

HAL_UART_Transmit_DMA(&huart1,Senbuff, sizeof(Senbuff));
HAL_Delay(1000);

添加成功之后编译,生成hex文件。如下图,编译没有出差。

烧录仿真

完成。 

四、资料链接

https://blog.csdn.net/xwj2633673783/article/details/112749476

https://blog.csdn.net/as480133937/article/details/104827639/

https://www.cnblogs.com/breezy-ye/articles/12157442.html

五、总结

本次实验内容较多,但是相对来说还是比较简单的,通过参考学习各位大佬的博客和积极查阅资料解决了我很多问题(当然还有百度yyds)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值