Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 图中的去盎司按钮_C_Interrupt_Pic - Fatal编程技术网

C 图中的去盎司按钮

C 图中的去盎司按钮,c,interrupt,pic,C,Interrupt,Pic,我是PIC mcu的新手。我使用pic12f675 MPLAB和XC8制作LED多闪烁模式。 我对按钮也有问题(在检查后称之为Bounce and Debounce)。 有时当我按下按钮时,它会按顺序如1->2->3->4->5,但有时它会跳转如1->3->4->6等 请建议我如何在pic mcu中去抖动或以其他方式解决我的问题 多谢各位。各位 (PS.I连接带10K电阻器的按钮) 我的代码在下面 #include <xc.h> #pragma config FOSC

我是PIC mcu的新手。我使用pic12f675 MPLAB和XC8制作LED多闪烁模式。 我对按钮也有问题(在检查后称之为Bounce and Debounce)。 有时当我按下按钮时,它会按顺序如1->2->3->4->5,但有时它会跳转如1->3->4->6等

请建议我如何在pic mcu中去抖动或以其他方式解决我的问题

多谢各位。各位

(PS.I连接带10K电阻器的按钮)

我的代码在下面

    #include <xc.h>
    #pragma config FOSC=INTRCIO,WDTE=OFF,MCLRE=OFF,BOREN=OFF
    #define _XTAL_FREQ 4000000
    
    int cnt = 0;
    int k = 0;

void __interrupt() MyISR(void){
   
    if(INTCONbits.INTF)  //If External Edge INT Interrupt
    {
        
        cnt++;
        INTCONbits.GIE = 0;
            
        INTCONbits.INTF = 0;    // Clear the interrupt
        
        INTCONbits.GPIF = 0;
        
        
        if( cnt > 6 ){
            cnt = 1;
            
        }
        
    }
    
    INTCONbits.GIE = 1;
    
}

void main(void) {
    ANSEL = 0;
    CMCON = 0b00000111; //turns comparators off
    TRISIO = 0b00000100;
    GPIO   = 0;
    
    TRISIO2 = 1;                // Make GP2 pin as input
    
    INTCONbits.GIE = 1;
    INTCONbits.INTE = 1;
    INTCONbits.GPIF = 1;
    INTCONbits.INTF = 0;

    
    OPTION_REG = 0b01000000;   

    while(1){
     
        if( cnt == 1 ){
            GP0 = 1;
            GP5 = 1;
        }else if( cnt == 2 ){
            
            for(k=0;k<30;k++){
                GP5 = 1;
                GP0 = 1;
            }
            k=0;
            while(k<3){
                GP5 = ~GP5;
                __delay_ms(70);
                GP0 = ~GP0;
                __delay_ms(70);
                k++;
            }
        }else if( cnt == 3 ){
            for(k=0;k<5;k++){
                GP5 = 1;
                GP0 = 1;
                __delay_ms(70);
                GP5 = 0;
                GP0 = 0;
                __delay_ms(70);
            }
            GP5 = 0;
            GP0 = 0;
            __delay_ms(1200);
            
            
        }else if( cnt == 4 ){
            
            for(k=0;k<3;k++){
                GP0 = 1;
                __delay_ms(50);
                GP0 = 0;
                __delay_ms(50);
            }
            
            
            for(k=0;k<3;k++){
                GP5 = 1;
                __delay_ms(50);
                GP5 = 0; 
                __delay_ms(50);
            }
            
            
        }else if( cnt == 5 ){
            
            GP0 = 1;
            GP5 = 1;
            for(k=0;k<3;k++){
                GP5 = 1;
                __delay_ms(50);
                GP5 = 0; 
                __delay_ms(50);
            }
            GP0 = 1;
            GP5 = 1;
            for(k=0;k<3;k++){
                GP0 = 1;
                __delay_ms(50);
                GP0 = 0; 
                __delay_ms(50);
            }
            
        }else if( cnt == 6 ){
            
            GP0 = 1;
            GP5 = 1;
            __delay_ms(20);
            GP0 = 0;
            GP5 = 0;
            __delay_ms(3000);
            
        }
        
    }
    return;
}
#包括
#pragma config FOSC=INTRCIO,WDTE=OFF,MCLRE=OFF,BOREN=OFF
#定义额外频率4000000
int-cnt=0;
int k=0;
void\uu中断()MyISR(void){
if(INTCONbits.INTF)//如果外部边缘INT中断
{
cnt++;
INTCONbits.GIE=0;
INTCONbits.INTF=0;//清除中断
INTCONbits.GPIF=0;
如果(碳纳米管>6){
cnt=1;
}
}
INTCONbits.GIE=1;
}
真空总管(真空){
ANSEL=0;
CMCON=0b00000111;//关闭比较器
TRISIO=0B000000100;
GPIO=0;
TRISIO2=1;//将GP2引脚作为输入
INTCONbits.GIE=1;
INTCONbits.INTE=1;
INTCONbits.GPIF=1;
INTCONbits.INTF=0;
选项_REG=0b01000000;
而(1){
如果(cnt==1){
GP0=1;
GP5=1;
}else如果(cnt==2){

对于(k=0;k我重写了您的代码,并在MPLAB模拟中对其进行了测试。它按预期工作。它按升序更改模式,然后在所选模式下运行,直到再次按下更改按钮,然后更改为下一个模式。您可以根据需要添加更多工作模式,也可以修改GPIOs闪烁的方式。没有延迟(),这就是为什么延迟在不消耗CPU的情况下运行。请在实际电路中进行测试并给我反馈

/*
 * File:   main.c
 * Author: kozmotronik
 *
 */

#define _XTAL_FREQ 4000000
#include <xc.h>
#include <stdint.h>
#include <stdbool.h>

#pragma config FOSC=INTRCIO,WDTE=OFF,MCLRE=OFF,BOREN=OFF

// Work mode definitions
#define MODE_IDLE   0
#define MODE_OFF    1
#define MODE_ON     2
#define MODE_SLOW   3
#define MODE_FAST   4
#define MODE_CANCEL 5
#define LAST_MODE   MODE_FAST

// Button states
#define BUTTON_IDLE             0
#define BUTTON_PRESS_DETECTED   1
#define BUTTON_DEBOUNCING       2
#define BUTTON_PRESS_CONFIRMED  3

#define SYSTEM_CLOCK_MS 1
#define SYSTEM_CLOCK_uS (SYSTEM_CLOCK_MS * 1000)
#define _XTAL_FREQ_MHZ (_XTAL_FREQ / 1000000) // Oscillator freq in MHz
#define TMR0_RELOAD_VALUE 256 - ( (SYSTEM_CLOCK_uS * _XTAL_FREQ_MHZ) / (8 * 4) ) // Result must be 131
#define MS_TO_TICKS(msTime) (msTime / SYSTEM_CLOCK_MS)

typedef struct{
    unsigned int start;
    unsigned int ticks;
} time_t;

char mode = MODE_IDLE;
char lastMode = MODE_OFF;
char buttonState = BUTTON_IDLE;
char k = 0;
unsigned int systemTick = 0; // Time value count by Timer0


void __interrupt() MyISR(void){
   
    if(INTCONbits.INTF)  //If External Edge INT Interrupt
    {
        INTCONbits.INTF = 0;    // Clear the interrupt
        buttonState = BUTTON_PRESS_DETECTED; // Signal the detected press
    }
    // Check for 1 ms periodic interrupt for system clock
    else if(INTCONbits.T0IF){
        INTCONbits.T0IF = 0; // clear flag
        TMR0 = TMR0_RELOAD_VALUE; // Reload the calculated value for 1 ms
        systemTick++;
    }
}

// Setup Timer0 for 1ms interrupt
void setupTimer0(){
#define PRESCALER_VALUE 2
#define PRESCALER_MASK ~7
    OPTION_REG &= PRESCALER_MASK; // Clear prescaler bits
    OPTION_REG |= PRESCALER_VALUE; // Set prescaler value for 1:8
    OPTION_REGbits.PSA = 0; // Assign prescaler to Tim0
    OPTION_REGbits.T0CS = 0; // Set internal oscillator as clock source
    TMR0 = TMR0_RELOAD_VALUE;
    INTCONbits.T0IF = 0;
    INTCONbits.T0IE = 1; // Enable Timer0 interrupt
}

// Get count atomically
unsigned int getTickCount(){
    unsigned int count;
    di(); // disable interrupts
    count = systemTick;
    ei(); // enable interrupts again
    return count;
}

void performMode(){
    static time_t modeDelay;
    static char slowModeState = 1;
    static char fastModeState = 1;
    
    switch(mode){
        case MODE_OFF:
            // Always must save the current mode before put it into the IDLE
            lastMode = mode; // We have to save the last mode first then put it into the IDLE state
            mode = MODE_IDLE; // The rollover bug caused by here since we haven't save the last mode before put it into the IDLE state
            GP0 = 0; GP5 = 0;
            break;
            
        case MODE_ON:
            GP0 = 1; GP5 = 1;
            break;
            
        case MODE_SLOW:
            if(slowModeState == 1){
                GP0 = 1; GP5 = 1;
                modeDelay.ticks = MS_TO_TICKS(100);
                modeDelay.start = getTickCount();
                slowModeState = 2; // Proceed the next step
            }
            else if(slowModeState == 2){
                if( !((getTickCount() - modeDelay.start) >= modeDelay.ticks) ){
                    // Delay not expired yet
                    return;
                }
                GP0 = ~GP0; GP5 = ~GP5; // Toggle
                // Reload the start time
                modeDelay.start = getTickCount();
            }
            break;
            
        case MODE_FAST:
            if(fastModeState == 1){
                GP0 = 1; GP5 = 1;
                modeDelay.ticks = MS_TO_TICKS(50);
                modeDelay.start = getTickCount();
                fastModeState = 2; // Proceed the next step
            }
            else if(fastModeState == 2){
                if( !((getTickCount() - modeDelay.start) >= modeDelay.ticks) ){
                    // Delay not expired yet
                    return;
                }
                // Delay time expired, proceed toggle
                GP0 = ~GP0; GP5 = ~GP5; // Toggle
                // Reload the start time
                modeDelay.start = getTickCount();
            }
            break;
            
        case MODE_CANCEL:
            // Cancel the current running mode, reset everything
            modeDelay.start = 0;
            modeDelay.ticks = 0;
            slowModeState = 1;
            fastModeState = 1;
            // Also reset the outputs
            GP0 = 0; GP5 = 0;
            break;
            
        default:
            mode = MODE_IDLE;
    }
}

void checkButton(){
#define DEBOUNCE_DELAY_MS 100u // Debounce delay is 100 ms
    static time_t debounceTimer;
    
    switch(buttonState){
        case BUTTON_IDLE:
            break;
            
        case BUTTON_PRESS_DETECTED:
            debounceTimer.ticks = MS_TO_TICKS(DEBOUNCE_DELAY_MS);
            debounceTimer.start = getTickCount();
            buttonState = BUTTON_DEBOUNCING;
            break;
            
        case BUTTON_DEBOUNCING:
            if( !((getTickCount() - debounceTimer.start) >= debounceTimer.ticks) ){
                // Debounce time has not expired yet
                return;
            }
            // Debounce time has expired so check the button last time to confirm if it is still pressed
            if(GPIObits.GP2 != 1){
                // Not stable yet, debounce again
                buttonState = BUTTON_PRESS_DETECTED;
            }
            // Button press is stable, confirm it
            buttonState = BUTTON_PRESS_CONFIRMED;
            break;
            
        case BUTTON_PRESS_CONFIRMED:
            buttonState = BUTTON_IDLE; // Change state so that it can process a new button press
            if(mode != MODE_IDLE && mode != MODE_OFF){
                // Cancel the running mode first
                lastMode = mode; // save the last mode
                mode = MODE_CANCEL; // purge the current one
                performMode();
            }
            mode = lastMode + 1; // Switch to next mode
            if(mode > LAST_MODE){
                // Rewind mode to the beginning which is MODE_OFF
                mode = MODE_OFF;
            }
            break;
            
        default:
            buttonState = BUTTON_IDLE;
    }
}


void main(void) {
    ANSEL = 0;
    CMCON = 0b00000111; //turns comparators off
    TRISIO = 0b00000100;
    GPIO   = 0;
    
    TRISIO2 = 1;                // Make GP2 pin as input
    
    INTCONbits.INTF = 0;
    INTCONbits.INTE = 1;
    INTCONbits.GIE = 1;

    OPTION_REG = 0b01000000; // Rising edge interrupt
    
    setupTimer0();

    // Super loop
    while(1){
        
        // Task 1: Button check
        if(buttonState != BUTTON_IDLE){
            checkButton();
        }
        
        // Task 2: Mode check
        else if(mode != MODE_IDLE){
            performMode();
        }
        
    }
    return;
}
/*
*文件:main.c
*作者:科兹莫特罗尼克
*
*/
#定义额外频率4000000
#包括
#包括
#包括
#pragma config FOSC=INTRCIO,WDTE=OFF,MCLRE=OFF,BOREN=OFF
//工作模式定义
#定义模式\u空闲0
#定义模式_OFF 1
#在2上定义模式_
#定义模式3
#定义模式\u FAST 4
#定义模式\u取消5
#定义最后一个\u模式\u快速
//按钮状态
#定义按钮\u空闲0
#定义按钮\u按\u检测到1
#定义按钮_去抖动2
#定义按钮\u按\u确认3
#定义系统时钟1
#定义系统时钟(系统时钟*1000)
#定义_XTAL_FREQ_MHZ(_XTAL_FREQ/1000000)//振荡器频率(以MHZ为单位)
#定义TMR0_RELOAD_值256-((系统时钟频率*)/(8*4))//结果必须为131
#定义毫秒到毫秒刻度(毫秒时间)(毫秒时间/系统时钟)
类型定义结构{
无符号整数起始;
无符号整数刻度;
}时间;
char mode=mode_IDLE;
char lastMode=模式\关闭;
char buttonState=按钮空闲;
chark=0;
unsigned int systemTick=0;//按Timer0计算的时间值
void\uu中断()MyISR(void){
if(INTCONbits.INTF)//如果外部边缘INT中断
{
INTCONbits.INTF=0;//清除中断
buttonState=BUTTON\u PRESS\u DETECTED;//向检测到的按下发送信号
}
//检查系统时钟的1毫秒周期中断
else if(INTCONbits.T0IF){
INTCONbits.T0IF=0;//清除标志
TMR0=TMR0_RELOAD_VALUE;//重新加载计算值1毫秒
systemTick++;
}
}
//1ms中断的设置定时器0
void setupTimer0(){
#定义预分频器_值2
#定义预分频器\u掩码~7
选项\u REG&=预分频器\u掩码;//清除预分频器位
选项_REG |=预分频器_值;//将预分频器值设置为1:8
选项_REGbits.PSA=0;//将预分频器分配给Tim0
选项_REGbits.T0CS=0;//将内部振荡器设置为时钟源
TMR0=TMR0_重新加载_值;
INTCONbits.T0IF=0;
INTCONbits.T0IE=1;//启用定时器0中断
}
//原子计数
无符号int getTickCount(){
无符号整数计数;
di();//禁用中断
计数=系统滴答;
ei();//再次启用中断
返回计数;
}
void performMode(){
静态时间延迟;
静态字符慢模式=1;
静态字符数=1;
开关(模式){
案例模式_关闭:
//在将当前模式置于空闲模式之前,必须始终保存当前模式
lastMode=mode;//我们必须先保存最后一个模式,然后将其置于空闲状态
mode=mode_IDLE;//由于我们在将最后一个模式置于空闲状态之前没有保存它,因此此处导致的滚动错误
GP0=0;GP5=0;
打破
案例模式打开:
GP0=1;GP5=1;
打破
案例模式_慢:
if(slowModeState==1){
GP0=1;GP5=1;
modeDelay.ticks=毫秒到毫秒刻度(100);
modeDelay.start=getTickCount();
slowModeState=2;//继续下一步
}
else if(slowModeState==2){
if(!((getTickCount()-modeDelay.start)>=modeDelay.ticks)){
//延迟尚未到期
返回;
}
GP0=~GP0;GP5=~GP5;//切换
//重新加载开始时间
modeDelay.start=getTickCount();
}
打破
案例模式快速:
如果(FastModerate==1){
GP0=1;GP5=1;
modeDelay.ticks=毫秒到毫秒刻度(50);
modeDelay.start=getTickCount();
FastModerate=2;//继续下一步
}
否则如果(FastModerate==2){
if(!((getTickCount()-modeDelay.start)>=modeDelay.ticks)){
//延迟尚未到期
返回;
}
//延迟时间到期,继续切换
GP0=~GP0;