stm32f103 整 理笔记

在正式复习stm32f1103之前 ,我们得新整 理一下,方便以后看日记

引脚功能:

GPIO_MODE_INPUT          浮空输入:   引脚电平完全由外部决定,悬空时电平乱跳。用于按键、传感器、外部信号输入。
GPIO_MODE_OUTPUT_PP      推挽输出:   能直接输出强高低电平,驱动能力强。用于LED、蜂鸣器、继电器、普通控制。
GPIO_MODE_OUTPUT_OD      开漏输出:   只能拉低电平,高电平要靠外部上拉,可多芯片共用总线。用于I2C、1-Wire、电平转换。
GPIO_MODE_AF_PP          复用推挽:   给串口、PWM、SPI等外设用,强驱动输出。用于串口TX、PWM输出、SPI时钟。
GPIO_MODE_AF_OD          复用开漏:   给外设开漏用,只能拉低,需上拉。用于硬件I2C的SDA/SCL。
GPIO_MODE_AF_INPUT       复用输入:   给外设专用输入口。用于串口RX、SPI输入、定时器捕获。
GPIO_MODE_ANALOG         模拟模式:   只测电压,不走数字信号。用于ADC采样、模拟信号输入。

1. 什么是 MSP?

MSP 全称是MCU Support Package,可以直接理解成:单片机外设的「底层初始化工具人」。 
它的核心工作,就是给单片机的各种外设(比如串口、定时器、GPIO、中断这些)做最基础的初始化: 
  • 给外设开时钟(相当于给外设通电,不通电外设没法干活)
  • 配置外设用到的 GPIO 引脚(比如串口要用到 TX/RX 两个引脚,得先把这俩脚设成串口模式)
  • 配置外设相关的中断(比如串口接收数据要触发中断,得先把中断打开、设好优先级) 
它是 HAL 库的核心组成部分,用 HAL 库开发时,必须写好 MSP 函数,外设初始化的时候会自动调用它。 
举个例子:你要用串口(USART)发数据,HAL 库会先自动调用串口的 MSP 函数,把串口的时钟、引脚、中断都配置好,再执行发数据的功能,不用你手动去管这些底层操作。
 

 

2. MSP 的调用逻辑 

MSP 函数不用你手动调用,CubeMX 会自动生成代码,程序运行时会自动调用,整个流程是这样的: 
    1. 程序从main()函数开始运行
    2. 先执行HAL_Init(),初始化 HAL 库的基础环境
    3. 自动调用HAL_MspInit(),这就是全局的 MSP 初始化入口
    4. 后续你初始化某个具体外设(比如串口、SPI)时,HAL 库会自动调用对应外设的 MSP 函数,完成该外设的底层配置

编写第一个示例,点亮一个灯,首先打开stmcubeMx 选中芯片型号 ,选择我们当下用的是gpio8,和9   开发板是立创星空学习板

image

 

需要用stmcubeMx 创立工程, 选中型号    然后配置引脚  gpio 8    gpio 9    ,因为我们要做点亮灯,默认要高电平,所以要配置为高电平  ,推换推出,由于是输出,下上拉无意义,这儿不用管,  如果设低电平,默认灯就亮了,好像也不是不行,这儿其实任意哈,,,

关于stmcubeMx 要下载6.14.1,老版有很多坑,传说6.15也有乱码的坑,所以还是选6.14.1   老版本的坑比如中文乱码问题 ,配置的时钟与实际硬件运行频率不一致(差一半、翻倍),如果用低本遇到需要解决中文乱码可以先增加一个环境变量,

选择新建,在变量名和变量值如下如下内容
变量名称: JAVA_TOOL_OPTIONS
变量值:-Dfile.ecoding=UTF-8       修改完成后,全部点确定。然后重启stm32CubeMX软件即可。

 

配置好工程后,可以用kial 或vscode 找开项目,在maian.c 写引脚 代码,完成第一个示例

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

    /* USER CODE BEGIN 3 */
		HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);   // led1 熄灭
		HAL_Delay(500); // 延时500ms 
		HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); // led1 点亮
		HAL_Delay(500);  // 延时500ms 

  }
  /* U

  这儿我们可以看到软件工作文件目录,需要介绍一下, stm32f1xx.it  是中断函数的编写地方,

       stm32f1xx.hal.map.c 是核心底层配置的地方,stm32f1xx_hal_msp.c。 是 STM32CubeMX 自动生成, MSP = MCU Support Package,MCU 底层支撑配置
专门存放所有外设的底层硬件初始化:比如以下配置
 

  • 开启外设时钟(GPIO、UART、ADC、TIM 等)
  • 配置引脚复用功能
  • 配置 NVIC 中断
  • 配置 DMA(如果用到)
     
    所有 HAL_XXX_MspInit() 统一放在这里。以下这个文件的代码片断,可能总结为main.c  虽然也有配置,他是基于这个文件的配置,这个文件才是操作硬 件的配置
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
  __HAL_RCC_USART1_CLK_ENABLE();  // 开时钟
  // 配置GPIO、NVIC等
}

 其它文件的分布,如下,

 

image

 

常见方法介绍:

main.c 文件中常用方法介绍:

HAL_Init()                         初始化项目和初始化hal 库 ,项目第一句代码,不要在HAL_Init()之前调用任何外设相关的代码,否则会出奇怪的 bug。

SystemClock_Config()     配置时钟,CubeMX 生成的工程里,这个函数会自动写好,一般不用自己改。时钟  配置对,外设波特率、定时器、延时都会出错。

MX_GPIO_Init()               这个函数是 CubeMX 生成的,里面会调用HAL_GPIO_Init()。帮你一次性配置好所有引脚的输入 / 输出模式、上下拉电阻、速度等。不要在这个函数里手动写引脚操作代码,                                            否则重新生成工程会被覆盖。

HAL_GPIO_WritePin()        控制 GPIO 引脚输出高 / 低电平。给引脚 “发信号”,比如让 LED 亮 / 灭、给模块发指令。

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);   // PA5输出高电平       参数介绍,第一个参数,那一组引脚 ,第二个参数,这组引脚中那个编号  第三个参数,高还是低电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // PA5输出低电平

HAL_Delay()          毫秒级延时函数,让程序 “等一会儿再往下走”        这个延时是阻塞的,延时期间程序什么都做不了,游戏里用多了会卡顿。高优先级中断会打断延时,导致实际延时时间变长

HAL_Delay_Us()(或自定义微秒延时)       功能同上,只是时间不同

其它以后才用到的函数   

HAL_GPIO_ReadPin()             读取 GPIO 引脚的电平状态,判断按键是否按下。

HAL_GPIO_TogglePin()           翻转 GPIO 引脚的电平状态(高变低、低变高)。

HAL_TIM_Base_Start() / HAL_TIM_Base_Start_IT()     启动定时器,用来做定时任务、PWM、游戏帧率控制。   

HAL_TIM_PWM_Start()          启动定时器的 PWM 输出,用来驱动蜂鸣器、电机、LED 呼吸灯。

在正式写代码前,先了解一下软件环境 ,比如中文支持,界面样式,在kail5 的 edit 有一个 Configuration菜单,里面有软件相关配置

image

 编译流程:

我们在写代码的时候,有部份代码是给编译器看的,比如以下的注解:

image

 

 一个完成的功能包装封,包括功能封装,示例 我们要点灯,并且要把功能封装成来。

第一步,核心代码是

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);   // PA5输出高电平       参数介绍,第一个参数,那一组引脚 ,第二个参数,这组引脚中那个编号  第三个参数,高还是低电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // PA5输出低电平

封装:
我们们gpio.c  写函数本身 在gpio.h 需要爆露出宏定义和函数名,方便主函数据调用
gpio.c 新增二个函数功能代码,一个是功能函数,一个是测试函数

void LED_Control(uint8_t device, uint8_t cmd)
{
    GPIO_PinState state = cmd ? GPIO_PIN_RESET : GPIO_PIN_SET;

    if(device == LED1)
        HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, state);
    else if(device == LED2)
        HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, state);
}

测试函数:

void LED_Test(void)
{
        LED_Control(LED1,ON); 
        LED_Control(LED2,OFF); 
        HAL_Delay(500); 
        LED_Control(LED1,OFF); 
        LED_Control(LED2,ON); 
        HAL_Delay(500); 
}

载图如下 :

image

 其它写法参考:

void LED_Control(uint8_t device, uint8_t cmd)
{
    switch(device)
    {
        case LED1: HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, cmd ? 0 : 1); break;
        case LED2: HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, cmd ? 0 : 1); break;
    }
} 

 

 最后主函数调用:

image

 

 以下功能通常  蜂鸣器   接触器   开发都是一样,通过调节电平来控制,所以基础控制电位的的功能先不介结了,以下开始研究按健扫描

 

 

中断模式

要使中断的话,意思是事件,比如我们要绑定在gpio  让这个按扭中低变平或高电平发生时,运行一个函数就叫中断,中断还可以帮在定时器到点,按健被 按下等场

示例一
第一在stm32cubeMx中  将一下gpio绑定于引脚 为中断模式 

 

 

image

 然后在gpio 的配置中配置一下什么条件触发

image

 

 还差一步,使其使能,这一步完成后就可以ai 可以写代码了

image

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

000000000000000000000

posted @ 2026-04-11 08:00  谢双元小号  阅读(2)  评论(0)    收藏  举报