-
Data: 2011-02-10 20:56:55
Temat: Re: AVR ATmega, pomiar częstotliwości przebiegu, prośba o sprawdzenie kodu
Od: "Robbo" <y...@m...com> szukaj wiadomości tego autora
[ pokaż wszystkie nagłówki ]Dziękuję bardzo za ten kod. Przykład z wykorzystaniem union oraz struct
również bardzo cenny!
Twój kod, tak na szybko, bez union i struct (chodzi o samą ideę):
SIGNAL (SIG_INPUT_CAPTURE3)
{
icr = ICR3;
if (ETIFR & _BV(TOV3)) {
overflow++;
ETIFR |= _BV(TOV3);
ff++; // licznik zdarzeń tego typu
}
actualDuration = ((unsigned long)icr + overflow * 65536UL) - pp;
pp = (unsigned long)icr + overflow * 65536UL;
}
SIGNAL (SIG_OVERFLOW3)
{
overflow++;
}
Wyświetlam sobie na LCD wartość ff. Na ogół ma wartość "1" i tak już
zostaje. Wynika z tego, że bardzo rzadko mam sytuację z jednoczesnymi
przerwaniami.
Wydaje mi się, że możliwe jest jeszcze pewne uproszczenie -- w praktyce mi
ono zdaje egzamin (a przynajmniej tak mi się wydaje na podstawie
obserwacji). Chodzi o to, że u Ciebie "overflow" inkrementowany jest
nieustannie. To nie jest błąd -- wszystko działa jak należy. Niemniej ja
chciałem mieć "overflow" zerowany, gdyż zależnie od jego wartości chciałem
zrobić odcinanie niskich częstotliwości mierzonego sygnału. Oto przeróbka:
*** KROK 1
SIGNAL (SIG_INPUT_CAPTURE3)
{
icr = ICR3;
if (ETIFR & _BV(TOV3)) {
overflow++;
ETIFR |= _BV(TOV3);
}
actualDuration = ((unsigned long)icr + overflow * 65536UL) - pp;
pp = (unsigned long)icr + overflow * 65536UL;
pp -= overflow * 65536UL;
overflow = 0;
}
powyższe można uprościć do takiej postaci:
*** KROK 2
SIGNAL (SIG_INPUT_CAPTURE3)
{
icr = ICR3;
if (ETIFR & _BV(TOV3)) {
overflow++;
ETIFR |= _BV(TOV3);
}
actualDuration = ((unsigned long)icr + overflow * 65536UL) - pp;
pp = (unsigned long)icr;
overflow = 0;
}
Zatem wydaje mi się (może się mylę, ale w praktyce działa i wygląda OK), że
w "pp" nie musimy trzymać wartości licznika software'owego, a wystarczy
trzymać ICR.
Co o tym myślisz?
A oto kompletny kod -- odcinamy poniżej ok. 2Hz (w szczególności, gdy sygnał
w ogóle jest zerowy).
SIGNAL (SIG_INPUT_CAPTURE3)
{
icr = ICR3;
if (ETIFR & _BV(TOV3)) {
overflow++;
ETIFR |= _BV(TOV3);
}
actualDuration = ((unsigned long)icr + overflow * 65536UL) - pp;
pp = (unsigned long)icr;
overflow = 0;
}
SIGNAL (SIG_OVERFLOW3)
{
overflow++;
}
int main(void)
{
char buf[16];
unsigned long actualDurationLatch;
TCCR3A = 0;
TCCR3B |= _BV(ICES3) | _BV(ICNC3) |
_BV(CS32) | _BV(30); // prescaler 64
ETIMSK |= _BV(TICIE3) | _BV(TOIE3);
sei();
while (1) {
cli();
actualDurationLatch = actualDuration;
sei();
if ((overflow >= 5) || (actualDurationLatch > 150000)) {
LCDwriteString("-------------");
} else {
sprintf(s, "%ld ", actualDurationLatch);
LCDwriteString(s);
}
}
}
W moim pierwotnym liście podałem kod z wykorzystaniem SIG_OUTPUT_COMPARE2
oraz SIG_INTERRUPT7. Kod tamten miał (w porównaniu do tego z wykorzystaniem
input capture) tę wadę, że zwiększanie zmiennej "timer" 100000 razy na
sekundę obciążąło procesor. Niemniej miał on też pewną zaletę -- chodzi o
to, że dla niskich częstotliwości "odcinanie" miałem zawsze w określonym
czasie (np. gdy timer osiągnął wartość 100000; timer był resetowany po
każdym zboczu narastającym -- zatem wartość 100000 mówiła, że minęło 100000
ticków zegara od ostatniego zbocza narastającego sygnału mierzonego). Tu
(chodzi o kod z input capture) niestety jest problem. Gdy sygnał zaniknie
nagle, to "overflow" musi doliczyć do 5 (taką wartość sobie przyjąłem), ale
przecież ICR może mieć różną wartość i czas, w którym "overflow" doliczy do
5 może być różny (gdy ICR było bliskie 0, to będzie to czas prawie pięciu
przepełnień ICR; gdy ICR było prawie 65000, to będzie to czas nieco ponad
czterech przepełnień ICR). Aby mieć dokładne odcinanie (po upływie dokładnie
określonego czasu), musiałbym zrobić dodatkowy timer (np. dający impuls co 1
sekundę), resetowany w SIG_INPUT_CAPTURE3. Jeśli timer da impuls (czyli nie
został zresetowany w ciągu ostatniej sekundy), to znaczy, że sygnał jest
poniżej 1Hz i robimy odcinanie.
R.
Następne wpisy z tego wątku
- 10.02.11 21:31 Michoo
- 11.02.11 07:36 Zbych
- 11.02.11 11:05 Robbo
- 11.02.11 11:43 Michoo
- 11.02.11 12:15 Zbych
- 11.02.11 12:22 Robbo
- 11.02.11 12:24 Zbych
- 11.02.11 12:33 Zbych
- 11.02.11 12:58 Robbo
- 11.02.11 13:09 Robbo
Najnowsze wątki z tej grupy
- pradnica krokowa
- Nieustający podziw...
- Coś dusi.
- akumulator napięcie 12.0v
- Podłączenie DMA 8257 do 8085
- pozew za naprawę sprzętu na youtube
- gasik
- Zbieranie danych przez www
- reverse engineering i dodawanie elementów do istniejących zamkniętych produktów- legalne?
- Problem z odczytem karty CF
- 74F vs 74HCT
- Newag ciąg dalszy
- Digikey, SN74CBT3253CD, FST3253, ktoś ma?
- Szukam: czujnik ruchu z możliwością zaączenia na stałe
- kabelek - kynar ?
Najnowsze wątki
- 2025-01-18 Warszawa => Developer .NET (mid) <=
- 2025-01-18 Katowice => Administrator IT - Systemy Operacyjne i Wirtualizacja <=
- 2025-01-17 Zniknął list gończy za "Frogiem". Frog się nam odnalazł?
- 2025-01-17 Kto wytłumaczy "głupiemu" prezydentowi Dudzie wielką moc prawną "dekretu premiera" TUSKA? [(C)Korneluk (2025)]
- 2025-01-17 Warszawa => Inżynier oprogramowania .Net <=
- 2025-01-17 Natalia z Andrychowa
- 2025-01-17 Gliwice => Business Development Manager - Dział Sieci i Bezpieczeńst
- 2025-01-17 Warszawa => System Architect (Java background) <=
- 2025-01-17 Warszawa => Full Stack .Net Engineer <=
- 2025-01-17 Gliwice => IT Expert (Network Systems area) <=
- 2025-01-17 Lublin => Programista Delphi <=
- 2025-01-17 Warszawa => Developer .NET (mid) <=
- 2025-01-17 Ostrów Wielkopolski => Konsultant Wdrożeniowy Comarch XL/Optima (Ksi
- 2025-01-17 Katowice => Senior Field Sales (system ERP) <=
- 2025-01-17 Wróblewo => Analityk finansowy <=