你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

STM32中断与DMA通信编程实践

2021-11-5 14:07:28

文章目录

    • 1、STM32CubeMX点亮LED灯
        • 1.1、建立工程项目
        • 1.2、完善代码并运行程序
    • 2、中断串口通信
    • 3、STM32CubeMX方式发送数据



 

1、STM32CubeMX点亮LED灯

1.1、建立工程项目

    首先使用STM32CubeMX软件新建一个工程,可参考HAL库点亮LED灯

    但是有些设置需要注意:
1:时钟配置:选择外部时钟HSE 8MHz、PLL锁相环倍频9倍(8*9=72)、系统时钟来源选择为PLL、设置APB1分频器为 /2
在这里插入图片描述

2:引脚设置:将PA4作为led管脚, 将端口设置为GPIO_Output输出模式、使用PA5作为开关管脚(使用用杜邦线模拟开关),将端口设置位GPIO_EXTI5. 中断模式
在这里插入图片描述

3:设置NVIC即中断控制:设置NVIC(嵌套向量中断控制器)、勾选 EXTI line(9:5) interrupts、
Preemption Priority:抢占优先级
Sub Priority:响应优先级
在这里插入图片描述

1.2、完善代码并运行程序

    然后使用keil打开STM32CubeMX软件生成的代码并完善,在main函数后面添加如下代码

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if( GPIO_Pin == B1_EXTI_Pin)  //判断中断源
	{
		HAL_GPIO_TogglePin(GPIOA, A1_led_Pin);  //翻转led管脚 A1口的电平
	}
}

    编译运行
在这里插入图片描述
视频生成的gif动图

2、中断串口通信

    借用部分代码借用,需要进行修改

    进行串口USART和引脚A9和A10的宏定义

/*串口-USART */
#define  DEBUG_USARTx                   USART1  //定义串口一
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200  //设置波特率为 115200

/*USART GPIO 引脚宏定义*/
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10

#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler

    配置串口中断函数

// 串口中断服务函数
void DEBUG_USART_IRQHandler(void)
{
  uint8_t ucTemp;
	//串口一接收中断
	if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
	{
		//获取接收到的数据
		ucTemp = USART_ReceiveData(DEBUG_USARTx);
		//如果接收标志为 0 ,则执行下面的部分
		if((USART_RX_FLAG & 0x8000) == 0)
		{
			//接收到了0x0d
			if(USART_RX_FLAG & 0x4000)
			{
				//接收错误,重新开始
				if(ucTemp != 0x0a)
					USART_RX_FLAG=0;
				//接收完成
				else
					USART_RX_FLAG |= 0x8000;
			}
			//还未接收到0x0d
			else
			{
				//接收到回车
				if(ucTemp == 0x0d)
				{
					USART_RX_FLAG |= 0x4000;
				}
				else
				{
					USART_RX_BUF[USART_RX_FLAG & 0x3FFF] = ucTemp;
					USART_RX_FLAG++;
					//接收数据错误,重新开始接收
					if(USART_RX_FLAG > 99)
						USART_RX_FLAG = 0;
				}
			}
		}
	}	 
}

    写入延时函数

//毫秒级的延时函数
void delay_ms(uint16_t delay_ms)
{    
  volatile unsigned int num;
  for (num = 0; num < delay_ms; num++)
  {
    delay_us(1000);
  }
}

    使用函数发送数据

//连续发送数据
void Usart_SendString(void)
{
	uint8_t i = 0;
	
	while(1)
	{
		if(USART_RX_FLAG & 0x8000)
		{
			// 获取接收到的数据长度
			len = USART_RX_FLAG & 0x3FFF;
			Usart_SendStr(DEBUG_USARTx, "\n");
			for(i=0; i<len;i++)
			{
				// 向串口发送数据
				USART_SendData(DEBUG_USARTx, USART_RX_BUF[i]);
				//等待发送结束
				while(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TC)!=SET);
			}
			Usart_SendStr(DEBUG_USARTx, "\n\n");
			//比较字符串
			if(strcmp((char *)USART_RX_BUF,"stop,stm32!")==0)
			{
				Usart_SendStr(DEBUG_USARTx, "stm32已停止发送!");
				break;//退出循环
			}
			//初始化
			USART_RX_FLAG=0;
			memset(USART_RX_BUF,0,sizeof(USART_RX_BUF));
		}
		else
		{
			//循环发送数据
			Usart_SendStr(DEBUG_USARTx, "Hello world!\n");
			delay_ms(800);
		}
	}
}

    最后在主函数里面调用函数发送数据

int main(void)
{	
	USART_Config();
	
	Usart_SendString();  //调用连续发送数据函数
	return 0;
}

    编译运行
在这里插入图片描述

3、STM32CubeMX方式发送数据

    设置串口,并将RCC设置外部高速时钟HSE 选择外部时钟源
在这里插入图片描述

    设置NVIC Settings使能中断
在这里插入图片描述

    设置DMA
在这里插入图片描述

在这里插入图片描述

    时钟配置
在这里插入图片描述

    最后生成代码
在这里插入图片描述

    在main.c中添加代码:

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

    在while循环中添加代码:

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff)-1);  //串口发送Senbuff数组
	    HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}

运行结果
在这里插入图片描述

参考:https://blog.csdn.net/junseven164/article/details/121071585?spm=1001.2014.3001.5501