单片机学习小组
直播中

djfldsthtr

8年用户 964经验值
擅长:光电显示
私信 关注

20脚JTAG/SWD调试接口接法是怎样的

20脚JTAG/SWD调试接口接法是怎样的?
什么是时钟?为什么STM32要有多个时钟源呢?




回帖(2)

张瑞娟

2022-2-24 11:33:15
线路连接


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 关键字被广泛使用。
举报

朱佳婧

2022-2-24 11:33:19
1
举报

更多回帖

发帖
×
20
完善资料,
赚取积分