2

嘿,StackOverflow!

在下面的代码中,我有一个简单的状态机,它改变了一些外部照明设备的操作(正如注释所暗示的那样)。通过按下连接到 GP1 的按钮改变状态。连接到 GP1 的电路是一个比较器去抖电路,它将 VDD 与 0.6VDD 进行比较(我也尝试过 RC/二极管/施密特触发电路),然后强制信号 LO。在示波器上,当按钮被快速启动时,我们会看到一个干净的方波。

PIC10F200当前(和不良行为如下:

  1. 开关被按下(状态 = 0)
  2. 状态机变量增量(状态 = 1)
  3. 照明转到案例 1,然后打开
  4. 照明至少保持一秒钟
  5. 照明关闭
  6. 系统保持此状态,直到再次按下按钮或关闭电源

问题是:为什么它会这样?如果可能的话,我如何修复它,使单次按下按钮相当于一个状态增量,只要系统通电并且按钮不再被启动,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++;
        }
    }
}

更新:由于我试图用这个代码/系统完成什么似乎有点混乱,让我们提供完整的上下文。这款微控制器PIC10F200是电致发光 (EL) 线驱动器整体电路板设计的一部分。微控制器通过连接到驱动IC的端口来简单地控制驱动电路是否启用。系统有四种操作模式,线常亮,线闪烁,线闪烁更快,每当检测到低频拍(系统中的另一个电路)时,线闪烁。GP0EN这些操作模式的转换由安装在 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++;
}
4

3 回答 3

2

您有硬件/软件设计问题!

  1. 当您的程序处于延迟循环中时,不会检查您的按键!
  2. 您只检查按键事件,但您还必须检查按键释放。

我的目的是您可以使用 GP2 (T0CKI) 引脚代替 GP1 作为按键按钮。如果用作计数器 TMR0 输入,则该引脚具有施密特触发器输入。之后将您的 MCPU TMR0 配置为在 GP2 (T0CKI) 引脚上使用外部时钟的计数器。您还必须设置 T0SE 位来配置计数器,该计数器将在 T0CKI 引脚上从高到低转换时递增。在任何循环后的程序中检查 TMR0 内容是否大于 0 按键被按下。等待一些毫秒并检查是否释放了密钥,如果释放而不是增加state变量并清除 TMR0 内容。

于 2014-03-06T09:15:27.797 回答
0

移动你的

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;}

switch声明之前。循环char isPressed = false;之前while

瓦尔特

于 2014-03-05T20:24:29.287 回答
0
__delay_ms(250); <-- too small delay

当您缓慢按下按钮时,循环可能会旋转数次。尝试将其增加到 1000 毫秒。

更新

您应该在禁用 WDT(看门狗定时器)的情况下运行 PIC,否则它将在几秒钟内重置 pic。这与您的观察相似。您可以在 main 函数开始时闪烁 LED 以检查是否发生这种情况,或者您可以初始化unsigned char state = 1;并查看其行为。

尝试这个 __CONFIG(MCLRE_ON & CP_OFF & OSC_IntRC & WDT_OFF);

于 2014-03-05T04:37:42.017 回答