程序中时常需要将GPIO引脚配置为输入引脚,从而接收外部的开关量信号,当开关信号变化时执行相应操作或给相应标志位置位。
这本身很常见,但是最近在调试的过程中却遇到了明明外部信号(例如按钮并未按下)并未改变,GPIO输入引脚信号确发生跳变,导致程序执行步骤出现错误。
在CCS里将相应GPIO引脚的GPxDAT寄存器添加到变量监视窗口,可以明显看到信号偶尔出现跳变(变量所在行变黄色),考虑应该是现场电磁干扰导致的信号跳变。
问题发生时因为正在现场调试,急着尽快解决问题,想了一个“土办法”,由单层if判断语句
1 if(GpioDataRegs.GPxDAT.bit.GPIOxx==0) //已使能内部上拉,0代表按钮按下 2 { 3 标志位置位; 4 }
变成双层if判断语句,两层if判断语句之间带10ms延迟
1 if(GpioDataRegs.GPxDAT.bit.GPIOxx==0) //已使能内部上拉,0代表按钮按下 2 { 3 DELAY_US(10000); //延时保持 4 5 if(GpioDataRegs.GPxDAT.bit.GPIOxx==0) 6 { 7 标志位置位; 8 } 9 }
使用这样的“土办法”确实解决了现场调试遇到的GPIO输入引脚信号跳变问题,实验了一天再没有出现程序执行步骤出错的问题。
回酒店之后继续思考这个问题,又读了一遍TI的寄存器手册。发现有两个GPIO引脚相关寄存器
GPxCTRL:
The GPxCTRL registers specify the samping period for input pins when configured for input qualification using a window of 3 or 6 samples .
The sampling period is the amount of time between qualification samples relative to the period of SYSCLKOUT . The number of samples is
specified in the GPxQSELn registers.
Value Description
0x00 Samping period = T(SYSCLKOUT ) x 1
0x01 Samping period = T(SYSCLKOUT ) x 2
0x02 Samping period = T(SYSCLKOUT ) x 4
......
0xFF Samping period = T(SYSCLKOUT ) x 510
GPxQSELn:
Select input qualification type for GPIO. The input qualification of each GPIO input is controlled by two bits .
Value Description
00 Synchronize to SYSCLKOUT only .
01 Qualification using 3 samples .
10 Qualification using 6 samples .
11 Asynchronous .(no synchronization or qualification) .
简单点说,GPxCTRL 决定了输入引脚的指定采样周期,也就是采样相对于系统时钟的周期,而GPxQSELn则决定了采样个数。
两个寄存器的默认值都是“ 0 ”,也就是一个系统时钟的采样周期,采样个数为1。尝试把采样周期和采样个数都相应增加,防止输入引脚电平状态受干扰产生的瞬间跳变导致GPIO采集信号跳变。
在 InitGpio()内相应位置添加了下面两行代码
1 GpioCtrlRegs.GPxCTRL.bit.GPIOxx = 0x0F ; //采样周期30个系统时钟 2 3 GpioCtrlRegs.GPxQSELn.bit.GPIOxx = 1; //采用3个采样周期宽度限制
经过实验,同样能达到消除现场调试遇到的GPIO输入引脚信号跳变现象。
相比较而言,更推荐配置GPxCTRL ,GPxQSELn寄存器的方法,更严谨,可配置性更好。
原文:https://www.cnblogs.com/Fangjq2020/p/13222446.html