Witam.
Zbudowałem układ, który składa się z dwóch części. Pierwsza to generator o częstotliwości 125kHz, druga to przetwornik ADC, który mierzy sygnał i zapala diody w zależności od niego.
Oba podukłady (podprogramy) oddzielnie działają poprawnie. Jednak jak skleiłem dwa kody (jeden od ADC drugi od generatora) to już zaczęły się schody.
Jak dotąd nie używałem dwóch przerwań w jednym programie i może stąd popełniłem błąd.
Problem objawia się tym, że jak w main() mam tak jak w programie poniżej to diody podłączone do portu D cały czas zapalają się i gaszą sekwencyjnie zgodnie z funkcją Test(). Tak jakby była ona wpisana w while(1). No i wtedy nie działa ADC.
Natomiast jak zostawię samo InitADC() to Test() wykona się raz i ADC działa.
Skąd może brać się takie zachowanie?
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define led0 (1 << PD0)
#define led1 (1 << PD1)
#define led2 (1 << PD2)
#define led3 (1 << PD3)
#define led4 (1 << PD4)
#define led5 (1 << PD5)
#define led6 (1 << PD6)
#define Out PD7
#define Square PB1
volatile int histereza=100;
volatile int x=0,i=0;
volatile int pomiar=0;
#define wart1 530//530
#define wart2 615//615
#define wart3 660
#define wart4 705
#define wart5 750
//--------------Przerwanie ADC-------------------
ISR(ADC_vect)
{
pomiar = ADC;
if ((pomiar > wart1-histereza) && (pomiar <= wart1+histereza)) PORTD = 0b00000001;
else if ((pomiar > wart1+histereza) && (pomiar <= wart2+histereza)) PORTD = 0b00000011;
else if ((pomiar > wart2+histereza) && (pomiar <= wart3+histereza)) PORTD = 0b00000111;
else if ((pomiar > wart3+histereza) && (pomiar <= wart4+histereza)) PORTD = 0b00001111;
else if ((pomiar > wart4+histereza) && (pomiar <= wart5+histereza)) PORTD = 0b00011111;
else PORTD = 0x00;
}
//-------------Konfiguracja ADC-----------------
void InitADC(void)
{
ADMUX = _BV(REFS0) | _BV(REFS1) ;// Napięcie odniesienia wewnętrzne, AREF podłączony z GND przez 100n
//| _BV(MUX0); // Kanał ADC1
ADCSRA = _BV(ADFR) // Free Running
| _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0) // preskaler , f = 8MHz/128 = 62,5 kHz (w zakresie 50kHz-200kHz)
| _BV(ADEN) // Aktywacja przetwornika
| _BV(ADIE) // Aktywne przerwanie od ADC
| _BV(ADSC); // Start pierwszej konwersji
}
void InitSquare()
{
//Tryb CTC
TCCR1A = (1 << COM1A0);
TCCR1B = (1 << WGM12) | (1 << CS10); // Preskaler 1
TIMSK = (1 << OCIE1A) | (1 << TOIE1);
OCR1A = 31;//31
}
void Test(void)
{
for (int i=0;i<=5;i++)
{
PORTD = 1<<i;
_delay_ms(100);
}
for (int i=5;i>=0;i--)
{
PORTD = 1<<i;
_delay_ms(100);
}
}
int main()
{
DDRD = 0xff;
DDRB |= (1 << Square);
Test();
InitADC();
InitSquare();
sei();
while(1)
{
}
}
Re: ADC
Zmień tryb działania ADC z ciągłego na pojedynczy.... i wywołuj go wtedy kiedy chcesz zmierzyć. Poza tym twój program wykona tylko raz procedurę Test bo masz ją poza pętla główną
UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.
Dodałem do programu funkcję
Dodałem do programu funkcję wywoływaną od przerwania, czyli w moim przypadku:
Dodanie tego kodu nie spowodowało jednak do końca prawidłowego działania. Tzn. idzie funkcja Test() potem inicjalizacje ADC i timera. Działa generator, nie działa ADC.
Edit:
No niestety pojedynczy tryb ADC nie pomógł. Robię to tak:
Oczywiście w main() wywołuje funkcję InitADCSingle().