[Tiny13][C] Obsługa ADC ...

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!
Awatar użytkownika
mictronic
-
Posty: 81
Rejestracja: 04 paź 2006, 19:28
Lokalizacja: Bydgoszcz
Kontakt:

[Tiny13][C] Obsługa ADC ...

Post autor: mictronic » 21 lip 2009, 18:13

Witam,mecze się z uruchomieniem ADC,dopiero zaczynam pisać w C wiec stąd te problemy zapewne.
Mowie co mam,i co nie działa.

Kod: Zaznacz cały

#define F_CPU 960000L
#include <avr/io.h>              
#include <avr/interrupt.h>
int main(void)
{

DDRB=0b00000001;

TCCR0A = 0b10000011;
TCCR0B = 0x01;

ADCSRA=0b11100111;//Enable ADC,Start ADC,Auto Trigger Mode Enable,Prescale 128
ADMUX=0b00000001;//PB.2 wejscie,reference z VCC
sei();

while(1){
//if(!(ADCSRA & _BV(ADIF)))
OCR0A=ADCL;
}

}
Pod pin PWM mam podpiętą diodę która ledwo się świeci,konfiguracja PWM działa bo wpisanie danej do rejestru OCR powoduje rozbłysk diody ; )

Co nie tak??

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

Post autor: Aro » 21 lip 2009, 18:55

Nie wnikając w głąb programu, od razu w oczy rzucił mi się drobny błąd. Otóż nie można odczytywać tylko rejestru ADCL. Chyba że masz ustawione przesuwanie wyniku (chyba bit ADLAR jak dobrze pamiętam). Przy normalnej pracy musisz odczytać starszy bajt czyli ADCH, aby kontroler ADC go zaktualizował przy następnym pomiarze. możesz wstawić

Kod: Zaznacz cały

uint8_t rej;
asm volatile("IN %[rej], ADCH": [rej] "=r" (rej));
przed instrukcję OCR0A=ADCL
Prościej jednak będzie wpisać po prostu OCR0A=ADCW. Efekt ten sam, ale program wygląda ładniej;)

Awatar użytkownika
mictronic
-
Posty: 81
Rejestracja: 04 paź 2006, 19:28
Lokalizacja: Bydgoszcz
Kontakt:

Post autor: mictronic » 21 lip 2009, 19:55

Ok mam już coś takiego,dioda już zmienia swoje stany pracy...

Kod: Zaznacz cały

#define F_CPU 960000L
#include <avr/io.h>             
#include <avr/interrupt.h>
int main(void)
{
char a;
DDRB=0b00000001;

TCCR0A = 0b10000011;
TCCR0B = 0x01;
sei();

ADCSRA=0b11100111;//Enable ADC,Start ADC,Auto Trigger Mode Enable,Prescale 128
ADMUX=0b00000001;//PB.2 wejscie,reference z VCC


while(1){
//if(ADCSRA & _BV(ADIF)){
a=ADCH;
OCR0A=ADCL;
//}
}

}
Ale nie działa to jakby w czasie rzeczywistym,raz mignie jak dotknę VCC teraz się ciągle świeci,nieraz się wyłącza...
Proszę o pomoc.

Przynajmniej tu jest jakiś ruch jakbym spytał na elektrodzie to pewnie nikt by nie odpowiedział i chwała Wam za to!

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

Post autor: Aro » 21 lip 2009, 20:36

raz mignie jak dotknę VCC
No to to już raczej wina sprzętu a nie programu.
Skoro dopiero zaczynasz pisać w C, to od razu proponuję abyś używał nazw bitów rejestrów, a nie stosował zapisu 0 i 1.
Aha, i odkomentuj tą instrukcję sprawdzającą flagę konwersji ADC. Teraz ciągle przepisujesz wartość, nawet jak przetwornik nie zakończył pracy. A najlepiej od razu zastosuj przerwanie z ADC i tam przepisuj wartość do OCR0A.

Kod: Zaznacz cały

ADCSRA=_BV(ADEN)|_BV(ADATE)|_BV(ADIE)|_BV(ADPS2)|_BV(ADPS1); //konwersja samobieżna, włączenie przerwania, preskaler=64
ADMUX=_BV(REFS0)|_BV(MUX0); //wewnętrzne napięcie odniesienia 1,1V oraz kanał 1 przetwornika ADC
DIDR0=_BV(ADC1D); //wyłącznie bufora cyfrowego dla wejścia ADC
ADCSRA|=_BV(ADSC); //uruchomienie ADC
sei();
i przerwanie

Kod: Zaznacz cały

SIGNAL(SIG_ADC)
{
  OCR0A=ADCW;
}
tyle wygrzebałem z mojego programu, pozmieniaj sobie tylko napięcie odniesienia, preskaler i ew. kanał ADC.

Awatar użytkownika
mictronic
-
Posty: 81
Rejestracja: 04 paź 2006, 19:28
Lokalizacja: Bydgoszcz
Kontakt:

Post autor: mictronic » 22 lip 2009, 13:05

Kod: Zaznacz cały

#include <avr/io.h>             
#include <avr/interrupt.h>
#include <avr/signal.h>


char a;

int main(void)
{
DDRB=0b00000001;
TCCR0A = 0b10000011;
TCCR0B = 0x01;

ADCSRA|=_BV(ADEN)|_BV(ADSC)|_BV(ADATE)|_BV(ADIE)|_BV(ADPS0)|_BV(ADPS1)|_BV(ADPS2);
ADMUX|=_BV(MUX0);

sei();

}

SIGNAL(SIG_ADC)
{
a=ADCH;
OCR0A=ADCL;

}
Zastosowałem się do powyższych poprawek,niestety nadal brak efektu.
Proszę zauważyć ze na linii ADC0 jest SCK programatora ISP,czy musze odłączyć programator przed testowaniem?
Zadowala mnie również ośmio bitowa dokładność pomiaru,tak wiec nie potrzebuje wogole odczytywać ADCH-jak to zrobić?

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

Post autor: Aro » 22 lip 2009, 20:42

A jaki masz dokładnie programator? Najlepiej sprawdź, czy na ADC0 jest jakiś stan, czy jest to wejście pływające.
Mówisz wystarcza ci 8 bitów... a jaki chcesz mieć zakres pomiaru? Może lepiej wykorzystać wewnętrzne napięcie odniesienia 1,1V i ustawić bit ADLAR? Wtedy będziesz odczytywał tyko rejestr ADCH, czyli masz 8 bitową dokładność i mniej więcej ten sam zakres. Czyli od 0 do 1.1V. Poprzednio miałeś zakres 1/4VCC, gdyż ATtiny13 ma tylko 10 bitowy przetwornik.

Awatar użytkownika
mictronic
-
Posty: 81
Rejestracja: 04 paź 2006, 19:28
Lokalizacja: Bydgoszcz
Kontakt:

Post autor: mictronic » 22 lip 2009, 21:13

Wiem już w czym problem,coś tu nie potrafi przenieść bezpośrednio wartości rejestru ADCL do rejestru OCR0A.Napisałem ten sam kod w bascomie:

Kod: Zaznacz cały

]
$regfile = "attiny13.dat"
$crystal = 9600000

Ddrb = &B00000001
Tccr0a = &B10000011
Tccr0b = &B00000001

Adcsra = &B11100111
Admux = &B00000001
Dim A As Byte
Do
A = Adch
Ocr0a = Adcl

Loop
I tez nie działa,ALE gdy OCR0A zmienimy na PWM0A podejmuje prace : )
Tak wiec konfiguracja adc i pwm jest poprawna ale błąd jest tylko w tym miejscu .
Jak to w takim razie napisać w C??

EDIT
Ah ustawiłem w bascomie bit ADLAR i przepisałem ADCH do OCR0A i działa ale w C nie : /

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

Post autor: Aro » 23 lip 2009, 11:35

Jakiego kompilatora C używasz?

Awatar użytkownika
mictronic
-
Posty: 81
Rejestracja: 04 paź 2006, 19:28
Lokalizacja: Bydgoszcz
Kontakt:

Post autor: mictronic » 23 lip 2009, 11:57

AVRGCC,eh taki prosty program jednak napisze go w BASCOMie : /

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

Post autor: Aro » 23 lip 2009, 16:49

A którą wersję masz?

Awatar użytkownika
mictronic
-
Posty: 81
Rejestracja: 04 paź 2006, 19:28
Lokalizacja: Bydgoszcz
Kontakt:

Post autor: mictronic » 23 lip 2009, 17:33

Jest to wersja 2.0.8.718

snow
Użytkownik
Posty: 794
Rejestracja: 16 sty 2007, 3:44
Lokalizacja: lubelskie
Kontakt:

Post autor: snow » 23 lip 2009, 18:26

Może tak:

Kod: Zaznacz cały

void adc_init(void)
{
// Wybranie wewnętrznego żródła napięcia odniesienia	
	ADMUX |= _BV(REFS0);		
	ADMUX |= _BV(REFS1);
//	Wybranie sposobu zapisu wyniku z wyrównaniem do lewej (osiem starszych bitów wyniku w rejestrze ADCH)
	ADMUX |= _BV(ADLAR);		
// Zezwolenie na konwersję	
	ADCSRA |= _BV(ADEN);		
// Wybranie częstotliwości dla taktowania przetwornika  (1/8 częstotliwosci zegara kontrolera) 
	ADCSRA |= _BV(ADPS0);	 
	ADCSRA |= _BV(ADPS1);	//
}


unsigned char odczyt_8bit (void)
{
				ADCSRA |= _BV(ADSC);         // Rozpoczęcie przetwarzania
				while(bit_is_set(ADCSRA,ADSC))	// Oczekiwanie na zakończenie przetwarzania
				{};	
				pomiar=ADCH;			     // Zapisanie starszych 8 bitów wyniku konwersji do
											// zmiennej "pomiar"
                               return pomiar;
}

Awatar użytkownika
mictronic
-
Posty: 81
Rejestracja: 04 paź 2006, 19:28
Lokalizacja: Bydgoszcz
Kontakt:

Post autor: mictronic » 25 lip 2009, 0:36

Pisze w C ledwo 2 tygodnie wiec powyższego kodu nie potrafię zaimplementować do własnych celów.Za to uruchomiłem układ inaczej.Okazało się ze miałem włączony fuse bit divide by 8 nie wiem jak,nie wiem poco ale jak go wyłączyłem przetwornik ruszył.Niestety zablokowałem chyba procesor/unieruchomiłem transmisje isp bo ustawiłem jednocześnie bit dzielenia przez 8 zegara oraz zegar 128kHz- tak sobie żeby zobaczyć co się stanie :D No i stało się ,jutro ..znaczy dzisiaj będę próbować jeszcze z opóźnieniem programowania ISP programatora .Moze pomoże ustawienie delay portu LPT w bascomie...

Jeszcze jedno zwierając końcówkę ADC do masy ,na wyjściu pwm nadal było wypełnienie bardzo małe bo widoczne na oscyloskopie ale zdolne zaświecić lekko dioda.Jak to możliwe?W nocie widziałem jakąś informacje ze od tej wartości należy odjąć 1 ...?

Awatar użytkownika
Pikczu
Użytkownik
Posty: 754
Rejestracja: 18 lip 2005, 18:33
Lokalizacja: Dublin
Kontakt:

Post autor: Pikczu » 25 lip 2009, 1:00

Witam Mictronic widzę że zarywasz nockę :)
Ja też siedzę nad bascomem i staram się poprawić mój kod ale coś mi słabo dziś idzie.

snow
Użytkownik
Posty: 794
Rejestracja: 16 sty 2007, 3:44
Lokalizacja: lubelskie
Kontakt:

Post autor: snow » 25 lip 2009, 8:49

mictronic pisze:W nocie widziałem jakąś informacje ze od tej wartości należy odjąć 1 ...?
Nie wydaje mi się aby takie coś trzeba było robić. Zawsze przy zwieraniu z masą powinnno się odczytać 0. Również PWM po przepisaniu wartości ADC do rejestru PWM powinien być 0.

ODPOWIEDZ