其他分享
首页 > 其他分享> > 【stm32_STD_lib学习】用keil观察GPIO引脚初始化后的寄存器

【stm32_STD_lib学习】用keil观察GPIO引脚初始化后的寄存器

作者:互联网

通过keil在线调试观察GPIO_STD_lib中Init后的GPIO寄存器状态

如图,首先需要在Debug设置处取消下载到flash的勾选,亲测如果不取消的话,调试时无法打断点也只能在汇编角度观察程序运行

 

 

如图,调出外设观察窗口:

 

为板级外设的初始化函数打断点

 

因为我key1键按下时,灯反而灭了,不符合预期;

通过在线调试过程中,检查初始化LED_Blue_Init()执行后,LED引脚的输出和实际灯的亮灭:

,如图,此时引脚GPIOB_Pin_1的引脚输出为0,但是灯却是亮的,

重新检查原理图后,发现GPIOB_Pin_1的引脚是与LED共阴极链接的,即输出低电平才会亮,得把bsp里的灯亮函数改为调用Reset函数(原来是Set)

 

 至此,key1和key2功能混乱的原因找到了;(以后写代码时得先注意把原理图看仔细些,不然就是在写bug)

接下来检查一下按键检测函数,因为前期现象不符合预期,有许多疑问,参考了野火的按键检测中阻塞的写法;

现在尝试把阻塞去掉看看有什么影响:

代码如下:(忘记用markdown了,将就看吧)

uint8_t KEY1_Detect(void)
{
  if ((GPIO_KEY1->IDR) & GPIO_KEY1_Pin)  //如果从输入寄存器IDR中读出的状态中,检测到KEY1引脚状态
  {
    /*

    这句是野火的按键阻塞函数

    while((GPIO_KEY1->IDR) & GPIO_KEY1_Pin);

    实测发现不需要阻塞在这里也行,只是现象不同,

    不阻塞的话,LED函数会在按键按下瞬间运行,即按下按键立刻开灯

    阻塞的话会在按键松开时才运行LED函数,即松开按键才开灯

    */

    return 1;              //引脚是按下的话就返回true


  }else                  //引脚未按下的话就返回flase
  {
    return 0;
  }
}

至此,按键阻塞的现象差异也明白了;

还剩下一个问题,浮空输入和上拉下拉的实际效果怎么样?

因为在之前的自己写标准库过程中,了解了如果是上下拉模式,标准库会手动去设置置位复位寄存器BSRR、BRR

 想看看实际上,浮空、上拉、下拉后,从寄存器中读出来的值有什么不同,

浮空不知道,但上下拉预期应该分别是高、低电平,先看引脚初始化前输入寄存器的值:

 

 

 

 如图A、C引脚都是0x0;

Floating浮空

 

 

 

 

 

IPD下拉

IPU上拉

 

 

 

 

 

 

 重新在上拉模式下打断点检查:

 

 

观察到函数确实操作了BSRR寄存器,输出寄存器ODR也改变了,但是输入寄存器IDR的值并没有改变,

原因我也不清楚,但这说明了一个现象,设置BSRR后,改变并不会同步到IDR上,只会同步到ODR上

 

 来看看KEY1_Detect按键检测的实现函数:

 

我这里是通过IDR检查的,尝试把对应led_off的Key2检测函数改成ODR检查

 

运行观察

 

 

 

 

 

 

 至此,现象说明的第一个直接问题是,用IDR和ODR做输入状态的检测条件,效果是不同的,

和前面提到的一样,上拉模式设置BSRR寄存器后,改变并不会同步到输入寄存器IDR上,只会同步到输出寄存器ODR上

 

检查在输出模式下的Led引脚是否也是这样:

 

 

 

 如图,把我的IDR该位清零了,再接着测试写BSRR

 

 

 再把上拉、下拉输入的key引脚设置CRL、BSRR过程中,IDR和ODR的变化记录下来:

 

 

 

 我这时才发现,其实我是在看浮空输入下(CRL复位为0x4代表浮空输入),改变BSRR,IDR和ODR会有什么变化

 

 

 

 

 

 上拉模式下,设置BSRR前后寄存器变化:

 

 

 

 此时IDR会同步;

再重新初始化引脚为浮空,查看更改BSRR的现象

 

 

 

 

 太乱了,我决定把std库抛开,直接设置CRL寄存器后,观察BSRR的改变对IDR和ODR的影响

 

 

在浮空、输入模式下,设置BSRR,ODR改变了,IDR没改变

上拉:

 

 

 

输出下:

 

 

 结论已经出来了,和上拉还是浮空无关,在输入模式下,IDR不会同步BSRR的变化,只有输出模式下,IDR才会同步BSRR的变化;

而ODR不管在任何情况下都会同步BSRR的变化。

回到本设计的过程,我想实现,key1按键被按下后,led点亮;key2按键被按下后,led熄灭;

1.在原理图方面要搞清楚引脚和led、按键的接法,和逻辑上的高低是否相同;

这里led共阴,得输出低电平才亮;按键的逻辑和思维习惯一样,按下为高电平;

那么在led_bsp中,调用std库时得调和电路符合的那个,ON调Reset,OFF调Set;

按键检测中检测高电平为按下,没问题。

2.在按键引脚设置为输入的前提下,设置BSRR的值是不会被反映到IDR的;

如果要获得BSRR改变的信号,得去读ODR;

复位时是浮空输入,在std库初始化的过程中,分别对上拉下拉设置了BSRR,

但在我前面测试的过程中,在std库对引脚初始化后,通过IDR输入数据寄存器去读,就读不到上下拉的变化;

只有把IDR改为ODR,才能读到BSRR的改变,用到这个上下拉造成的效果;

3.又通过测试发现,上拉的引脚在程序里一直读到1,下拉的引脚在程序里一直读到0,不管外部的按键如何变化;

4.所以设置为浮空输入才是按键的正确使用方法,并且又发现,在浮空输入下,通过ODR根本读不到外部按键的变化;

所以说之前的用法果然是错的,正确用法的思路应该是:

设置为输入模式下,IDR接收外部环境的变化,不根据内部输出改变;

设置位输出模式下,ODR接收内部控制的信号,不根据外部信号改变。

输入模式与IDR,输出模式与ODR,这两组概念是绑定使用的,对GPIO的疑问解决了。

 

过程发现的另一个现象:(或许用不上,以后再看)

GPIO时钟使能时,IDR的值会改变

 

 

 

 

 

 

 

 

 

 另一个问题:(已解决)

貌似复位后无法进入main

按住复位键后全速运行提示不支持那么多断点,哈哈,减掉一点

 

断点删除后,得重新编译烧写,后面就能正常调试了。

 

标签:STD,lib,引脚,ODR,IDR,BSRR,浮空,按键
来源: https://www.cnblogs.com/xianyucaicaizi/p/16212643.html