C 为什么此状态机不保持其状态?

C 为什么此状态机不保持其状态?,c,microcontroller,pic,microchip,xc8,C,Microcontroller,Pic,Microchip,Xc8,嘿,你在这儿 在下面的代码中,我有一个简单的状态机,它可以更改某些外部照明设备的操作(如注释所示)。通过按下连接到GP1的按钮可更改状态。连接到GP1的电路是一个比较器去抖动电路,它将VDD与0.6VDD进行比较(我也尝试过RC/二极管/施密特触发电路),然后强制信号LO。在示波器上,当按钮快速启动时,我们看到一个干净的方波 PIC10F200的电流(和不需要的)行为如下: 按下开关(状态=0) 状态机变量增量(状态=1) 照明转到案例1并打开 照明至少保持打开一秒钟 灯光关闭 系统保持此状态,

嘿,你在这儿

在下面的代码中,我有一个简单的状态机,它可以更改某些外部照明设备的操作(如注释所示)。通过按下连接到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++;
            }
        }
    }
    
    更新:由于我试图用此代码/系统实现的目标似乎有点混乱,让我们提供完整的上下文。该微控制器是电致发光(EL)导线驱动器整体电路板设计的一部分。miconcontroller通过将
    GP0
    连接到驱动器IC的
    EN
    端口,简单地控制驱动器电路是否启用系统有四种操作模式,导线持续接通,导线闪烁,导线闪烁更快,并且每当检测到低频节拍时(系统中的另一个电路),导线闪烁这些操作模式的转换由安装在PCB上的按钮(瞬时打开)开关控制。这要求上述代码中的
    状态在按钮启动之间保持稳定。它目前不这样做,其行为如本文原始部分所述。正如问题标题所述,为什么
    状态当前不稳定,我如何使其稳定?

    更新(2014-03-08):解决方案

    假设GP0是输出,GP2是T0CKI,并且您有一个开关在启动时将信号驱动到LO,则需要设置以下设置

    TRIS = 0b111110;
    OPTION = 0b11101111;
    
    选项的位0-3是否真正重要取决于判断调用以及您是否选择使用WDT模块

    此外,按钮释放检测的实现是一个简单的计数器机制,在计数期间的任何点GP2为LO时重置

    if (TMR0 > 0)
    {
        while (count < 20)
        {
            if (!GPIObits.GP2) count = 0;
            __delay_ms(10);
            count++;
        }
        TMR0 = 0;
        state++;
    }
    
    if(TMR0>0)
    {
    同时(计数<20)
    {
    如果(!GPIObits.GP2)计数=0;
    __延迟时间(10);
    计数++;
    }
    TMR0=0;
    状态++;
    }
    
    \u延迟\u毫秒(250) 移动你的

    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;}
    
    开关
    语句之前
    charispressed=false
    while
    循环之前


    valter

    您遇到了硬件/软件设计问题

  • 当你的程序在延迟循环中时,你的按键不在 检查
  • 您只检查按键事件,但也必须检查按键 放松
  • 我的目的是,你可以使用GP2(T0CKI)引脚代替GP1键按钮。如果用作计数器TMR0输入,则该引脚具有施密特触发器输入。之后,将MCPU TMR0配置为GP2(T0CKI)引脚上带有外部时钟的计数器。您还必须将T0SE位设置为配置计数器,该计数器将在T0CKI引脚的高-低转换时递增。 在程序中,在任何循环后检查TMR0内容,如果大于0,则按键。
    等待几毫秒,检查按键是否已松开如果已松开,则增加
    状态变量并清除TMR0内容。

    那么gp1是按钮,gp0是led,gp2是什么?还有,按钮是如何工作的?一次点击(按下并释放)给出1,另一次为0?是的,GP1连接到按钮,GP0连接到LED/EL线驱动器EN端口(最终),GP2是来自低频检测电路的输入(低音来自…大声音乐),该电路尚未连接,因为我甚至无法使状态机正常工作。这个按钮是一个瞬间打开的按钮,就像你在最便宜的电子产品中找到的最基本的那种。所以,当它被按下时,触点被连接,VDD通过比较器电路(LM324N运算放大器)。你为什么要用“状态”来做这件事。你想要实现的事情很容易。您不需要使代码复杂化。使用
    状态
    ,我试图简单地在代码中标记的设备的操作模式之间切换。以我目前对PIC、XC8的工作原理和C语言的了解,这是完成这项任务的最简单方法。除了汇编中的任何解决方案,我完全愿意尝试不同的方法,因为改变语言不仅不能解决问题,还引入了不必要的实现和支持复杂性。您描述的是一种状态。当按下按钮时。在将来,你可能想添加其他东西,但现在它是一个状态
    如果(!GPIObits.GP1){GPIObits.GP0=1;uu delay_ms(1000);GPIObits.GP0=0;}
    我之前尝试过这个方法,系统仍然以相同的方式运行,即使我将其设置为任意大的值,如。。。10000毫秒,还是一样,它亮起,持续一秒钟,然后它关闭并保持这种状态…我怀疑如果图片在亮起时被重置。你怎么给灯供电。该灯是否耗电过多或出现故障或干扰,或者是否有继电器?你用的是好的PSU吗?好的,为了测试,我用的是LED。。。这应该很吸引人。。。非常小的
    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;}