Pomiar czestotliwosc - Bascom

Jan 03, 2005 15 Replies

Witam! Mam napisac program do mierzenia czestotliwosci w Bascomie, a potem zasymulowaæ to w Proteusie. Narazie poprawnie podaje mi czestotliwosc, ale tylko dla jednego impulsu, przy za³o¿eniu ¿e wype³nienie to 50%. Niestety je¶li pod³±czê zegar, to g³upieje. Pisze na AT89c52. Sygna³ zegara pod³±czany do ~INT0. Je¶li kto¶ wie, napiszcie co jest nie tak.



Pozdrawiam, Teres


Tutaj jest schemat do Proteusa

formatting link
A tutaj kod z Bascoma:



'LCD CONFIGURATION Config Lcdpin = Pin , Db4 = P0.2 , Db5 = P0.3 , Db6 = P0.4 , Db7 = P0.5 , E = P0.1 , Rs = P0.0



$crystal = 1200000 '1,2Mhz Config Lcd = 16 * 4 Enable Interrupts 'wlaczenie przerwan Enable Int0 Set Tcon.0 'reaguje na zobcze Config Timer0 = Timer , Gate = External , Mode = 1 'ustawienie licznika



'reaguje na podanie sygnalu na int0 Dim Tmp As Integer , Wynik As String * 9 , Tmp2 As Long , Tmp3 As Long Set Tcon.4 Lcd "test" 'wlacza TR0 On Int0 Wypisz 'procedura obslugi przerwania



Cls Home Tmp3 = 0 Lcd "Witaj" Do 'nieskoñczona pêtla konca programu Loop



End


Wypisz: Reset Tcon.4



Tmp = Tl0 Tmp2 = Th0 Tl0 = 0 Th0 = 0



Shift Tmp2 , Left , 8 'przesuwamy o



8 miejsc starsza czesc licznika Tmp3 = Tmp + Tmp2 Tmp3 = Tmp3 * 2 'wypelnienie
50%

Cls Tmp3 = Tmp3 Tmp3 = 100000 / Tmp3 Lcd "czestotliwosc=" Lowerline Lcd Tmp3 ; " Hz" Tl0 = 0 Th0 = 0 Waitms 5000 Disable Int0 Enable Int0 Return Return



Zak³adam, ¿e przyczyn± jest to, i¿ po wej¶ciu do obs³ugi przerwania wy³±czasz je i program juz z niego nie wraca. Wywal Disable INT0 i zastosuj jaki¶ znacznik wykonania przerwania. Poza tym nieu¿ywaj lcd w przerwaniu. W przerwaniu zachowaj tylko wskazania timera i ustaw znacznik. Dopiero po wyzerowaniu znacznika w programie g³ownym do..loop wykonaj kolejne przerwanie.

PC

'ustawienie

'przesuwamy o

'wypelnienie

Np. tak:

'ustawienie

dim test as bit

reset test

Do if test=1 then disable int0 Shift Tmp2 , Left , 8 Tmp3 = Tmp + Tmp2 Tmp3 = Tmp3 * 2 Cls Tmp3 = Tmp3 Tmp3 = 100000 / Tmp3 Lcd "czestotliwosc=" Lowerline Lcd Tmp3 ; " Hz" Tl0 = 0 Th0 = 0 Waitms 5000 Enable Int0 start timer0 reset test end if End

Wypisz: if test=0 then stop timer0 Tmp = Tl0 Tmp2 = Th0 set test end if return

U¿ytkownik "Pablo C" <pch[ciach]@poczta.onet.pl> napisa³ w wiadomo¶ci news:crb3u6$heq$ snipped-for-privacy@nemesis.news.tpi.pl...

[ciach] Dziêki wielkie, sam nie wiem czemu o tym nie pomy¶la³em.

Pozdrawiam, Teres

Witam. Ja proponuję coś takiego: 'LCD CONFIGURATION $crystal = 1200000 '1,2Mhz Config Lcd = 16 * 4 Config Lcdpin = Pin , Db4 = P0.2 , Db5 = P0.3 , Db6 = P0.4 , Db7 = P0.5 , E = P0.1 , Rs = P0.0 Config Timer0 = Timer , Gate = Internal , Mode = 1 'ustawienie Licznika Dim Tmp3 As Long , Pstart As Bit Set Tcon.0 'reaguje na Zobcze On Int0 Int0_int Reset Pstart Enable Interrupts 'wlaczenie Przerwan Enable Int0 'zezwolenie na przerwanie int0 '... Do While Ie.0 = 1 : Wend Tmp3 = Counter0 Tmp3 = 1000000 / Tmp3 Rem wyświetlenie wyniku itp. ' .... Counter0 = 0 Enable Int0 'następny pomiar Loop

Int0_int: Rem zbocze opadające:początek pomiaru If Pstart = 0 Then Start Timer0 Set Pstart Else Rem zbocze opadające:koniec pomiaru (zmierzony czas trwania okresu) Stop Timer0 Disable Int0 Reset Pstart End If Return

U¿ytkownik "Piotrek Sz." snipped-for-privacy@gazeta.pl napisa³ w wiadomo¶ci news:crc3du$1rm$ snipped-for-privacy@inews.gazeta.pl...

Niestety ale prowadz±cy chce ¿eby Timer nie byl uruchamiany recznie (start/stop) tylko przez INT0 jako sterowanie.

Pozdrawiam, Teres

Teres snipped-for-privacy@WYTNIJTOpoczta.fm napisał(a):

Hmmm. W takim przypadku , można mierzyć tylko przebiegi o wypełnieniu 50/50 , a przy innych proporcjach wypełnienia wyjdzie knot :(

Pozdrawiam Piotrek

U¿ytkownik "Pablo C" <pch[ciach]@poczta.onet.pl> napisa³ w wiadomo¶ci news:crb3u6$heq$ snipped-for-privacy@nemesis.news.tpi.pl... [ciach] Poprawi³em swój program i wysz³o co¶ co wklejam poni¿ej. Niestety ci±gle mam problem, pierwszy pomiar jest ok, a potem jakie¶ kosmiczne liczby w Tmp3, dziel±c 10000 przez Tmp3 dostaje 0 na wy¶wietalczu. Czy ten Timer0 nie kasuje sie sam po zaprzestaniu podawania sygna³u na INT0, chyba ¿e to trzeba zrobiæ jako¶ inaczej, najlepiej dalej uruchamiane przerwaniem(tak chce prowadz±cy), w ostateczno¶ci zrobie jako Counter0. Pozdrawiam, Teres

Kod programu: 'LCD CONFIGURATION Config Lcdpin = Pin , Db4 = P0.2 , Db5 = P0.3 , Db6 = P0.4 , Db7 = P0.5 , E = P0.1 , Rs = P0.0

$crystal = 1200000 '1,2Mhz Config Lcd = 16 * 4 Enable Interrupts 'wlaczenie przerwan Enable Int0 Set Tcon.0 'reaguje na zobcze Config Timer0 = Timer , Gate = External , Mode = 1 'ustawienie licznika

'reaguje na podanie sygnalu na int0 Dim Tmp As Integer , Wynik As String * 9 , Tmp2 As Long , Tmp3 As Long , Test As Bit

Set Tcon.4 'wlacza TR0 On Int0 Wypisz 'procedura obslugi przerwania

Cls Home Tmp3 = 0 Lcd "Witaj" Reset Test 'skasowanie znacznika

Do 'petla w programie If Test = 1 Then Disable Int0 Shift Tmp2 , Left , 8 Tmp3 = Tmp + Tmp2 Tmp3 = Tmp3 * 2 Cls 'Tmp3 = 100000 / Tmp3 Lcd "czestotliwosc=" Lowerline Lcd Tmp3 ; " Hz" Tl0 = 0 Th0 = 0 ' Waitms 5000 Enable Int0 Start Timer0 Reset Test End If Loop

End

Wypisz: If Test = 0 Then Stop Timer0 Tmp = Tl0 Tmp2 = Th0 Set Test End If Return

Teres snipped-for-privacy@WYTNIJTOpoczta.fm napisał(a):

Przeanalizujmy Twój program ;)

Skąd wiadomo , że kiedy obsługiwałeś LCD nie została ustawiona flaga INT0 ? Bo jeśli została ustawiona , to po powyższej instrukcji odrazu wykona się przerwanie INT0 i nawet timera nie zdążysz wystartować :(

Skąd wiadomo że na wejściu INT0 nie występuje od iluśtam cykli stan "0" i timer rozpocznie zliczanie nie wtedy , kiedy należy , czyli natychmiast po pojawieniu się stanu niskiego na wej.INT0

Pojawiło się zbocze opadające i timer rozpoczął zliczanie ...

.. Ty go odrazu "w rogi" i stop , a powinien zliczać doputy , dopuki n wej. INT0 jest niski stan czyż nie ?

Po co te kombinacje ze zmiennymi pomocniczymi , nie prościej "Tmp3=Counter0" , a potem "Shift Tmp3,Left,1" zamiast matematyki ?

Ponarzekałem , a teraz rozwiązanie ( a istnieje ich wiele):

1.Startujemy Timer0 Do 1.Czekamy na wysoki stan na INT0 2.Zerujemy Test 3.Zerujemy Timer0 - przy wysokim stanie INT0 nie zlicza 4.Zerujemy flagę przerwania INT0 (TCON.1) - na wszelki wypadek 4.Zezwalamy na przerwania INT0 6.Czekamy na Test=1 - Timer0 rozpoczął zliczanie 7.Czekamy na wysoki stan na INT0 - koniec zliczania 9.Zabraniamy przerwań INT0 8.Counter0 do Temp3 - nie musimy zatrzymywac bo i tak już nie zlicza 10.Obliczamy i wyświetlamy 11.Skok do pkt. 1 Loop

Przerwanie_INT0: Ustaw Test Return

Tak należało by zbudować program , a bez przerwania też by się dało :)

Pozdrawiam Piotrek Sz.

PS Jakiś wymagający ten prowadzący ;)

U¿ytkownik "Piotrek Sz." snipped-for-privacy@gazeta.pl napisa³ w wiadomo¶ci news:crmkp2$9bp$ snipped-for-privacy@inews.gazeta.pl...

Z tego co widze w Proteusie to zgodnie z czestotliwoscia sygna³u wykonuj± siê przerwania, wiêc to chyba nie ma znaczenia

Racja

Ale w³a¶ciwie to timer ma zliczaæ czas tylko dla wysokiego stanu na INT0, st±d w³a¶nie ma ustwione GATE=EXTERNAL

Zak³adam ¿e wype³nienie 50% wiêc tu¿ po zakoñczeniu stanu wysokiego podwajam d³ugo¶æ zliczon± i wypisuje

"Tmp3=Counter0" ,

Nie wiedzia³em, ¿e co¶ takiego jest.

Bede dalej probowa³ Szczerze mówi±c to nie wiem czy powinienem u¿ywaæ instrukcji start i stop timer.Poza tym czy po instrukcji stop timer, a nastepnie start zaczyna od nowa zliczac od 0 ??

Pozdrawiam, Teres

M³ody doktorant ;)

Teres snipped-for-privacy@WYTNIJTOpoczta.fm napisał(a): ..

W takim razie nie są wyłączane .

Niestety , nie ma takiej możliwości.Timer0 jest "bramkowany" stanem niskim na wej. INT0 .

To zajmuje mniej pamięci programu i jest szybsze.

Nie musisz , wystarczy raz wystartować.

Jedynie reset sprzętowy zeruje liczniki lub zapisanie zer do liczników.

Gdybyś podał więcej informacji , co Twój uC ma robić , jaka max częstotliwość będzie podawana na INT0 , z jakim kwarcrm pracuje itd. , było by łatwiej Ci pomóc :) Można by np. podawać mierzony sygnał na INT0 i odwrócony o 180 stopni(1 maluśki tranzystor) na INT1 i wykorzystywać przerwanie INT1 do oczytywania licznika(ów) Timera0 ,a wtedy program byłby śmiesznie prosty ;).

Pozdrawiam Piotrek Sz.

U¿ytkownik "Piotrek Sz." snipped-for-privacy@gazeta.pl napisa³ w wiadomo¶ci news:crpjrt$lnb$ snipped-for-privacy@inews.gazeta.pl...

Faktycznie, ale w chyba w 89s52 jest wejscie ~INT0 takze sygna³ jest negowany juz na wejsciu i w efekcie wszystko sie zgadza, stan wysoki z generatora to stan niski na wejsciu uC. Nastepnie na generatorze stan niski i wywo³ujemy obs³ugê INT0

Zapamietam

Czyli powinienem zapisywac zera do liczników, racja ??

W³a¶ciwie to tylko mam zasymulowaæ u¿ycie uC jako miernika czêstotliwo¶ci. Sam sobie dobieram czêstotliwo¶æ kwarcu, a co za tym idzie maksymaln± czêstotliwo¶æ do zmierzenia. Co do tego mierzenia z uzyciem INT1, to jednak chyba mi sie nie przyda, bo jak pisa³em wej¶cia INT0 i INT1 s± zanegowane w uC, tak¿e mierze d³ugo¶æ trwania stanu wysokiego, no ew. zeby jeszcze patrzyæ na czas zanegowanego sygna³u na INT1, a potem je dodaæ. Tylko ¿e wtedy musia³bym chyba zrobiæ za³o¿enie ¿e sygna³ zawsze zaczyna sie od stanu wysokiego podawanego na ~INT0.

Pozdrawiam, Terespl

Teres snipped-for-privacy@WYTNIJTOpoczta.fm napisał(a):

Wybacz , ale pleciesz bzdury.Jeżeli GATE=1 (EXTERNAL) to licznik zlicza impulsy zewnętrzne lub wewnętrzne( u Ciebie wewnetrzne) tylko wtedy , kiedy TR0=1 i INT0=0 (P3.2=0) innej możliwości NIE MA , a ta kreseczka nad INTx oznacza stan aktywny niski , a nie negację.Widze że musisz jeszcze sporo poczytać o prockac z rodziny MCS-51.Proponuje zrobic doświadczenie i wyświetlać w kółko zawartość liczników Timera0 , a wejście INT0(P3.2) recznie łączyć z masą czyli ustawiac niski stan , a wtedy zobaczysz na LCD co sie dzieje z licznikami jak ustawisz "0" i nie podłączaj tego wejścia czasami do + by ustawić stan "1".

Nie zrozumiałeś o co mi chodzi :( Przerwanie INT1 nie ma nic mierzyc , tylko odczytać Timer0. Pozdrawiam Piotrek Sz.

U¿ytkownik "Piotrek Sz." snipped-for-privacy@gazeta.pl napisa³ w wiadomo¶ci news:crprqi$jvb$ snipped-for-privacy@inews.gazeta.pl...

Tak jest w pdf: GATE When TRx (in TCON) is set and GATE = 1, TIMER/COUNTERx will run only while INTx pin is high (hardware control). When GATE = 0, TIMER/COUNTERx will run only while TRx = 1 (software control).

A tak na innej stronie: GATE0 When this bit is set the timer will only run when INT0 (P3.2) is high. When this bit is clear the timer will run regardless of the state of INT0.

Wiêc wynika z tego ¿e przy Gate=External timer dzia³a tylko przy INT0 = high.

zanegowanego

Hmm sam nie wiem, moze faktycznie nie zakapowa³em, w sumie wyobrazalem sobie to tez tak: stan wysoki na INT0 , zanegowany na INT1 - licznik T0 zlicza czas stan sie zmienia stan niski na INT0, stan wysoki na INT1 - licznik T1 zaczyna zliczac, T0 przesta³ ..... bez sensu ;-)

Hmm czyli zostaje taka opcja mierzenie czasu trwania stanu wysokiego na INT0 (TR0) a potem INT1 do wywo³ania przerwania, tylko wydaje mi siê ¿e to przerwanie mo¿na spokojnie robiæ przy pomocy INT0.

Pozdrawiam, Teres

Teres snipped-for-privacy@WYTNIJTOpoczta.fm napisał(a): ..

No cóż , muszę przyznać się do błędu :( Mam taką książeczkę "Mikrokomputery jednoukładowe rodziny MCS-51" napisaną przez p. Andrzeja Rydzewskiego i w niej stoi tak : "Jeśli w słowie TMOD jest GATE równe 1 , to zewnętrzne lub wewnętrzne impulsy zegarowe są dodatkowo bramkowane zewnętrznym sygnałem z wejścia INTi.W tym przypadku , po programowym uruchomieniu licznika(wpisaniu jedynko do TRi) , zliczanie może być sterowane zewnętrznie - licznik pracuje tylko wtedy , kiedy INTi=0". Więc byłem na 100% pewien , że tak jest w rzeczywistości ,a tu figa z makiem. Jak to już nie można nikomu wierzyć ;) By odkupić winy ... .. Start Timer0 'skasowanie znacznika Do 'petla w programie If Test = 1 Then Shift Tmp3 , Left , 1 Cls Tmp3 = 100000 / Tmp3 Lcd "czestotliwosc=" Lowerline Lcd Tmp3 ; " Hz" ' Wait 1 Reset Test End If Loop End Wypisz: If Test = 0 Then 'czy wyświetlacz już sie wyrobił ? Tmp3 = Counter0 Set Test 'nowa wartość do wyświetlenia - gotowa. End If Counter0 = 0 'zerujemy , by przy zmianie stanu INT0 na 1 zliczał od zera Start Timer0 'trzeba wystartować Timer ,ponieważ przy operacjach na Counter0 'licznik jest zatrzymywany Return

Myślę , że powinno być OK.

Pozdrawiam Piotrek

U¿ytkownik "Piotrek Sz." snipped-for-privacy@gazeta.pl napisa³ w wiadomo¶ci news:crrubm$c2d$ snipped-for-privacy@inews.gazeta.pl...

Pewnie literówka w ksi±¿ce, zdarza sie czasem

Dzieki, prawie sobie poradzi³em, tylko nie wiedzia³em ze licznik trzeba od nowa startowaæ

Jeszcze raz dziêki, program napisany.

Pozdrawiam, Teres

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required