STM32的使用方法一

2024-09-08 07:20
文章标签 使用 方法 stm32

本文主要是介绍STM32的使用方法一,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • 注:我采用的是STM32F103RC芯片、相应的电路图和STM32CubeIDE软件
  • 这是在STM32CubeIDE软件定义芯片后,所给的必要的代码逻辑,加上了注释
#include "main.h"/* Private variables ---------------------------------------------------------*//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);  // 声明系统时钟配置函数##关键词解释
句柄 :对硬件资源或系统资源的抽象,通常用于标识和管理这些资源。通常是一个包含配置参数、状态信息和相关寄存器地址的结构体。定义句柄后,可以通过该句柄对相应的硬件外设进行配置、操作和管理。/*** @brief  The application entry point.* @retval int*/
int main(void)
{// 初始化HAL库,配置系统时钟和外设HAL_Init();HAL 库提供了一套统一的 API 来抽象硬件外设(如GPIO、ADC、UART、I2C、SPI等)的操作。// 配置系统时钟SystemClock_Config();
MX_ 前缀通常表示由 STM32CubeMX 工具生成的初始化代码,而不是开发者手动编写的函数。// 在这里可以初始化其他外设// 无限循环,主程序运行的核心循环while (1){// 这里可以放置主循环代码}
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};          // RCC振荡器初始化结构体RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};          // RCC时钟初始化结构体// 配置HSI(内部高速时钟)作为时钟源RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;             // 打开HSIRCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;  // 设置HSI校准值RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;       // 不使用PLL(相位锁定环)if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();  // 如果配置失败,调用错误处理函数}// 配置AHB、APB1、APB2总线时钟RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;  // 使用HSI作为系统时钟源RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;       // AHB时钟不分频RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;        // APB1时钟不分频RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;        // APB2时钟不分频if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK){Error_Handler();  // 如果配置失败,调用错误处理函数}
}/*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{__disable_irq();  // 禁用所有中断while (1){// 错误处理:进入死循环}
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{// 用户可以在这里添加自己的实现来报告文件名和行号
}
#endif /* USE_FULL_ASSERT */

一、GPIO

  1. 在STM32中,GPIO(General Purpose Input/Output,通用输入/输出)是一个非常重要的外设,用于与外部设备进行交互。
  2. GPIO引脚可以通过软件配置为输入或输出,用于读取或控制外部设备的状态,如开关、LED、传感器等。
  3. GPIO模块将管脚分组为PA PB PC PD,每一组为16个。
  4. 使用
    - 由于我的电路图是PC6,PC7,PC8为LED灯连接。故配置它们为GPIO_Output,因此在代码中多了static void MX_GPIO_Init(void);函数,进行串口的配置,故也要在main函数中GPIO初始化。 MX_GPIO_Init();
    - 又因为PC2控制着LED的亮灭,故将PC2设置为GPIO_Intput,并将其上拉。
    - 为什么上拉:芯片的管脚浮在空中,电平是不确定的.为了使之稳定,我们可以需要对其进行 上拉和下拉。
    在这里插入图片描述
    - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8, GPIO_PIN_SET);用于将6,7,8管脚设置为输出状态。GPIO_PIN_RESET 可以将指定的 GPIO 引脚输出设为逻辑低电平(0V),通常表示逻辑0。
    - HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8); 对输入输出取反操作,即设置一定的延时可以一闪一闪的。
    - 利用PC2开关LED灯
 if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_2) == GPIO_PIN_RESET) {HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8, GPIO_PIN_SET);} else {HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8, GPIO_PIN_RESET);}
  1. 输出的推挽和开漏
    推挽 push pull 可以输出高低电平 有一定的驱动能力
    开漏 open drain 只能输出低,必须上拉电阻 没有驱动能力
    在这里插入图片描述
  2. 代码
#include "main.h"void SystemClock_Config(void);
static void MX_GPIO_Init(void);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();while (1){if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_2) == GPIO_PIN_RESET) {HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8, GPIO_PIN_SET);} else {HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8, GPIO_PIN_RESET);}}
}void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK){Error_Handler();}
}static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOC_CLK_ENABLE();HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8, GPIO_PIN_RESET);GPIO_InitStruct.Pin = GPIO_PIN_2;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|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(GPIOC, &GPIO_InitStruct);
}void Error_Handler(void)
{__disable_irq();while (1){}
}#ifdef  USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */

二、中断

  1. 中断(Interrupt)是一种非常重要的机制,用于处理外部或内部事件,而无需频繁地查询(轮询)硬件状态。
  2. 中断能够在事件发生时立即响应,并将处理器从主程序转移到中断服务程序(ISR),以处理特定的任务。
  3. 使用方法
    1). 设置管脚为GPIO_EXTI
    2). 在NVIC Interrupt Table表中允许对应的中断管脚使能
    3). 设置对应的管脚为边缘触发,并为GPIO上拉。(根据情况即可)
    4). 触发中断后执行中断函数void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    注: 外部中断有很多,都是使用相同的函数,可以通过GPIO_Pin来区分到底是哪一个中断。例如if(GPIO_Pin== GPIO_PIN_2)
  4. 代码示例
//设置了PC2和PB9两个中断。
#include "main.h"  // 包含主头文件,定义了使用的库函数和STM32相关功能// 中断处理函数,当外部中断发生时调用
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if(GPIO_Pin == GPIO_PIN_2)  // 检查是否由PC2引脚引发中断{static int keycnt = 0;  // 计数变量,保存按键次数keycnt++;  // 每次中断计数加1if(keycnt % 2) {  // 如果按键次数是奇数,打开LEDHAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);  // 将PC6引脚设为高电平(LED亮)}else {  // 如果按键次数是偶数,关闭LEDHAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);  // 将PC6引脚设为低电平(LED灭)}}else if(GPIO_Pin == GPIO_PIN_9)  // 检查是否由PB9引脚引发中断{static int keycnt1 = 0;  // 另一个计数变量,用于PB9引脚keycnt1++;  // 每次中断计数加1if(keycnt1 % 2) {  // 如果按键次数是奇数,打开另一个LEDHAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);  // 将PC7引脚设为高电平(LED亮)}else {  // 如果按键次数是偶数,关闭LEDHAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);  // 将PC7引脚设为低电平(LED灭)}}
}int main(void)
{HAL_Init();  // 初始化HAL库,配置STM32硬件抽象层SystemClock_Config();  // 配置系统时钟MX_GPIO_Init();  // 初始化GPIO(通用输入输出引脚)while (1)  // 无限循环,程序在此循环中持续运行{}
}void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};  // 定义RCC时钟配置结构体RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};  // 定义时钟初始化结构体RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;  // 选择HSI(高精度内部振荡器)作为时钟源RCC_OscInitStruct.HSIState = RCC_HSI_ON;  // 启用HSIRCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;  // 使用默认的HSI校准值RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;  // 不启用PLL(相位锁定环)if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)  // 如果时钟配置失败{Error_Handler();  // 调用错误处理函数}RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;  // 配置AHB、APB1、APB2总线时钟RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;  // 使用HSI作为系统时钟RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;  // AHB总线时钟不分频RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;  // APB1总线时钟不分频RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  // APB2总线时钟不分频if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)  // 如果时钟配置失败{Error_Handler();  // 调用错误处理函数}
}static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};  // 定义GPIO初始化结构体__HAL_RCC_GPIOC_CLK_ENABLE();  // 启用GPIOC引脚的时钟__HAL_RCC_GPIOB_CLK_ENABLE();  // 启用GPIOB引脚的时钟HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8, GPIO_PIN_RESET);  // 将PC6、PC7和PC8引脚设为低电平(关闭)GPIO_InitStruct.Pin = GPIO_PIN_2;  // 配置PC2引脚GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;  // 设为下降沿触发中断模式GPIO_InitStruct.Pull = GPIO_PULLUP;  // 开启上拉电阻HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);  // 初始化PC2引脚GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8;  // 配置PC6、PC7、PC8为输出模式GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;  // 设为推挽输出模式GPIO_InitStruct.Pull = GPIO_NOPULL;  // 无需上下拉GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;  // 设为低速输出HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);  // 初始化PC6、PC7、PC8引脚GPIO_InitStruct.Pin = GPIO_PIN_9;  // 配置PB9引脚GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;  // 设为下降沿触发中断模式GPIO_InitStruct.Pull = GPIO_PULLUP;  // 开启上拉电阻HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);  // 初始化PB9引脚HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0);  // 设置EXTI2中断优先级为0HAL_NVIC_EnableIRQ(EXTI2_IRQn);  // 使能EXTI2中断HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);  // 设置EXTI9-5中断优先级为0HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);  // 使能EXTI9-5中断
}void Error_Handler(void)
{__disable_irq();  // 禁用所有中断while (1)  // 进入死循环,等待人为重启{}
}#ifdef  USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{// 调试信息,显示在哪个文件和第几行发生了错误
}
#endif

三、时间获取和软件消抖

时间获取
  1. 在STM32中,通常使用 SysTick 定时器 来实现时间测量和滴答计数 (ticks)。
  2. HAL_GetTick() 是 HAL 库提供的函数,用于获取系统启动后经过的毫秒数。
  3. 每当系统启动时,计时器从 0 开始,每 1 毫秒 ticks 变量就会递增 1。
uint32_t T1 = HAL_GetTick();  // 获取当前时间,单位是毫秒
do_something();               // 执行需要测量时间的操作
uint32_t T2 = HAL_GetTick();   // 获取结束时的时间uint32_t elapsed_time = T2 - T1;  // 计算操作执行的时间差,单位为毫秒
软件消抖
  1. 用来处理按键等机械开关在按下或释放时产生的抖动信号。
  2. 机械开关的抖动会导致短时间内开关状态不稳定,造成误触发。
  3. 在嵌入式系统中,按键输入需要进行消抖处理,确保得到的按键状态是稳定的。
  4. 代码实现
void intr_fun(uint32_t debounce_time)//消抖函数。debounce_time 为使用的消抖时间
{static uint32_t pre_ticks = 0;if(HAL_GetTick() - pre_ticks < debounce_time){return;}pre_ticks = HAL_GetTick();// 执行中断处理代码
}

四、矩阵键盘

  • 原理图
    在这里插入图片描述
  • 矩阵键盘的优点是能够使用较少的引脚来检测多个按键,这对于微控制器(如STM32)尤其有用。
  • 矩阵键盘处理逻辑(行和列的模式切换速度非常快,用户感知不到)
    1. 进入中断模式
    - 矩阵键盘的行和列分别连接到单片机的GPIO引脚。
    - 4列作为输出,输出低电平;
    - 4行作为输入(中断模式),并设置为上拉电阻模式,等待按键按下时的中断信号。
    2. 中断触发后,进入中断处理函数
    3. 第一步:检测行
    - 重新配置行作为输入模式,列作为输出模式(列保持低电平);
    - 如果按键按下,某行的电平会被拉低,这样可以检测出是哪一行的按键被按下。
    4. 第二步:检测列
    - 重新配置列为输入模式,行作为输出模式(行输出低电平);
    - 此时检测列的电平,按键按下的列会被拉低,从而可以得知是哪一列的按键被按下。
    5. 行和列都确定
    - 知道按下的具体行和列,可以进行编码,根据行和列的组合确定按下的是哪一个键。
    6. 恢复中断模式
    - 按键检测完毕后,恢复最初的中断模式,即行作为输入(中断),列作为输出,继续等待下次按键按下的中断信号。

矩阵键盘的行和列

  • 使用方法
    1. 将PA1~PA3的管脚作为输出设置为GPIO_Output
    2. 将PA4~PA7的管脚作为中断模式,设置为GPIO_EXTI,等待按键按下
    3. 在NVIC Interrupt Table中允许PA4~PA7启用中断。
    4. 导入特定的文件矩阵键盘文件。c文件在Src中,h文件在Inc中。
    5. 导入矩阵键盘的头文件,并在main函数中初始化keyboard_init();
    6. 对五的注解:
    - 调用 keyboard_init() 是为了完成矩阵键盘的GPIO引脚和中断的初始配置,确保STM32能够正常检测按键事件。
    - 这是任何硬件外设操作的第一步,在系统主循环开始之前,必须初始化所有硬件资源,以便后续的按键检测能够正常工作。
    7. 在void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)中处理即可
  • 代码示例
#include "main.h"
#include "keyboard.h"void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{static uint32_t pre_ticks = 0;if (HAL_GetTick() - pre_ticks < 200)  // 防抖处理{return;}pre_ticks = HAL_GetTick();char keynum = keyboard_getKeyNum(GPIO_Pin);switch (keynum) {case '1':HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);break;case '2':HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);break;case '3':HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);break;default:// 关闭所有 LEDHAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);break;}
}int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();keyboard_init();while (1){}
}void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK){Error_Handler();}
}static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8, GPIO_PIN_RESET);GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_6;GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|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(GPIOC, &GPIO_InitStruct);HAL_NVIC_SetPriority(EXTI4_IRQn, 0, 0);HAL_NVIC_EnableIRQ(EXTI4_IRQn);HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
}void Error_Handler(void)
{__disable_irq();while (1){}
}#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif

这篇关于STM32的使用方法一的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1147480

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

浅谈主机加固,六种有效的主机加固方法

在数字化时代,数据的价值不言而喻,但随之而来的安全威胁也日益严峻。从勒索病毒到内部泄露,企业的数据安全面临着前所未有的挑战。为了应对这些挑战,一种全新的主机加固解决方案应运而生。 MCK主机加固解决方案,采用先进的安全容器中间件技术,构建起一套内核级的纵深立体防护体系。这一体系突破了传统安全防护的局限,即使在管理员权限被恶意利用的情况下,也能确保服务器的安全稳定运行。 普适主机加固措施:

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操