嘿,StackOverflow!
在下面的代码中,我有一个简单的状态机,它可以更改一些外部照明设备的操作(正如注释所暗示的那样)。通过按下连接到GP1的按钮来更改状态。连接到GP1的电路是一个比较器去抖动电路,它将VDD与0.6VDD进行比较(我也尝试过RC/二极管/施密特触发电路),然后强制信号LO。在示波器上,当按钮快速启动时,我们会看到一个干净的方波。
PIC10F200的电流(以及不希望的)行为如下:
- 按下开关(状态=0)
- 状态机变量增量(状态=1)
- 照明进入案例1,然后打开
- 照明至少保持一秒钟
- 照明关闭
- 系统保持此状态,直到再次启动按钮或断电
问题是:为什么它会这样如果可能的话,我该如何修复它,使一次按下按钮就等于一次状态增量,然后PIC会在系统通电且按钮未再次启动的情况下保持该增量?
#define SYS_FREQ 8000000L
#define FCY SYS_FREQ/4
#define _XTAL_FREQ 4000000
/******************************************************************************/
/* User Global Variable Declaration */
/******************************************************************************/
/******************************************************************************/
/* Main Program */
/******************************************************************************/
__CONFIG(MCLRE_ON & CP_OFF & OSC_IntRC);
void main(void)
{
TRIS = 0b111110;
unsigned char state = 0;
while(1)
{
switch (state)
{
case 0: // IDLE/OFF
if (GPIObits.GP0) GPIObits.GP0 = 0;
break;
case 1: // ON
if (!GPIObits.GP0) GPIObits.GP0 = 1;
break;
case 2: // BLINK (slow)
GPIObits.GP0 = !GPIObits.GP0;
__delay_ms(100);
break;
case 3: // BLINK (fast)
GPIObits.GP0 = !GPIObits.GP0;
__delay_ms(50);
break;
case 4: // BEAT DETECT
GPIObits.GP0 = GPIObits.GP2;
break;
default:
state = 0;
break;
}
if (!GPIObits.GP1)
{
__delay_ms(250);
state++;
}
}
}
UPDATE:由于我试图用这个代码/系统完成什么似乎有点困惑,所以让我们提供完整的上下文。该微控制器,PIC10F200是电致发光(EL)线驱动器整体板设计的一部分。微控制器通过将GP0
连接到驱动器IC的EN
端口来简单地控制驱动器电路是否启用该系统有四种操作模式,导线持续接通,导线闪烁,导线闪烁速度更快,只要检测到低频跳动,导线就会闪烁(系统中的另一个电路)从这些操作模式的转换由安装在PCB上的按钮(瞬时开启)开关控制这需要上述代码中的state
在按钮启动之间保持稳定。它目前没有这样做,其行为与本文最初部分所述相同。正如问题标题所述,为什么state
目前不稳定,我如何做到这一点
更新(2014-03-08):解决方案
假设GP0是输出,GP2是T0CKI,并且您有一个开关,在启动时将信号驱动为LO,则需要设置以下设置。
TRIS = 0b111110;
OPTION = 0b11101111;
OPTION的0-3位是否真的很重要是一个判断调用,以及您是否选择使用WDT模块。
此外,按钮释放检测的实现是一个简单的计数器机制,该机制在计数期间的任何点GP2为LO时重置。
if (TMR0 > 0)
{
while (count < 20)
{
if (!GPIObits.GP2) count = 0;
__delay_ms(10);
count++;
}
TMR0 = 0;
state++;
}
您有硬件/软件设计问题!
- 当程序处于延迟循环时,按键不处于已检查
- 您只检查按键事件,但也必须检查按键relase
我的目的是你可以使用GP2(T0CKI)引脚代替GP1作为按键。如果用作计数器TMR0输入,则此引脚具有施密特触发器输入。之后,将MCPU TMR0配置为GP2(T0CKI)引脚上带有外部时钟的计数器。您还必须设置T0SE位以配置计数器,该计数器将在T0CKI引脚上从高到低转换时递增。在任何循环后的程序中,如果TMR0内容大于0,则按下该键。等待几毫秒,检查密钥是否已重新绑定。如果已重新绑定,则增加state
变量并清除TMR0内容。
移动
if (!GPIObits.GP1){
if(isPressed == false){
//__delay_ms(250); //you dont need the delay
state++;
if(state == 5){state = 0;}
isPressed = true;
}
}
else{isPressed = false;}
在CCD_ 6语句之前。while
环路之前的char isPressed = false;
valter
__delay_ms(250); <-- too small delay
当您慢慢按下按钮时,循环可能会旋转几次。尝试将其增加到1000ms。
更新
您应该在禁用WDT(看门狗计时器)的情况下运行PIC,否则它将在几秒钟内重置PIC。这与你的观察结果相似。您可以在主功能开始时闪烁LED以检查是否发生这种情况,也可以初始化unsigned char state = 1;
并查看其行为。
试试这个__CONFIG(MCLRE_ON & CP_OFF & OSC_IntRC & WDT_OFF);