C 对中断服务例程切换的易失性变量的更改未反映在main()中

C 对中断服务例程切换的易失性变量的更改未反映在main()中,c,interrupt,volatile,C,Interrupt,Volatile,我有一个真正的树桩,我已经被困了一段时间了。我正在用C语言编程PIC16F15376微控制器Xpress板 我将名为buttonintation的易失性变量初始化为0。当中断服务例程发生时,调用按钮设置(1),有效地设置按钮设置=1。[注意:我也尝试过直接切换buttonIntention变量,没有get或set函数。]在main()中,持续轮询的while(1)检查ISR是否已关闭(这将设置buttonIntention=1),如果ISR已关闭,TESTPIN设置得很高,我可以在我的o型示波器

我有一个真正的树桩,我已经被困了一段时间了。我正在用C语言编程PIC16F15376微控制器Xpress板

我将名为
buttonintation
的易失性变量初始化为0。当中断服务例程发生时,调用
按钮设置(1)
,有效地设置
按钮设置=1
。[注意:我也尝试过直接切换
buttonIntention
变量,没有get或set函数。]在
main()
中,持续轮询的
while(1)
检查ISR是否已关闭(这将设置
buttonIntention=1
),如果ISR已关闭,
TESTPIN
设置得很高,我可以在我的o型示波器上查看它

我已经确定,当我按下按钮时,ISR确实会开火<然后,代码>按钮项在ISR中设置为1,因为我尝试的ISR结束时注释掉的代码工作正常

但是,我的
if(buttonintation)
在我的
中,而
main()中的(1)
实际上从未看到buttonintation设置为1。我认为将此变量设置为
volatile
可以解决此问题,因为它在ISR和
main()
之间共享,并且我认为在我的8位微控制器上使用
uint8\u t
类型可以解决我读过但并不真正理解的任何“原子”问题。。。但是,仍然有一些错误,if语句从未看到1

有什么想法吗

这是我的密码:

// CONFIG1
#pragma config FEXTOSC = OFF    // External Oscillator mode selection bits->Oscillator not enabled
#pragma config RSTOSC = HFINT32    // Power-up default value for COSC bits->HFINTOSC with OSCFRQ= 32 MHz and CDIV = 1:1
#pragma config CLKOUTEN = OFF    // Clock Out Enable bit->CLKOUT function is disabled; i/o or oscillator function on OSC2
#pragma config CSWEN = ON    // Clock Switch Enable bit->Writing to NOSC and NDIV is allowed
#pragma config FCMEN = ON    // Fail-Safe Clock Monitor Enable bit->FSCM timer enabled

// CONFIG2
#pragma config MCLRE = ON    // Master Clear Enable bit->MCLR pin is Master Clear function
#pragma config PWRTE = OFF    // Power-up Timer Enable bit->PWRT disabled
#pragma config LPBOREN = OFF    // Low-Power BOR enable bit->ULPBOR disabled
#pragma config BOREN = ON    // Brown-out reset enable bits->Brown-out Reset Enabled, SBOREN bit is ignored
#pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices
#pragma config ZCD = ON    // Zero-cross detect disable->Zero-cross detect circuit is disabled at POR.
#pragma config PPS1WAY = ON    // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software
#pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable bit->Stack Overflow or Underflow will cause a reset

// CONFIG3
#pragma config WDTCPS = WDTCPS_31    // WDT Period Select bits->Divider ratio 1:65536; software control of WDTPS
#pragma config WDTE = OFF    // WDT operating mode->WDT Disabled, SWDTEN is ignored
#pragma config WDTCWS = WDTCWS_7    // WDT Window Select bits->window always open (100%); software control; keyed access not required
#pragma config WDTCCS = SC    // WDT input clock selector->Software Control

// CONFIG4
#pragma config WRTC = OFF    // UserNVM self-write protection bits->Write protection off
//#pragma config SCANE = available    // Scanner Enable bit->Scanner module is available for use
#pragma config LVP = ON    // Low Voltage Programming Enable bit->Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.

// CONFIG5
#pragma config CP = OFF    // UserNVM Program memory code protection bit->UserNVM code protection disabled
//#pragma config CPD = OFF    // DataNVM code protection bit->DataNVM code protection disabled

// ==========================================================================
// Import Header Files
// ==========================================================================

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xc.h>
#include <math.h>

// ==========================================================================
// Define statements
// ==========================================================================

// Inputs from buttons
#define startButton         PORTCbits.RC4
#define profileButton       PORTCbits.RC5
#define incrementButton     PORTCbits.RC6
#define decrementButton     PORTCbits.RC7

#define TESTPIN LATCbits.LATC0

// ==========================================================================
// Global Variables
// ==========================================================================

// ISR Toggle Variables (MUST be declared volatile)
volatile uint8_t buttonIntention = 0;

// ==========================================================================
// General Configuration
// ==========================================================================

// --- --- --- --- --- --- ---
// Configure Inputs and Outputs
// --- --- --- --- --- --- ---
void config_IO(void) {
    // --- Set output for 5 gate drivers and LCD rs and en: ---
    TRISA = 0; // Set all Port A I/O to output
    LATA = 0; // Set all Port A outputs to LOW/0
    ANSELA = 0; // Turn Port A analog off (Digital only)

    // --- Set output for  LCD data: ---
    TRISB = 0; // Set all Port B I/O to output
    LATB = 0; // Set all Port B outputs to LOW/0
    ANSELB = 0; // Turn Port B analog off (Digital only)

    // --- Set input from buttons: ---
    //TRISC = 0b11111000;  // Set Port C 3-7 to input for the buttons
    TRISC = 0xF8;  // Set Port C 3-7 to input for the buttons
    LATC = 0;  // Set all Port C outputs LOW
    ANSELC = 0;  // Turn Port C analog off (Digital only)
}

// --- --- --- --- --- --- ---
// Configure Change Notification for Button Interrupts
// --- --- --- --- --- --- ---
void config_CN(void){

    //Clear Interrupt flag    
    IOCIF = 0; 
    // Clear all of Port C 0-7 interrupt flags
    IOCCF = 0x00;

    // Enable interrupts on Positive Edge of the buttons RC3-RC7
    IOCCP3 = 1;
    IOCCP4 = 1;
    IOCCP5 = 1;
    IOCCP6 = 1;
    IOCCP7 = 1;        

    IOCIE = 1; //Enable Interrupt
}

// --- --- --- --- --- --- ---
// Configure the oscillator: 
// --- --- --- --- --- --- ---

void config_OSC (void) { 
    // Clear registers
    OSCCON1 = 0x00;
    OSCCON2 = 0x00;
    OSCCON3 = 0x00;

    // OSCCON1:
    // Use High Freq. Internal Oscillator (HFINTOSC @ 1 - 32 MHz)
    //OSCCON1bits.NOSC = 0b110;
    OSCCON1bits.NOSC = 0x6;

    // OSCFRQ: 
    // Configure HFINTOSC to 32 MHz
    // OSCFRQbits.HFFRQ = 0b110;
    OSCFRQbits.HFFRQ = 0x6;    

    // Divide clock by 1
    //OSCCON1bits.NDIV = 0b0000;
    OSCCON1bits.NDIV = 0x0; 
}

// ==========================================================================
// Button Function
// ==========================================================================

void buttonSet(uint8_t setter){
    buttonIntention = setter;
}
uint8_t buttonGet(void){
    return buttonIntention;
}

// ==========================================================================
// Interrupt service routine
// ==========================================================================

void __interrupt() isr(void)
{    
    // If button is pressed...
    if(IOCIF == 1 && buttonIntention == 0) {
        //buttonIntention = 1; // Change state to indicate that button was somehow pressed intentionally or unintentionally
        //OR
        buttonSet(1);     
        IOCIF = 0; //Clear Interrupt flag
    }
//if(buttonIntention){
//TESTPIN = 1;
//}
}

// ========================================================================== 
// Main function
// ==========================================================================

int main(void) {
    WDTCON0bits.SWDTEN = 0x0; // Ensure Watchdog Timer is totally disabled

    // Register 10-1 INTCON
    INTCONbits.PEIE = 1; // Enable peripheral interrupt
    INTCONbits.GIE = 1; // Enable global interrupt  

    // --- Call configuration functions: ---    
    config_IO();
    config_OSC();
    config_CN();

    // --- Loop forever: ---
    while (1) {
        if(buttonGet()){
            TESTPIN = 1;              
        }
    }
    return 0;
}
//配置1
#pragma config FEXTOSC=OFF//外部振荡器模式选择位->振荡器未启用
#pragma config RSTOSC=HFINT32//COSC位通电默认值->带OSCFRQ=32 MHz和CDIV=1:1的HFINTOSC
#pragma config CLKOUTEN=OFF//Clock Out Enable bit->CLKOUT函数被禁用;OSC2上的i/o或振荡器功能
#pragma config CSWEN=ON//时钟开关启用位->允许写入NOSC和NDIV
#pragma config FCMEN=ON//Fail-Safe Clock Monitor Enable bit->FSCM timer enabled
//配置2
#pragma config MCLRE=ON//Master Clear启用位->MCLR引脚为Master Clear功能
#pragma config PWRTE=OFF//通电定时器启用位->禁用PWRT
#pragma config LPBOREN=OFF//低功耗BOR启用位->禁用ULPBOR
#pragma config BOREN=ON//Brown out reset enable bit->Brown out reset Enabled,SBOREN位被忽略
#pragma config BORV=LO//Brown out Reset VOLVE Selection->Brown out Reset VOLVE(VBOR)在左前设置为1.9V,在F设备上设置为2.45V
#pragma config ZCD=ON//Zero cross detect disable->Zero cross detect circuit在POR被禁用。
#pragma config PPS1WAY=ON//Peripheral Pin Select one-way control->PPSLOCK位只能在软件中清除和设置一次
#pragma config STVREN=ON//堆栈溢出/下溢重置启用位->堆栈溢出或下溢将导致重置
//配置3
#pragma config WDTCPS=WDTCPS_31//WDT周期选择位->分频比1:65536;WDTPS的软件控制
#pragma config WDTE=OFF//WDT操作模式->禁用WDT,忽略SWDTEN
#pragma config WDTCWS=WDTCWS_7//WDT窗口选择位->窗口始终打开(100%);软件控制;不需要密钥访问
#pragma config WDTCCS=SC//WDT输入时钟选择器->软件控制
//配置4
#pragma config WRTC=OFF//UserNVM自写保护位->写保护关闭
//#pragma config SCANE=可用//扫描仪启用位->扫描仪模块可供使用
#pragma config LVP=ON//低压编程启用位->低压编程启用。MCLR/Vpp引脚功能为MCLR。
//配置5
#pragma config CP=OFF//UserNVM程序内存代码保护位->禁用UserNVM代码保护
//#pragma config CPD=OFF//DataNVM代码保护位->禁用DataNVM代码保护
// ==========================================================================
//导入头文件
// ==========================================================================
#包括
#包括
#包括
#包括
#包括
// ==========================================================================
//定义语句
// ==========================================================================
//来自按钮的输入
#定义开始按钮PORTCbits.RC4
#定义profileButton端口cbits.RC5
#定义递增按钮端口cbits.RC6
#定义递减按钮PORTCbits.RC7
#定义TESTPIN LATCbits.LATC0
// ==========================================================================
//全局变量
// ==========================================================================
//ISR切换变量(必须声明为volatile)
易失性uint8\u t按钮项=0;
// ==========================================================================
//一般配置
// ==========================================================================
// --- --- --- --- --- --- ---
//配置输入和输出
// --- --- --- --- --- --- ---
无效配置IO(无效){
//---为5个门驱动器和LCD rs和en设置输出:---
TRISA=0;//将所有端口A I/O设置为输出
LATA=0;//将所有端口A输出设置为低/0
ANSELA=0;//关闭端口A模拟(仅数字)
//---设置LCD数据的输出:---
TRISB=0;//将所有端口B I/O设置为输出
LATB=0;//将所有端口B输出设置为低/0
ANSELB=0;//关闭端口B模拟(仅数字)
//---从按钮设置输入:---
//TRISC=0b11111000;//将端口C 3-7设置为按钮的输入
TRISC=0xF8;//将端口C3-7设置为按钮的输入
LATC=0;//将所有端口C输出设置为低
ANSELC=0;//关闭端口C模拟(仅数字)
}
// --- --- --- --- --- --- ---
//为按钮中断配置更改通知
// --- --- --- --- --- --- ---
无效配置(无效){
//清除中断标志
IOCIF