2023.1.2 作业

STM32M4核中断处理与串口通信实践
该文介绍了如何使用STM32CubeMX配置M4内核微控制器的GPIO中断,并通过重映射printf函数实现串口打印。在中断事件发生时,LED灯状态会取反,同时通过串口输出相应的信息。配置包括了UART4的初始化、GPIO引脚设置以及中断服务函数的编写。

1、以下实验,使用M4核开发
        PF7(key2) / PF8(key3) / PF9(key1) / PF5(火焰传感器) / PF12(人体红外传感器) / PE15(光电开关)检测中断
        要求1:当中断到来时,LED灯状态取反
        要求2:当中断触发时,打印一句话
        例如按键1触发,LED1状态取反,串口打印一句话:KEY1 DOWN#####

1.1>通过STM32CubeMX软件对各个引脚进行配置,配置好后生成 keil 工程。

1.2>直接通过 printf 函数的话,STM32 是不能够输出字符的,要在嵌入式中使用此函数的话,
需要通过重映射的方式,将 printf 函数重映射到 STM32 串口的寄存器上才可以。所以,要重定义 fputc 函数, printf 函数最终会通过调用 fputc 输出字符串到串口。在usart.c中进行重写:

/**
  ******************************************************************************
  * @file    usart.c
  * @brief   This file provides code for the configuration
  *          of the USART instances.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "usart.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

UART_HandleTypeDef huart4;

/* UART4 init function */
void MX_UART4_Init(void)
{

  /* USER CODE BEGIN UART4_Init 0 */

  /* USER CODE END UART4_Init 0 */

  /* USER CODE BEGIN UART4_Init 1 */

  /* USER CODE END UART4_Init 1 */
  huart4.Instance = UART4;
  huart4.Init.BaudRate = 115200;
  huart4.Init.WordLength = UART_WORDLENGTH_8B;
  huart4.Init.StopBits = UART_STOPBITS_1;
  huart4.Init.Parity = UART_PARITY_NONE;
  huart4.Init.Mode = UART_MODE_TX_RX;
  huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart4.Init.OverSampling = UART_OVERSAMPLING_16;
  huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart4) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN UART4_Init 2 */

  /* USER CODE END UART4_Init 2 */

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  if(uartHandle->Instance==UART4)
  {
  /* USER CODE BEGIN UART4_MspInit 0 */

  /* USER CODE END UART4_MspInit 0 */
  if(IS_ENGINEERING_BOOT_MODE())
  {
  /** Initializes the peripherals clock
  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_UART24;
    PeriphClkInit.Uart24ClockSelection = RCC_UART24CLKSOURCE_PCLK1;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

  }

    /* UART4 clock enable */
    __HAL_RCC_UART4_CLK_ENABLE();

    __HAL_RCC_GPIOG_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**UART4 GPIO Configuration
    PG11     ------> UART4_TX
    PB2     ------> UART4_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF6_UART4;
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN UART4_MspInit 1 */

  /* USER CODE END UART4_MspInit 1 */
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==UART4)
  {
  /* USER CODE BEGIN UART4_MspDeInit 0 */

  /* USER CODE END UART4_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_UART4_CLK_DISABLE();

    /**UART4 GPIO Configuration
    PG11     ------> UART4_TX
    PB2     ------> UART4_RX
    */
    HAL_GPIO_DeInit(GPIOG, GPIO_PIN_11);

    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_2);

  /* USER CODE BEGIN UART4_MspDeInit 1 */

  /* USER CODE END UART4_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
/*重写的fputc函数*/
int fputc(int ch,FILE *stream)
{
	//1、判断发送寄存器是否为空
	while(!(huart4.Instance->ISR & 0x40));
	//2、将要发送的数据,写到发送寄存器中
	huart4.Instance->TDR=ch;
	//3、判断是否为'\n',若是则再发送一个'\r'字符
	if(ch=='\n'){
		fputc('\r',stream);
	}
	return ch;
}
/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

 1.3>在gpio.c文件中重写中断触发处理函数

/**
  ******************************************************************************
  * @file    gpio.c
  * @brief   This file provides code for the configuration
  *          of all used GPIO pins.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "gpio.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/*----------------------------------------------------------------------------*/
/* Configure GPIO                                                             */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/** Configure pins
*/
void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_10|GPIO_PIN_8, GPIO_PIN_RESET);

  /*Configure GPIO pin : PE15 */
  GPIO_InitStruct.Pin = GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /*Configure GPIO pins : PF5 PF12 */
  GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /*Configure GPIO pin : PF10 */
  GPIO_InitStruct.Pin = GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /*Configure GPIO pins : PE10 PE8 */
  GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /*Configure GPIO pins : PF7 PF8 PF9 */
  GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI5_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(EXTI5_IRQn);

  HAL_NVIC_SetPriority(EXTI7_IRQn, 7, 0);
  HAL_NVIC_EnableIRQ(EXTI7_IRQn);

  HAL_NVIC_SetPriority(EXTI8_IRQn, 8, 0);
  HAL_NVIC_EnableIRQ(EXTI8_IRQn);

  HAL_NVIC_SetPriority(EXTI9_IRQn, 9, 0);
  HAL_NVIC_EnableIRQ(EXTI9_IRQn);

  HAL_NVIC_SetPriority(EXTI12_IRQn, 12, 0);
  HAL_NVIC_EnableIRQ(EXTI12_IRQn);

  HAL_NVIC_SetPriority(EXTI15_IRQn, 15, 0);
  HAL_NVIC_EnableIRQ(EXTI15_IRQn);

}

/* USER CODE BEGIN 2 */
/*上升沿触发中断处理函数*/
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
	switch(GPIO_Pin){
		/*光电开关触发中断,led1状态反转,串口打印相关信息*/
		case GPIO_PIN_15:
			HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_10);
			printf("光电开关被触发#####\n");
			break;
		/*人体红外传感器触发中断,led3状态反转,串口打印相关信息*/
		case GPIO_PIN_12:
			HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_8);
			printf("人体红外传感器被触发#####\n");
			break;
		/*火焰传感器触发中断,led2状态反转,串口打印相关信息*/
		case GPIO_PIN_5:
			HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
			printf("火焰传感器被触发#####\n");
			break;
	}
}

/*下降沿触发中断处理函数*/
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
	switch(GPIO_Pin){
		/*key1按键触发中断,led1状态反转,串口打印相关信息*/
		case GPIO_PIN_9:
			HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_10);
			printf("KEY1 DOWN#####\n");
			break;
		/*key3按键触发中断,led3状态反转,串口打印相关信息*/
		case GPIO_PIN_8:
			HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_8);
			printf("KEY3 DOWN#####\n");
			break;
		/*key2按键触发中断,led2状态反转,串口打印相关信息*/
		case GPIO_PIN_7:
			HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
			printf("KEY2 DOWN#####\n");
			break;
	}
}
/* USER CODE END 2 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

1.4>实现效果:

 

 

普通文本型问题,无需结构化输出。 你提到的“第六题”在当前对话中没有明确上下文,可能是某个作业或实验中的题目。结合你使用的 **IntelliJ IDEA 2023.3.4** 和之前一直在开发 Flink 流处理程序的背景,我推测你可能是在完成一个 **Flink 实时统计订单任务** 的系列题目,而“第六题”可能是其中要求实现某个具体功能的一题。 --- ### 🔍 基于常见教学场景的合理推断(依你看第六题怎么做) 假设你的“第六题”是类似: > **将每10秒统计的用户订单数结果写入 MySQL 数据库,并确保使用事件时间与水印机制。** 那么你应该做以下几步: --- ### ✅ 第六题推荐做法(Flink 写入 MySQL) #### 1. 添加 Maven 依赖(`pom.xml` 中加入) ```xml <!-- Flink JDBC Connector --> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-connector-jdbc_2.12</artifactId> <version>1.17.0</version> </dependency> <!-- MySQL Driver --> <dependency> <groupId>mysql</mysql-driver> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> ``` > ⚠️ 注意:版本要和你的 Flink 版本匹配(如你是 Flink 1.17,使用对应 connector) --- #### 2. 在代码中添加 JdbcSink 修改你原有的 `.print()` 为写入 MySQL: ```scala import org.apache.flink.connector.jdbc.JdbcSink import org.apache.flink.connector.jdbc.JdbcConnectionOptions // ... 其他代码不变 ... // 替换 .print() 为 addSink(JdbcSink) .addSink(JdbcSink.sink( "INSERT INTO user_order_count (user_id, order_count, window_start, window_end) VALUES (?, ?, ?, ?)", (element: UserOrderCount, statement: PreparedStatement) => { statement.setInt(1, element.userId) statement.setInt(2, element.orderCount) statement.setLong(3, element.windowStart) statement.setLong(4, element.windowEnd) }, new JdbcConnectionOptions.JdbcConnectionOptionsBuilder() .withUrl("jdbc:mysql://192.168.72.141:3306/demo?useSSL=false&serverTimezone=UTC") .withUsername("root") .withPassword("12345678") .withDriverName("com.mysql.cj.jdbc.Driver") .build )) ``` --- #### 3. 确保虚拟机 MySQL 已建表 登录虚拟机执行: ```sql CREATE DATABASE IF NOT EXISTS demo; USE demo; CREATE TABLE user_order_count ( user_id INT, order_count INT, window_start BIGINT, window_end BIGINT ); ``` --- #### 4. 在 IntelliJ IDEA 中运行 - 使用 `main` 方法直接运行。 - 确保网络通畅(主机能访问虚拟机 `192.168.72.141:3306`)。 - 检查防火墙、MySQL 远程权限是否开启。 --- ### 💡 常见问题排查(IDEA 2023.3.4) | 问题 | 解决方案 | |------|----------| | 报错 `ClassNotFoundException: com.mysql.cj.jdbc.Driver` | 确保 `mysql-connector-java` 在 `pom.xml` 中并已编译进项目 | | 连接超时 | 检查虚拟机 IP、MySQL 是否允许远程连接、端口 3306 是否开放 | | 任务提交但无数据写入 | 查看控制台日志,确认窗口是否触发(事件时间推进是否正常) | --- ### 📌 总结:依你看第六题怎么做? 如果你的第六题是“**将统计结果存入数据库**”,那么: ✅ 步骤总结: 1. 加依赖(JDBC + MySQL) 2. 改 Sink:`.addSink(JdbcSink...)` 3. 虚拟机建表 4. 配置网络与权限 5. IDEA 中运行主类 📌 提示:可以在 `.print()` 后再加 `.addSink(...)`,同时看到控制台输出和数据库写入,便于调试。 --- 如果你指的是其他“第六题”,请提供完整题目内容,我会为你精准解答!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值