我是AVR编程的新手,如果问题很简单,请抱歉。
使用:
引脚:
目标:当您按下按钮时,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
答案 0 :(得分:0)
首先,由于主循环和中断都使用start
,因此应将volatile
设为volatile
。 volatile bool start = false;
关键字告诉编译器该变量可能会被其控制范围之外的事物所修改,因此它无法优化对该变量的任何读取或写入:
loop
第二,您可能想删除在while(1){}
末尾写的这一行:
loop
该行很糟糕,因为它会使您的程序进入无限循环,在此循环中什么都不做。我认为您实际上是希望在start
函数中编写的代码能够多次运行。
第二,在检测到start
标志已设置后,您可能需要将其设置为0,否则它将永远为1。
第三,在INT0 ISR中将{{1}}设置为false可能不是一个好主意,因为在主循环有机会观察到它为true并处理该事件之前,它可能被设置为false。我想这真的取决于您要做什么。您可以尝试在问题中添加有关您要使用AVR解决的确切问题的详细信息。参见What is the XY problem?。
您的代码中可能还有其他问题需要调试。您能想到什么方法来简化此过程吗?也许您可以减少使用的中断数。要进行调试,您可以尝试使一些LED闪烁以找出程序的哪些部分正在执行。