Witam.
Na wstępie przepraszam za mało czytelną nazwę w temacie ale nie wiedziałem jak inaczej opisać mój problem w tak małej ilości znaków.
Temat powinien brzmieć: [atmega8][bascom] Sterowanie 7-segmentowym wyświetlaczem LED przy pomocy portów B i C z odpowiednim przesunięciem bitowym. Próba rozwiązania problemu z mutipleksacją LED i odczytem z 1wire.
Opiszę delikatnie założenia, z których wychodzę i co chciałbym uzyskać, a także czym już dysponuje.
Chciałbym zbudować w oparciu o ATMEGA8 termometr z zegarkiem i zaprogramować go w języku BASCOM, a po przetestowaniu tego rozwiązania, spróbować napisać to samo w C. Układ dodatkowo musi co jakiś mały odstęp czasu wysyłać aktualną temperaturę z DSa lub klilku poprzez UART. A jako wzór czasu do zegarka będzie miał podłączony rezonator kwarcowy (zegarkowy).
Do ATMEGA8 mam podłączone następujące elementy (wszystko na płytce prototypowej):
- Tranzysotry do multipleksu są sterowane z PORTB.0 do PORTB.3.
- Przyciski mają być na PORTB.4 i PORTB.5.
- wyświetlacz LED 4x7-seg. Sterowanie wyświetlaniem cyfr odbywa się na portach PORTD.2 do PORTD.7 (linie do A do F) i PORTC.4, PORTC.5 (linie do G i DP).
Zdecydowałem się na takie podłączenie wyświetlacza, gdyż:
a. chciałem mieć możliwość wykorzystania UARTa na portach PD0 i PD1, więc z tego powodu nie mogłem sterować LEDem z całego PORTD.
b. chciałem mieć możliwość podłączenia zew. rezonatora kwarcowego więc nie mogłem wykorzystać PB.6 i PB.7 no i z tego powodu PORTB odpadł.
Aktualnie walczę z następującym problemem.
Jak przy włączonym wyświetlaniu LED w multipleksie na timer0 zsynchronizować transmisje 1wire, aby nie pojawiały się błędy podczas odczytu danych raz na (20-40sek lub czasami częściej)
Próbowałem sprawdzać wartość Timer0 przed przejściem w tryb komunikacji na 1wire. Ale nie udaje mi się dobrać odpowiedniej wartości. Albo źle podchodzę do tematu.
Nie wiem również czy przy wyłączeniu przerwań podczas transmisji 1wire uda mi się utrzymywać np. timer1, który będzie pracował w oparciu o zbocze opadające zew. kwarcu.
Czy, któryś z kolegów mogłby podpowiedzieć jak (i czy w ogóle) można usunąć błędy odczytu 1wire w takim projekcie i dodatkowo mieć stabilną współpracę z zew. rezonatorem kwarcowym, który ma być wzorcem czasu.
Z góry dziękuje za wszelkie sugestie.
Poniżej zamieszczam kod programu:
Na wstępie przepraszam za mało czytelną nazwę w temacie ale nie wiedziałem jak inaczej opisać mój problem w tak małej ilości znaków.
Temat powinien brzmieć: [atmega8][bascom] Sterowanie 7-segmentowym wyświetlaczem LED przy pomocy portów B i C z odpowiednim przesunięciem bitowym. Próba rozwiązania problemu z mutipleksacją LED i odczytem z 1wire.
Opiszę delikatnie założenia, z których wychodzę i co chciałbym uzyskać, a także czym już dysponuje.
Chciałbym zbudować w oparciu o ATMEGA8 termometr z zegarkiem i zaprogramować go w języku BASCOM, a po przetestowaniu tego rozwiązania, spróbować napisać to samo w C. Układ dodatkowo musi co jakiś mały odstęp czasu wysyłać aktualną temperaturę z DSa lub klilku poprzez UART. A jako wzór czasu do zegarka będzie miał podłączony rezonator kwarcowy (zegarkowy).
Do ATMEGA8 mam podłączone następujące elementy (wszystko na płytce prototypowej):
- Tranzysotry do multipleksu są sterowane z PORTB.0 do PORTB.3.
- Przyciski mają być na PORTB.4 i PORTB.5.
- wyświetlacz LED 4x7-seg. Sterowanie wyświetlaniem cyfr odbywa się na portach PORTD.2 do PORTD.7 (linie do A do F) i PORTC.4, PORTC.5 (linie do G i DP).
Zdecydowałem się na takie podłączenie wyświetlacza, gdyż:
a. chciałem mieć możliwość wykorzystania UARTa na portach PD0 i PD1, więc z tego powodu nie mogłem sterować LEDem z całego PORTD.
b. chciałem mieć możliwość podłączenia zew. rezonatora kwarcowego więc nie mogłem wykorzystać PB.6 i PB.7 no i z tego powodu PORTB odpadł.
Aktualnie walczę z następującym problemem.
Jak przy włączonym wyświetlaniu LED w multipleksie na timer0 zsynchronizować transmisje 1wire, aby nie pojawiały się błędy podczas odczytu danych raz na (20-40sek lub czasami częściej)
Próbowałem sprawdzać wartość Timer0 przed przejściem w tryb komunikacji na 1wire. Ale nie udaje mi się dobrać odpowiedniej wartości. Albo źle podchodzę do tematu.
Nie wiem również czy przy wyłączeniu przerwań podczas transmisji 1wire uda mi się utrzymywać np. timer1, który będzie pracował w oparciu o zbocze opadające zew. kwarcu.
Czy, któryś z kolegów mogłby podpowiedzieć jak (i czy w ogóle) można usunąć błędy odczytu 1wire w takim projekcie i dodatkowo mieć stabilną współpracę z zew. rezonatorem kwarcowym, który ma być wzorcem czasu.
Z góry dziękuje za wszelkie sugestie.
Poniżej zamieszczam kod programu:
$regfile = "m8def.dat"
$crystal = 8000000
$baud = 9600
'-- Wejscia przycisków
Config Portb.4 = Input
Config Portb.5 = Input
' -- podciągnięcie
Set Portb.4
Set Portb.5
' -- porty sterowania segmentami LED
Config Portd = Output
Config Portc.5 = Output
Config Portc.4 = Output
' -- tranzystory
Config Portb.0 = Output
Config Portb.1 = Output
Config Portb.2 = Output
Config Portb.3 = Output
T4 Alias Portb.0
T3 Alias Portb.1
T2 Alias Portb.2
T1 Alias Portb.3
S1 Alias Pinb.4
S2 Alias Pinb.5
Wyswietlacz1 Alias Portd
Wyswietlacz2 Alias Portc
Declare Sub Rozloz
Declare Sub Ds18b20
Config 1wire = Portc.3
'--- zmienne
Dim A As Byte
Dim Cyfra1 As Integer
Dim Cyfra2 As Integer
Dim Cyfra3 As Integer
Dim Cyfra4 As Integer
Dim Temp As Integer
Dim Temp1 As Integer
Dim T(9) As Byte
Dim Bd As Integer
Dim Ulamek As Integer
Dim Calosc As Integer
Dim Jakitimer0 As Byte
Dim Symbol As Byte
Dim I As Integer
'-- przerwania
Config Timer0 = Timer , Prescale = 64
'Config Timer1 = Timer , Prescale = 1 'konfiguracja liczników
Enable Interrupts
Enable Timer0
On Timer0 Tajmer1
Print "start programu"
Cls
I = 5
Do
Call Ds18b20
Temp = Calosc
Temp1 = Ulamek
Call Rozloz
Print "I = " ; I ; " Temperatura = " ; Calosc ; "." ; Ulamek ; " 'C" ; " Timer0 = " ; Timer0 ; " JakiTimer = " ; Jakitimer0
Loop
Sub Ds18b20
If Timer0 =< 180 Then
Jakitimer0 = Timer0
Disable Interrupts
1wreset
1wwrite &HCC
1wwrite &H44
Enable Interrupts
Waitms 750 'czas konwersji 750 ms
Disable Interrupts
1wreset
1wwrite &HCC
1wwrite &HBE
Enable Interrupts
T(1) = 1wread(9)
If Err = 1 Then
Wait 1
Print "ERROR"
Exit Sub
End If
Bd = Makeint(t(1) , T(2))
Bd = Bd * 10
Bd = Bd / 16
Ulamek = Bd Mod 10
Calosc = Bd / 10
Else
Jakitimer0 = Timer0
Incr I
Timer0 = 50
End If
End Sub
'-- rozkladanie liczby na cyfry
'Sub Rozloz
'
'Cyfra4 = Temp / 1000
'
'Temp = Temp Mod 1000
'
'Cyfra3 = Temp / 100
'
'Temp = Temp Mod 100
'
'Cyfra2 = Temp / 10
'
'Cyfra1 = Temp Mod 10
'
''If Znaczek = 1 Then Cyfra4 = 14
'''Else
''' Cyfra3 = Temp / 100
'''End If
'
'End Sub
Sub Rozloz
If Err = 0 Then
Temp = Temp Mod 100
Cyfra4 = Temp / 10
Cyfra3 = Temp Mod 10
Cyfra2 = 16
Cyfra1 = Temp1 Mod 10
Else
Cyfra4 = 10
Cyfra3 = 11
Cyfra2 = 11
Cyfra1 = 11
End If
End Sub
'---------------------- obsluga przerwania
Tajmer1:
Incr A
If A = 4 Then A = 0
Set T1
Set T2
Set T3
Set T4
Select Case A
Case 0:
Symbol = Lookup(cyfra1 , Dta)
Wyswietlacz1 = Symbol * 4
Symbol = Lookup(cyfra1 , Dta)
Wyswietlacz2 = Symbol / 4
Reset T1
Case 1:
Symbol = Lookup(cyfra2 , Dta)
Wyswietlacz1 = Symbol * 4
Symbol = Lookup(cyfra2 , Dta)
Wyswietlacz2 = Symbol / 4
'If Cyfra2 <> 0 Then Wyswietlacz = Lookup(cyfra2 , Dta)
'Wyswietlacz = Lookup(cyfra2 , Dta)
Reset T2
Case 2:
Symbol = Lookup(cyfra3 , Dta)
Wyswietlacz1 = Symbol * 4
Symbol = Lookup(cyfra3 , Dta)
Wyswietlacz2 = Symbol / 4
Reset T3
Case 3:
Symbol = Lookup(cyfra4 , Dta)
Wyswietlacz1 = Symbol * 4
Symbol = Lookup(cyfra4 , Dta)
Wyswietlacz2 = Symbol / 4
Reset T4
End Select
Return
'---- koniec przerwania
Dta:
' SEKWENCJA .GFEDCBA
' SEKWENCJA 11111111
Data &B11000000 , &B11111001 , &B10100100 , &B10110000 , &B10011001
Data &B10010010 , &B10000010 , &B11111000 , &B10000000 , &B10010000
Data &B10000110 , &B11001110 , &B11110001 , &B11000111
Data &B10111111 , &B11110111 , &B11101111
'Data &B10000110