我需要帮助我有这个基本的基本程序,根据我推动的开关,按顺序使用LED,我想知道的是:如何中断一个(或停止它)并运行另一个顺序,当我切换其他开关并运行新的顺序而不是之前的顺序时,我想知道其他需要中止操作的程序是如何做的,因为它将处于延迟和填充的“循环”中,我想这是一个如果每个引导和关闭的线之间都会这样做,但我不认为这是正确/有效的方式..谢谢!
#include <16f876.h>
#use delay(clock=4M)
#fuses XT,NOWDT
#use standard_io(A)
#use standard_io(B)
int16 t0=2000;
int16 t1=1000;
int16 t2=1000;
int16 t3=500;
void main(){
output_b(0b00000000);
while(TRUE){
if(input(PIN_A0)==0){
output_b(0b00000000);
output_b(0b00011000);
delay_ms(t0);
output_b(0b00100100);
delay_ms(t0);
output_b(0b01000010);
delay_ms(t0);
output_b(0b10000001);
delay_ms(t0);
}
if(input(PIN_A1)==0){
output_b(0b00000000);
output_b(0b00000001);
delay_ms(t1);
output_b(0b00000011);
delay_ms(t1);
output_b(0b00000111);
delay_ms(t1);
output_b(0b00001111);
delay_ms(t1);
output_b(0b00011111);
delay_ms(t1);
output_b(0b00111111);
delay_ms(t1);
output_b(0b01111111);
delay_ms(t1);
output_b(0b11111111);
delay_ms(t1);
}
if(input(PIN_A2)==0){
output_b(0b10000000);
delay_ms(t2);
output_b(0b11000000);
delay_ms(t2);
output_b(0b11100000);
delay_ms(t2);
output_b(0b11110000);
delay_ms(t2);
output_b(0b11111000);
delay_ms(t2);
output_b(0b11111100);
delay_ms(t2);
output_b(0b11111110);
delay_ms(t2);
output_b(0b11111111);
delay_ms(t2);
}
if(input(PIN_A3)==0){
output_b(0b00000000);
output_b(0b00000001);
delay_ms(t3);
output_b(0b00000000);
delay_ms(t3);
output_b(0b00000011);
delay_ms(t3);
output_b(0b00000000);
delay_ms(t3);
output_b(0b00000111);
delay_ms(t3);
output_b(0b00000000);
delay_ms(t3);
output_b(0b00001111);
delay_ms(t3);
output_b(0b00000000);
delay_ms(t3);
output_b(0b00011111);
delay_ms(t3);
output_b(0b00000000);
delay_ms(t3);
output_b(0b00111111);
delay_ms(t3);
output_b(0b00000000);
delay_ms(t3);
output_b(0b01111111);
delay_ms(t3);
output_b(0b00000000);
delay_ms(t3);
output_b(0b11111111);
delay_ms(t3);
}
}
}
答案 0 :(得分:1)
您可以编写自己的delay_ms函数,如下所示:
bool my_delay_ms(int mstime) {
int current = 0;
while (current < mstime) {
delay_ms(10);
current += 10;
if (something?) {
return true;
}
}
return false;
}
然后用if (my_delay_ms(t0)) continue;
替换每个delay_ms。
您可以将10更改为您想要轮询中断信号的频率。条件检测到中断信号,continue
允许你的while循环跳转到下一个循环,以便在适当的时候改变顺序。
答案 1 :(得分:1)
您可以设置一个触发每毫秒的计时器,然后将代码重写为状态机。这样你就不会在延迟例程中浪费cpu周期,并且你能够立即响应按钮按下,至少在一毫秒内响应,这对用户来说是即时的。
状态机跟踪变量。数字表示它所处的状态。每次执行状态时,状态可能会改变。更改的状态在下次定时器触发时执行。每个触发器还会检查按钮/去抖等。
确保您的代码在计时器周期内运行,因此请不要使用任何延迟,而是使用状态机执行延迟,或者如果您需要不同的分辨率/时间,请使用其他计时器。
我将由你来设置定时器和中断寄存器。
/* global variables */
int state = 0;
unsigned char delaycnt = 0;
char millisecond_flag = 0;
void DoStateMachine()
{
switch( state )
{
case 100:
output_b(0b00000000);
output_b(0b00011000);
state++;
delaycnt = 10;
break;
case 101:
delaycnt--;
if(delaycnt == 0) state = 102;
break;
case 200:
output_b(0b00000000);
output_b(0b00000001);
state++;
delaycnt = 10;
break;
case 201:
delaycnt--;
if(delaycnt == 0) state = 202;
break;
default:
state = 0; // do nothing
break;
}
}
void CheckButtons()
{
// Do button debounce here
if( BUTTON1 == 1)
state = 100;
if( BUTTON2 == 1)
state = 200;
}
void main()
{
//Setup timer here
while(1)
{
if( millisecond_flag == 1)
{
CheckButtons();
DoStateMachine();
millisecond_flag = 0;
}
//sleep device?
}
}
// Handle interrupt
void interrupt ISR()
{
if( TMR1IF == 1)
{
millisecond_flag = 1;
TMR1IF = 0;
}
}