STM32中断与DMA通信编程

一:STM32中断介绍

1.中断概念

中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。

2.中断过程

中断发生:当CPU在处理某一事件A时,发生了另一事件B,请求CPU迅速去处理。

中断处理:CPU暂停当前的工作,转去处理事件B。

中断返回:当CPU将事件B处理完毕后,再回到事件A中被暂停的地方继续处理事件。

3.中断优先级

STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。

高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。

抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。

抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。

如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行。

二:高低平控制LED灯

进入STM32CubeMX,新建项目

选择芯片

 

点击sys,将debug选项改为Serial Wire,在Rcc里的HSE选择Crystal/Ceramic Resonator

 

将PB0选为外部中断触发器,PA1是控制led灯

 

选择PLLCLK,将后面的晶振频率最大值改为72M赫兹

 

project里把toolchain那里改为MDK-ARM,版本选择最新的就行了,项目名和项目路径自己选择

 

生成文件

 

打开keil5,在main.c里写入下列代码即可,然后运行烧录得出结果

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
	GPIO_PinState b0_pin = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);  // 读取b0的状态
	b0_pin=1-b0_pin;
	switch (GPIO_Pin){//判断引脚
		case GPIO_PIN_0:
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1,1-b0_pin);  // 将a1写入与b0相同的电位
			break;
	}
	
}

 效果

 三:中断实现串口通信

还是用STM32CubeMX新建项目,过程同上一个相同

 

选择UASRT1,将mode改为异步通信,选择下面的NVIC Setting,将enabled选上

 

 

打开keil5,打开main.c文件,将以下代码写入头文件

// uint8_t aRxBuffer;//接收缓冲中断
uint8_t Uart1_RxBuff[256];//接收缓冲
uint8_t Uart1_Rx_Cnt=0;//接收缓冲计数
uint8_t cAlmStr[]="数据溢出(大于256)";

 然后将HAL_UART_RxCpltCallback函数重写,和上面的回调函数是一个道理

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if(Uart1_Rx_Cnt >= 255)  //溢出判断
	{
		Uart1_Rx_Cnt = 0;
		memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));
		HAL_UART_Transmit(&huart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);	
	}
	else
	{
		Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer;   //接收数据转存
	
		if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)||(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
		{
			HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1_RxBuff, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
			Uart1_Rx_Cnt = 0;
			memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff)); //清空数组
		}
	}
	
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断

}

 然后在主函数写一个接收中断函数

int main(void)
{
 //初始化
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
 
	
	
	//接收中断函数
	HAL_UART_Receive_IT(&huart1,(uint8_t*)&aRxBuffer,1);
	
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

结果:

四: DMA

1.DMA概念

DMA,全称Direct Memory Access,即直接存储器访问。

DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实现和完成的。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。

2.DMA传输数据四个要素

传输源 :DMA数据传输的来源

传输目标:DMA数据传输的目的

传输数量:DMA传输数据的数量

触发信号:启动一次DMA数据传输的动作

3.DMA的主要特征

每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发,这些功能通过软件来配置。

在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推)。

独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。

支持循环的缓冲器管理。

每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求。

存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输。

闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标。

可编程的数据传输数目:最大为65535(0xFFFF)。

4.传输方式

普通模式:传输结束后(即要传输数据的数量达到零),将不再产生DMA操作。若开始新的DMA传输,需在关闭DMA通道情况下,重新启动DMA传输。

循环模式:传输结束后(即要传输数据的数量达到零),将不再产生DMA操作。若开始新的DMA传输,需在关闭DMA通道情况下,重新启动DMA传输。

五:实现用DMA连续向上位机发送数据

一样使用STM32CubeMX,过程同上面一致

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

在USART1中,点击DMA Settings的Add,添加USART_RX 和USART_TX,传输速率设置为中速Medium,模式设置为Normal,右侧选择Memory;在最右侧的System view中选择DMA,点击Add,添加MEMTOMEM。

 

然后生成过程

打开keil5,编写main.c文件,在main.c文件中的while循环那块的代码如下

while (1)
  {
   uint8_t send_char[]="hello world\n";//发送的字符串
    HAL_UART_Transmit_DMA(&huart1,(uint8_t *)send_char,0xc);//DMA发送
		HAL_Delay(500);//延时
  }

 结果:

六:总结

通过这次STM32中断与DMA通信编程实验,我又了解了中断,DMA之类的知识,对于我们之后的学习有了更大的方便。

七:参考文献

(2条消息) 【STM32】HAL库 STM32CubeMX教程十一---DMA (串口DMA发送接收)_Z小旋-CSDN博客

 stm32hal库串口DMA收发 - Breezy-ye - 博客园 (cnblogs.com)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值