【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