首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用atmega16和外部中断的七段项目

使用atmega16和外部中断的七段项目
EN

Stack Overflow用户
提问于 2022-04-19 22:44:00
回答 2查看 123关注 0票数 0

我一直在做一个简单的项目,在AVR微控制器atmega16上对proteus进行模拟。

项目是:当我按下按钮时,它会将七个段增加到数字9,然后,如果我们再次按下按钮,它就会溢出,并再次返回到0。

当我改变(flag=1;)在When循环代码的位置时,它给了我不同的输出,我的意思是当我按下按钮时,它在推送后没有响应。

可能需要再按一下按钮才能增加七段proteus模拟

唯一正常工作的代码是在退出之前设置flag=1; (第二个if和else条件)。

因此,我的问题是,当我更改代码中的flag=1;语句位置时,实际发生了什么。

代码语言:javascript
运行
复制
#include<avr/io.h>
#include<avr/interrupt.h>
char flag=1;
char num=0;
void INT2_Init(void){
    DDRB&=~(1<<2);
    SREG|=(1<<7);
    GICR|=(1<<INT2);
    MCUCSR|=(1<<ISC2);
}
ISR(INT2_vect){
    flag=0;
    GIFR|=(1<<INTF2);
}

int main(void){
    DDRC=0x0f;
    PORTC=0;
    DDRB&=~(1<<2);
    INT2_Init();
    while(1){
        if(flag==0){
            if(num>8){
                num=0;
                PORTC=(PORTC&0xf0)|num;
            }
            else{
                num++;
                PORTC=(PORTC&0xf0)|num;
            }
        }
        flag=1;
    }

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-04-25 07:50:05

如果主代码和中断中有一些变量更改,则必须将其标记为volatile。否则,编译器可能决定缓存变量值,并在循环中省略它的读取。

volatile char flag=1;

第二,注意您的标志变量更改的时间和地点。例如:

代码语言:javascript
运行
复制
    while(1){
        // at this point flag is 0, comparison failed
        if(flag==0) {
          ...
        }
// Interrupt happens here, changing flag to 0
// Then flag is immediately reset, thus flag change is missed in the loop
        flag=1; 
    }

相反,考虑使用这样的模式:

代码语言:javascript
运行
复制
    while (1) {
         cli(); // disabling interrupts ensuring no interrupt happens inside 
         if (flag==0) {
           ...
         }
         flag = 1;
         sei(); // re-enable interrupts
    }

或者,在这种情况下,它可以更简单

代码语言:javascript
运行
复制
    while (1) {
         if (flag==0) {
             flag = 1; // Reset flag only if it set, right after comparison
             ...
         }
    }
票数 0
EN

Stack Overflow用户

发布于 2022-04-20 07:07:00

我不太清楚你在问什么。你只是挣扎着去理解代码吗?我的评论有用吗?

代码语言:javascript
运行
复制
#include<avr/io.h>
#include<avr/interrupt.h>
char flag=1;
char num=0;

void INT2_Init(void){
    DDRB&=~(1<<2);
    SREG|=(1<<7);
    GICR|=(1<<INT2);
    MCUCSR|=(1<<ISC2);
}

// sets flag to 0 on external interrupt (button press)
ISR(INT2_vect){
    flag=0;
    GIFR|=(1<<INTF2);
}

int main(void){
    DDRC=0x0f;
    PORTC=0;
    DDRB&=~(1<<2);
    INT2_Init();

    while(1){
        // if flag was set to 0 in external interrupt -> increment (or overflow) number on segment display
        if(flag==0){
            if(num>8){
                num=0;
                PORTC=(PORTC&0xf0)|num;
            }
            else{
                num++;
                PORTC=(PORTC&0xf0)|num;
            }
        }
        // reset the flag to 1 to prevent num from being incremented continuously
        flag=1;
    }
}

我建议将flag=1;移到if中,以明确说明语句只应在按下每个按钮时执行一次。

代码语言:javascript
运行
复制
    while(1) {
        // if flag was set to 0 in external interrupt -> increment (or overflow) number on segment display
        if(flag==0){
          // reset the flag to 1 to prevent num from being incremented continuously
          flag=1;

            if(num>8){
                num=0;
                PORTC=(PORTC&0xf0)|num;
            }
            else{
                num++;
                PORTC=(PORTC&0xf0)|num;
            }
        }
    }

使用自描述变量名也是明智的。例如,喜欢buttonWasPressed而不是flag。这样的代码就更容易阅读了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71932120

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档