在AVR

时间:2018-10-10 12:30:06

标签: c interrupt avr

我是AVR编程的新手,如果问题很简单,请抱歉。

使用:

  1. 操作系统:Windows7
  2. IDE:Atmel工作室
  3. uC = m328p

引脚:

  1. ADC信号-ADC0 / PC0
  2. LED值-(PB0-PB7)
  3. LED_START-PD1
  4. LED_LIGHT-PD0
  5. 按钮-PD2

目标:当您按下按钮时,LED_START会亮起,需要从转换开始。 AVR中断并开始ADC转换。程序基本上有两个中断。我知道INT0中断具有最高优先级。

我不知道该如何处理。 我已经尝试了几种方法,例如添加全局变量“ start”并进行更改。而且,当我仅将LED START设置为ON时,它将保持该状态,直到LED_values达到特定值为止,然后LED START会自行关闭。

所以请您告诉我如何处理两个中断,以实现既定目标并向我解释我做错了什么。

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define F_CPU 1000000UL
#define BIT_IS_SET(byte, bit) (byte & (1 << bit))
#define BIT_IS_CLEAR(byte, bit) (!(byte & (1 << bit)))

typedef enum{false, true} bool;

bool previousState = false;
bool start = false;

char num;

void setup();
void loop();
void ADC_init();
void EI_init(); // External Interrupt

int main(void)
{
    setup();
    loop();
}

void setup(){
    DDRC &= ~(0x1); // LDR Input
    DDRB = 0xFF; //LEDs value Output
    DDRD |= 0x3; //LED light LED start Output
    DDRD &= ~(1 << PIND2); //Button Input
}

void loop(){
    PORTD |= (1 << PIND2);
    EI_init();
    ADC_init();
    sei();
    if(start){
        ADCSRA |= (1 << ADSC);  
    }
    while(1){}

}

void ADC_init(){
    ADMUX = 0x60;
    ADCSRA = 0x8B;
    ADCSRB = 0x0;
    ADCH = 0x0;
}

ISR(ADC_vect) {
    PORTB = ADCH;   // assign contents of ADC high register to Port D pins
    int b = (int)ADCH;
    if(b > 180) { //100
        PORTD = 0x1;
    }else{
        PORTD &= ~(0x1);
    }
    _delay_ms(100);
    ADCSRA |= (1 << ADSC);      // start next ADC
}

void EI_init(){
    EIMSK |= (1 << INT0); // Interrupt enabled
    EICRA |= (1 << ISC00); // any state change
}

ISR(INT0_vect){
    if(BIT_IS_CLEAR(PORTD,PIND2)){
        start = true;
    }else{
    start = false;
    }
}

这是方案:scheme

1 个答案:

答案 0 :(得分:0)

首先,由于主循环和中断都使用start,因此应将volatile设为volatilevolatile bool start = false; 关键字告诉编译器该变量可能会被其控制范围之外的事物所修改,因此它无法优化对该变量的任何读取或写入:

loop

第二,您可能想删除while(1){} 末尾写的这一行:

loop

该行很糟糕,因为它会使您的程序进入无限循环,在此循环中什么都不做。我认为您实际上是希望在start函数中编写的代码能够多次运行。

第二,在检测到start标志已设置后,您可能需要将其设置为0,否则它将永远为1。

第三,在INT0 ISR中将{{1}}设置为false可能不是一个好主意,因为在主循环有机会观察到它为true并处理该事件之前,它可能被设置为false。我想这真的取决于您要做什么。您可以尝试在问题中添加有关您要使用AVR解决的确切问题的详细信息。参见What is the XY problem?

您的代码中可能还有其他问题需要调试。您能想到什么方法来简化此过程吗?也许您可以减少使用的中断数。要进行调试,您可以尝试使一些LED闪烁以找出程序的哪些部分正在执行。