线路连接
1、20脚JTAG/SWD调试接口接法:
参考电压信号,用于检测目标板是否供电,直接与目标板VDD相连,并不向外提供输出电压;
GND:公共地信号;
SWDIO:串行数据输入信号,作为仿真信号的双向数据信号线,建议上拉;
SWCLK:串行时钟输入,作为仿真信号的时钟信号线,建议下拉;
SWO:串行数据输出,CPU调试接口可通过SWO输出一些调试信息,该引脚可选。
RESET:仿真器输出至目标CPU的系统复位信号;是可选信号
下载完程序并提供电源,Debug模式下,下载完成后依然供电
2、USB转串口
功能:将串口收发数据转换成USB数据,接到电脑USB配合串口调试助手使用,方便检查串口收发信息
驱动:常用驱动CH340,过时驱动
3、开发板电源问题
STM32不能提供5V电压,51似乎可以
新建工程文件常出现的错误
1、缺少启动文件
编译的时候会报错,error: L6236E: No section matches selector - no section to be FIRST/LAST.
查看左边Project目录下Drivers/CMSIS文件下缺少.s 文件。直接从旧的工程里拷贝,右键该文件夹在菜单列表选品字型图标,添加即可。
2、Keil 软件仿真出现 Error: Flash Download failed - “Cortex-M4” 的解决方法
打开KEIL即显示缺少库文件(但已经安装了),强行退出下载界面,编译出现Error: Flash Download failed - "Cortex-M4"错误。依次点击魔法棒、Debug、setting、flash dowmload可以看到缺少flash文件
解决方法:在强行退出的最后一步(创建工程的页面)选择合适的芯片即可
CubeMX配置
时钟树
什么是时钟
时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令。时钟系统就是CPU的脉搏,决定cpu速率,像人的心跳一样 只有有了心跳,人才能做其他的事情,而单片机有了时钟,才能够运行执行指令,才能够做其他的处理 (点灯,串口,ADC),时钟的重要性不言而喻。
为什么 STM32 要有多个时钟源呢
STM32本身十分复杂,外设非常多 但我们实际使用的时候只会用到有限的几个外设,使用任何外设都需要时钟才能启动,但并不是所有的外设都需要系统时钟那么高的频率,为了兼容不同速度的设备,有些高速,有些低速,如果都用高速时钟,势必造成浪费 并且,同一个电路,时钟越快功耗越快,同时抗电磁干扰能力也就越弱,所以较为复杂的MCU都是采用多时钟源的方法来解决这些问题。所以便有了STM32的时钟系统和时钟
STM32为了低功耗,他将所有的外设时钟都设置为disable(不使能),用到什么外设,只要打开对应外设的时钟就可以, 其他的没用到的可以还是disable(不使能),这样耗能就会减少。 这就是为什么不管你配置什么功能都需要先打开对应的时钟的原因
STM32的时钟系统框图
乍一看很吓人,但其实很好理解,我们看系统时钟SYSCLK 的左边 系统时钟有很多种选择,而左边的部分就是设置系统时钟使用那个时钟源,
系统时钟SYSCLK 的右边,则是系统时钟通过AHB预分频器,给相对应的外设设置相对应的时钟频率
从左到右可以简单理解为 各个时钟源—>系统时钟来源的设置—>各个外设时钟的设置
时钟系统
各个时钟源 (左边的部分)
STM32 有4个独立时钟源:HSI、HSE、LSI、LSE。
①、HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高。
②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。
③、LSI是低速内部时钟,RC振荡器,频率为40kHz,提供低功耗时钟。
④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。
其中LSI是作为IWDGCLK(独立看门狗)时钟源和RTC时钟源 而独立使用
而HSI高速内部时钟 HSE高速外部时钟 LSI低速内部时钟 这三个经过分频或者倍频 作为系统时钟来使用
PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。 通过倍频之后作为系统时钟的时钟源
HAL 库
__weak 修饰符
“weak” 顾名思义是“弱”的意思,所以如果函数名称前面加上weak 修饰符,我们一般称这个函数为“弱函数”。 加上了weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak 声明的函数,并且编译器不会报错。
举个例子: 我们打开工程模板,找到并打开文件stm32f4xx_hal.c 文件,里面定义了一个函数 HAL_MspInit,定义如下:
__weak void HAL_MspInit(void)
{
__IO uint32_t tmpreg = 0x00;
UNUSED(tmpreg);
}
// 可以看出,HAL_MspInit 函数前面有加修饰符__weak。同时,在该文件的前面有定义函数HAL_Init,并且 HAL_Init 函数中调用了函数 HAL_MspInit。
HAL_StatusTypeDef HAL_Init(void)
{
…//此处省略部分代码
HAL_MspInit();
return HAL_OK;
}
如果我们没有在工程中其他地方重新定义 HAL_MspInit()函数,那么 HAL_Init 初始化函数执行的时候,会默认执行 stm32f4xx_hal.c 文件中定义的 HAL_MspInit 函数,而这个函数没有任何控制逻辑。
如果用户在工程中重新定义函数 HAL_MspInit,那么调用 HAL_Init 之后,会执行用户自己定义的 HAL_MspInit 函数而不会执行 stm32f4xx_hal.c 默认定义的函数。也就是说,表面上我们看到函数 HAL_MspInit 被定义了两次,但是因为有一次定义是弱函数,使用了__weak修饰符,所以编译器不会报错。
总结:
weak 在回调函数的时候经常用到。这样的好处是,系统默认定义了一个空的回调函数,保证编译器不会报错。同时,如果用户自己要定义用户回调函数,那么只需要重新定义即可,不需要考虑函数重复定义的问题,使用非常方便,在 HAL 库中weak 关键字被广泛使用。
线路连接
1、20脚JTAG/SWD调试接口接法:
参考电压信号,用于检测目标板是否供电,直接与目标板VDD相连,并不向外提供输出电压;
GND:公共地信号;
SWDIO:串行数据输入信号,作为仿真信号的双向数据信号线,建议上拉;
SWCLK:串行时钟输入,作为仿真信号的时钟信号线,建议下拉;
SWO:串行数据输出,CPU调试接口可通过SWO输出一些调试信息,该引脚可选。
RESET:仿真器输出至目标CPU的系统复位信号;是可选信号
下载完程序并提供电源,Debug模式下,下载完成后依然供电
2、USB转串口
功能:将串口收发数据转换成USB数据,接到电脑USB配合串口调试助手使用,方便检查串口收发信息
驱动:常用驱动CH340,过时驱动
3、开发板电源问题
STM32不能提供5V电压,51似乎可以
新建工程文件常出现的错误
1、缺少启动文件
编译的时候会报错,error: L6236E: No section matches selector - no section to be FIRST/LAST.
查看左边Project目录下Drivers/CMSIS文件下缺少.s 文件。直接从旧的工程里拷贝,右键该文件夹在菜单列表选品字型图标,添加即可。
2、Keil 软件仿真出现 Error: Flash Download failed - “Cortex-M4” 的解决方法
打开KEIL即显示缺少库文件(但已经安装了),强行退出下载界面,编译出现Error: Flash Download failed - "Cortex-M4"错误。依次点击魔法棒、Debug、setting、flash dowmload可以看到缺少flash文件
解决方法:在强行退出的最后一步(创建工程的页面)选择合适的芯片即可
CubeMX配置
时钟树
什么是时钟
时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令。时钟系统就是CPU的脉搏,决定cpu速率,像人的心跳一样 只有有了心跳,人才能做其他的事情,而单片机有了时钟,才能够运行执行指令,才能够做其他的处理 (点灯,串口,ADC),时钟的重要性不言而喻。
为什么 STM32 要有多个时钟源呢
STM32本身十分复杂,外设非常多 但我们实际使用的时候只会用到有限的几个外设,使用任何外设都需要时钟才能启动,但并不是所有的外设都需要系统时钟那么高的频率,为了兼容不同速度的设备,有些高速,有些低速,如果都用高速时钟,势必造成浪费 并且,同一个电路,时钟越快功耗越快,同时抗电磁干扰能力也就越弱,所以较为复杂的MCU都是采用多时钟源的方法来解决这些问题。所以便有了STM32的时钟系统和时钟
STM32为了低功耗,他将所有的外设时钟都设置为disable(不使能),用到什么外设,只要打开对应外设的时钟就可以, 其他的没用到的可以还是disable(不使能),这样耗能就会减少。 这就是为什么不管你配置什么功能都需要先打开对应的时钟的原因
STM32的时钟系统框图
乍一看很吓人,但其实很好理解,我们看系统时钟SYSCLK 的左边 系统时钟有很多种选择,而左边的部分就是设置系统时钟使用那个时钟源,
系统时钟SYSCLK 的右边,则是系统时钟通过AHB预分频器,给相对应的外设设置相对应的时钟频率
从左到右可以简单理解为 各个时钟源—>系统时钟来源的设置—>各个外设时钟的设置
时钟系统
各个时钟源 (左边的部分)
STM32 有4个独立时钟源:HSI、HSE、LSI、LSE。
①、HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高。
②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。
③、LSI是低速内部时钟,RC振荡器,频率为40kHz,提供低功耗时钟。
④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。
其中LSI是作为IWDGCLK(独立看门狗)时钟源和RTC时钟源 而独立使用
而HSI高速内部时钟 HSE高速外部时钟 LSI低速内部时钟 这三个经过分频或者倍频 作为系统时钟来使用
PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。 通过倍频之后作为系统时钟的时钟源
HAL 库
__weak 修饰符
“weak” 顾名思义是“弱”的意思,所以如果函数名称前面加上weak 修饰符,我们一般称这个函数为“弱函数”。 加上了weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak 声明的函数,并且编译器不会报错。
举个例子: 我们打开工程模板,找到并打开文件stm32f4xx_hal.c 文件,里面定义了一个函数 HAL_MspInit,定义如下:
__weak void HAL_MspInit(void)
{
__IO uint32_t tmpreg = 0x00;
UNUSED(tmpreg);
}
// 可以看出,HAL_MspInit 函数前面有加修饰符__weak。同时,在该文件的前面有定义函数HAL_Init,并且 HAL_Init 函数中调用了函数 HAL_MspInit。
HAL_StatusTypeDef HAL_Init(void)
{
…//此处省略部分代码
HAL_MspInit();
return HAL_OK;
}
如果我们没有在工程中其他地方重新定义 HAL_MspInit()函数,那么 HAL_Init 初始化函数执行的时候,会默认执行 stm32f4xx_hal.c 文件中定义的 HAL_MspInit 函数,而这个函数没有任何控制逻辑。
如果用户在工程中重新定义函数 HAL_MspInit,那么调用 HAL_Init 之后,会执行用户自己定义的 HAL_MspInit 函数而不会执行 stm32f4xx_hal.c 默认定义的函数。也就是说,表面上我们看到函数 HAL_MspInit 被定义了两次,但是因为有一次定义是弱函数,使用了__weak修饰符,所以编译器不会报错。
总结:
weak 在回调函数的时候经常用到。这样的好处是,系统默认定义了一个空的回调函数,保证编译器不会报错。同时,如果用户自己要定义用户回调函数,那么只需要重新定义即可,不需要考虑函数重复定义的问题,使用非常方便,在 HAL 库中weak 关键字被广泛使用。
举报