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