[STM32CubeMX]学习笔记6:按键控制DMA串口发送

MCU:STM32F103ZET6

IDE:  MDK-ARM V5 +STM32CubeMX5.0.0

串口调试助手:SSCOM3.2

 

功能描述:通过KEY_UP按键控制DMA串口1数据的传送。

需要配置DMA,串口USART1,使能按键中断,LED提示灯。

 

一. 在 Pinout&Configuration---System Core中:

  • 1. 首先设置时钟RCC的HSE(外部高速时钟)为晶振模式:Crystal/ceramic Resonator

  • 2. 设置系统SYS的Debug为Serial Wire:

  • 3. 设置GPIO中的LED管脚。

在MCU管脚图中找到PC0和PC1管脚(查原理图对应的管脚号),将管脚设置为GPIO_Output输出模式,此时在System Core的GPIO中,会出现对应端口,点击端口将GPIO output level设置为low,将User Label定义为LED。

  • 4. 设置按键映射到外部中断线上。

选择PA0的端口为GPIO_EXTI0:

KEY_UP应为上升沿触发,并外接下拉电阻,点击端口将GPIO mode设置为External Interrupt Mode with Rising edge trigger detection,将GPIO Pull-up/Pull-down配置为Pull-down,将User Label定义为KEY_UP。

*TIPS:在将端口映射到EXTI线上后,SYS会出现以下警告:表示红色部分的模式不可使用,且因为PA0本身对应的是系统唤醒功能,因此System Wake-UP的功能也无法被选中。

接着在GPIO-Configuration中使能四个GPIO的中断(之前就是忘记了这个):

二. 在 Pinout&Configuration---Connectivity中:

  • 1. 打开USART1,并设置模式为异步收发模式Asynchronous:

  • 2. 设置USART1的参数,通用的“96-N-8-1”模式,即波特率9600,N校验位(无校验),数据位数为8,停止位为1位:

三. 在 Pinout&Configuration---System Core中:

1. 配置DMA参数:

经过第二步后,PA9和PA10被配置为了USART1_RX/USART1_TX:

按照图中数字顺序配置DMA,点击Add,添加USARTT1_TX, Channel会自动选择,Direction默认选择的是存储器到外设,Mode不使用循环,设置为Normal即可;外设地址无增量,存储器地址有增量;Data Width根据需要将存储器和外设的宽度都设置为字节。

四.在 Clock Configuration中:

配置时钟为72 Mhz。

五.在 Project Manager---Project中:

  • 1.设置项目的名称以及保存的位置,选择Toolchain/IDE为MDK-ARM V5,

Tips:最好把Linker Settings中的Minimum Heap Size设置为0x600。

  • 2.在Code Generator选项中如下勾选:

最后点Generate Code生成代码,并选择“Open Project”:

六.代码分析与改写:

配置思路:首先在一个数组中定义要发送的内容;让LED1不断闪烁,表示系统正在运行;编写中断回调函数,当按键按下时发送数据到外设(USART1)中,并改变LED2状态表示进入中断。

此处与笔记2的分析过程相同:

************************************************************************************************************************************************

在生成的stm32f1xx_it.c中是系统中断的相关函数,找到四个外部中断的中断服务函数:

void EXTI0_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI0_IRQn 0 */

  /* USER CODE END EXTI0_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
  /* USER CODE BEGIN EXTI0_IRQn 1 */

  /* USER CODE END EXTI0_IRQn 1 */
}

进入“HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0)”函数后发现定义如下:

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}

服务函数中第一步对中断口清零,随后进入回调函数“HAL_GPIO_EXTI_Callback”:

__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);
  /* 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. 定义发送的数组内容,在main.c中添加:
/* USER CODE BEGIN PV */
uint8_t serialMsg[] = "DMA has been successfully received! \r\n";
/* USER CODE END PV */
  • 2.在while(1)循环中添加LED1系统正常运行指示灯:
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	    HAL_GPIO_TogglePin(GPIOC,LED1_Pin);
	    HAL_Delay(200);
    /* USER CODE END WHILE */
  • 3.编写中断回调函数:
/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin==UP_Pin)
	{
		for(long i=1;i<72000;i++){};  //软件消抖
			if(HAL_GPIO_ReadPin(UP_GPIO_Port,UP_Pin)==1)  //按键是否按下
			{
				HAL_GPIO_TogglePin(GPIOC,LED2_Pin);
				HAL_UART_Transmit_DMA(&huart1, (uint8_t *)serialMsg, sizeof(serialMsg)); 
				HAL_Delay(1000);
			}
	}
}
/* USER CODE END 4 */

至此,编译后无错并下载到开发板中,就完成了通过STM32CubeMX调用HAL库实现按键控制DMA串口发送的效果程序。

实验现象:正常运行后,按下KEY_UP后DMA发送数组至串口:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章