ATMEGA8 i dwa kanały ADC w C

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

ATMEGA8 i dwa kanały ADC w C

Post autor: Aro » 08 lip 2008, 20:06

Witam,
Śmieszny problem, no ale cóż :oops: Mam problem z napisaniem programu obsługującego dwa kanały ADC. Praktycznie brak separacji kanałów, sygnał z jednago nachodzi na drugi i odwrotnie. Poniżej listing:

Kod: Zaznacz cały

int main(void)
{
	TCCR0=_BV(CS00);
	TIMSK=_BV(TOIE0);
	ADMUX =  _BV(REFS1) | _BV(REFS0);                // wybierz kanał 0 przetwornika ADC
	ADCSR = _BV(ADEN)|_BV(ADPS2);                  //ADC
	DDR(T1)=_BV(T1pin);
	DDR(T2)|=_BV(T2pin);
	wdt_enable(WDTO_15MS);
while(1)
{
	if(PIN(POWER)&_BV(POWERpin)) exitp=0;
		else exitp=1;
		PWM=150;
		
	while(exitp)
	{
		PORT(T1)|=_BV(T1pin);
		ADMUX = ( _BV(REFS1) | _BV(REFS0));    //kanał 0
		_delay_loop_2(1000);
		_delay_loop_1(50);
		ADCSR|=_BV(ADSC);
		_delay_loop_1(50);
		uint16_t value=ADCW;
		ADCSR|=_BV(ADSC);
		_delay_loop_1(15);
		value+=ADCW;
		if(value>1610)PWM--;
		if(value<1525)PWM++;
		if(value>1700)PWM--;
		if(value<1350)PWM++;
		if(value>1730)PWM-=2;
		if(value<1200)PWM++;
		
		if(PWM>199)PWM=199;
		if(PWM<2)PWM=2;
		_delay_loop_2(1000);
		ADMUX = ( _BV(MUX1) | _BV(REFS1) | _BV(REFS0));   //kanał 3
		_delay_loop_2(1000);
		ADCSR|=_BV(ADSC);
		_delay_loop_1(50);
		ADCSR&=~(_BV(ADIF));      //powinno byc raczej ADCSR|=_BV(ADIF);
		value=ADCW;
		//ADCSR|=_BV(ADSC);
		_delay_loop_1(15);
		value+=ADCW;
		_delay_loop_1(50);
		
		//if(value<1000)exitp=0;*/
		
		for(uint16_t i=0; i<200; i++)
		{
			if(PWM>i) PORT(T1)|=_BV(T1pin);
			else PORT(T1)&=~(_BV(T1pin));
			_delay_loop_1(28);
		}
		PORT(T1)&=~(_BV(T1pin));
		
		wdt_reset();
		
		PORT(T2)|=_BV(T2pin);
		ADMUX = ( _BV(REFS1) | _BV(REFS0));    //kanał 0
		_delay_loop_2(1000);
		ADCSR|=_BV(ADSC);
		_delay_loop_1(50);
		value=ADCW;
		ADCSR|=_BV(ADSC);
		_delay_loop_1(15);
		value+=ADCW;
		if(value>1660)PWM--;
		if(value<1450)PWM++;
		if(value>1800)PWM-=2;
		if(value<1000)PWM+=2;
		if(value<800)PWM+=3;
		if(value<600)PWM+=4;
		if(PWM>199)PWM=199;
		if(PWM<2)PWM=2;
				
		for(uint16_t i=0; i<200; i++)
		{
			if(PWM>i) PORT(T2)|=_BV(T2pin);
			else PORT(T2)&=~(_BV(T2pin));
			_delay_loop_1(28);
		}
		PORT(T2)&=~(_BV(T2pin));
		wdt_reset();
		
		if(PIN(POWER)&_BV(POWERpin)) exitp=0;
		
	}
	wdt_reset();
}
	return 0;
}

Leszczu87
-
Posty: 7
Rejestracja: 23 wrz 2005, 9:34

Post autor: Leszczu87 » 29 sie 2008, 16:54

Miałem podobny problem chociaż program nie miał błędów - co sekunde miał dawac na zmiane wyniki z czujników, ale wszystko wariowało. W końcu uzyłem wyświetlania jednoczesnego na ekranie obu wyników w taki sposób i o dziwo działa(choć zasada działanie pozostała w zasadzie ta sama):

Kod: Zaznacz cały

SIGNAL(SIG_ADC)                        // przerwanie z przetwornika ADC
{
  value1 = ADCW;
  if(k==1)
  {
	wysw();
  }
  if(k==2)
  {
	wysw2();
	k=0;
  }
  k=k+1;
}

void wysw(void)
{
	uint16_t temp=0;
			ADMUX = 1<<REFS0 | 1<<MUX0;
			ADCSRA = 1<<ADSC | 1<<ADEN | 1<<ADIE | 1<<ADPS2 | 1<<ADPS1; //| 1<<ADFR;
			LCDpsec();	
			temp=value1;		
			LCDcommand(LCDC_DDA|12);
			LCDdec(temp);
			value1 = 0;		
		LCDpsec();
}
void wysw2()
{
		uint16_t temp=0;
			ADMUX = 1<<REFS0; 
			ADCSRA = 1<<ADSC | 1<<ADEN | 1<<ADIE | 1<<ADPS2 | 1<<ADPS1; //| 1<<ADFR;
			LCDpsec();
			LCDcommand(LCDC_DDA|65);
			temp=value1;
			LCDdec(temp);
}
void LCDpsec(void)
{
	_delay_ms(50);
}
int main(void)
{
	DDRD = 1<<7 | 1<<6 | 1<<5 | 1<<3 | 1<<4;
	DDRB = 1;
	PORTD=1<<0 | 1<<1 | 1<<2;
	
	TCCR1B = 1<<CS12;//1<<CS11 | 1<<CS10;  //prescaler dla timer1 x64

	
	ADMUX = 1<<REFS0;                	// wybierz kanał 0 przetwornika ADC i AREF zewnetrzne
	ADCSRA = 1<<ADEN | 1<<ADIE | 1<<ADPS2 | 1<<ADPS1; //| 1<<ADFR;
								// włącz przetwornik i uruchom generowanie przerwań
								// częstotilwość taktowania F_ADC=F_CPU/64
								// przy F_CPU=8MHz : F_ADC=125 kHz
	
	LCDinit();
	LCDcls();
	LCDpsec();
	LCDstr("2 czujniki"); 
	//LCDcommand(LCDC_CGA|2);
	LCDcommand(LCDC_DDA|40);
	LCDstr("");
	
	sei();               		// włącz obsługę przerwań
	
	ADCSRA = 1<<ADSC | 1<<ADEN | 1<<ADIE | 1<<ADPS2 | 1<<ADPS1;
}
Kod umieszcza się między znacznikami code. Następnym razem będzie ostrzeżenie. CSM
Ostatnio zmieniony 29 sie 2008, 16:55 przez Leszczu87, łącznie zmieniany 1 raz.

Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Post autor: Aro » 29 sie 2008, 21:11

Mój problem polegał na tym, że nie sprawdziłem dokładnie połączeń na płytce testowej, a powodem dziwnych wyników była duża rezystancja jednego z przewodów. Program jest dobry.

ODPOWIEDZ