logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

BASCOM – jak zapisać kolejne bity sygnału DCF bez tablicy bitów?

mass85 05 Maj 2008 01:01 2715 26
REKLAMA
  • #1 5106645
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    Czy mozna w jakis sposob utworzyc cos na wzor tablicy bitow, ktora niestety jest zabroniona w BASCOMie? Potrzebne mi to do zapisywania kolejno odebranych bitow sygnalu DCF.
  • REKLAMA
  • #2 5106647
    don diego
    Poziom 32  
    Posty: 1557
    Pomógł: 165
    Ocena: 63
    A nie może to być tablica bajtów?
  • #3 5106649
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    Byloby to swego rodzaju marnotrawstwo pamieci :)
  • #4 5106653
    Balu
    Poziom 38  
    Posty: 4397
    Pomógł: 323
    Ocena: 48
    Nie znam metody na tablicę bitów:/ Jedynie pojedyncze zmienne typu bit, albo jakąś funkcję operującą na tablicy bajtów i zlepiającą po 8 bitów...
  • Pomocny post
    #5 5106654
    don diego
    Poziom 32  
    Posty: 1557
    Pomógł: 165
    Ocena: 63
    Dlaczego? W jednym bajcie możesz zapisać osiem bitów. Nic się nie marnuje. Trzeba tylko odpowiednio interpretować dane.
  • REKLAMA
  • #6 5106663
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    No ale w przypadku zpaisywania bitow w zmiennej BYTE, skomplikuje mi sie caly program. A tablicy chcialem uzyc wlasnie w celu uproszczenia. Gdybym pisal program w assemblerze, to tam moznaby zajac pewien obszar pamieci i odwolywac sie do niego korzystajac ze wskaznika. Jednak czy warto przemycac kod assemblera w takim przypadku do Bascoma? Obawiam sie, ze to nie zadziala.

    Jesli nie znajdzie sie jakies lepsze rozwiazanie, to chyba rzeczywiscie bede wybrane, potrzebne mi bity zapisywal w pojedynczych zmiennych.
  • #7 5106667
    Balu
    Poziom 38  
    Posty: 4397
    Pomógł: 323
    Ocena: 48
    może napisz Sobie jednak prostą funkcję?
    poiedzmy że możesz mieć tych zmiennych 24 *3 byte*
    No to siup powiedzmy, że masz zmienna tab(3) as byte
    no i jazda...

    masz funkcje która zwraca przez ciało 0/1 (nie wiem czy może zwracać bool, więc najwyżej niech zwraca byte) w ciele funkcji dzielisz adres_bit przez 8
    całość to numer byteu w tablicy, reszta to numer bitu, no i dalej już prosto:) ew rozbij na dwie funkcje jedna piszącą drugą czytającą...
    Nie wydaje się to skomplikowane;)
  • #8 5106862
    szymtro
    Poziom 30  
    Posty: 1421
    Pomógł: 101
    Ocena: 59
    A ja napisze że jest taka możliwość.
    Autor nie sprecyzował który bascom go interesuje.

    Bascom 8051 ma taką możliwość bo mikrokontrolery serii '51 mają taką możliwość (na początku przedziału pamięci).
  • #10 5107015
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    No wlasnie, ale wtedy trzeba pisac program w assemblerze, o czym wspomnialem. BASCOM nie obsluguje tablic bitow, sprawdzalem juz w kompilatorze. BTW pisze pod Atmege16.

    Balu, myslalem, ze nie mozna zrobic czegos takiego
    DIM A as BYTE
    DIM B as BYTE
    
    A.B = 1
    


    Jednak przed chwila to sprawdzilem i kompilator nie zglasza bledu. Takze w tym wypadku rzeczywiscie nie trzeba sie specjalnie glowic nad ta tablica bitow. THX
  • #11 5108371
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    Jeszcze jedno pytanko:
    Config Timer0 = Timer , Prescale = 64

    Powyzsza linijka generuje mi nastepujacy blad:
    Error : 96 Line : 33 Prescale value must be 1,8,64,256 or 1024 [ 64] , in File : F:\STUDIA\DCF\PROGRAM\PROGRAM.BAS

    Rozumiecie, o co chodzi? Przeciez ustawilem poprawna wartosc preskalera...
    Co wiecej, jak zmienie ten timer na timer2, to wtedy sie kompiluje, jednak w symulatorze odmierza mi 8ms zamiast 2ms. Zegar to 8MHz, preskaler 64, timer liczy do 250. 8MHz/64/250 = 500Hz, czyli okres to 2ms... Jesli ustawie mu prescaler = 8, to wtedy odmierza 0.25ms, czyli poprawnie...

    Czy to z moim Bascomem jest cos nie tak?

    Abyscie mieli pelna jasnosc co do programu, to wkleje jego kod. Choc zaznaczam, ze jest jeszcze w powijakach :)
    
    
    $regfile = "m16def.dat"                                     'dyrektywa dla mikrokontrolera ATmega16
    $crystal = 8000000                                          'częstotliwość taktowania 8 MHz
    
    Ddra = &B11110000                                           'PA.7-4 wyjscia wybierajace wyswietlacz, PA.3-2 wejscia przyciskow
    Config Portc = Output                                       'port sterujacy wyswietlaczem
    Config Portd.2 = Input
    
    D1 Alias Porta.7                                            'linie wybierajace wyswietlacz
    D2 Alias Porta.6
    D3 Alias Porta.5
    D4 Alias Porta.4
    
    B1 Alias Pina.3                                             'przycisk 1   (aktywne 0)
    B2 Alias Pina.2                                             'przycisk 2   (aktywne 0)
    
    Dot Alias Portc.7                                           'linia ustawiajaca kropke
    
    Dcf_in Alias Pind.2
    
    Porta.3 = 1                                                 'ustawienie rezystorow podciagajacych
    Porta.2 = 1                                                 'dla wejsc obslugujacych przyciski
    
    Dim Hours As Byte
    Dim Minutes As Byte
    Dim Seconds As Byte
    Dim 2ms_cntr As Word
    
    Dim Synchronized As Bit                                     'czy wykryto szczeline synchronizacyjna
    Dim Int0_bit As Bit                                         'pamietana poprzednia wartosc bitu int0
    Int0_bit = Dcf_in
    
    Config Int0 = Change
    
    Config Timer2 = Timer , Prescale = 64
    Config Timer1 = Timer , Prescale = 1024
    
    Timer2 = 6
    Start Timer2
    
    On Int0 Interrupt_dcf
    On Timer2 Interrupt_2ms
    
    
    
    Enable Interrupts
    Enable Int0
    Enable Timer2
    
    Do
    Loop
    
    End                                                         'koniec programu
    
    
    Interrupt_2ms:
       Timer2 = Timer2 + 6
       2ms_cntr = 2ms_cntr + 1
       If 2ms_cntr = 500 Then
          Gosub Incr_sec
          2ms_cntr = 0
       End If
    
    Return
    
    
    Interrupt_dcf:
       Waitus 15
       If Dcf_in <> Int0_bit Then
          If Int0_bit = 0 Then
             Stop Timer1
             Int0_bit = 1
          Else
             Timer1 = 0
             Start Timer1
             Int0_bit = 0
          End If
       End If
    Return
    
    
    Incr_sec:
       Seconds = Seconds + 1
       If Seconds >= 60 Then
          Seconds = 0
          Gosub Incr_min
       End If
    Return
    
    Incr_min:
       Minutes = Minutes + 1
       If Minutes >= 60 Then
          Minutes = 0
          Gosub Incr_hour
       End If
    Return
    
    Incr_hour:
       Hours = Hours + 1
       If Hours >= 23 Then
          Hours = 0
       End If
    Return
  • #12 5108385
    Balu
    Poziom 38  
    Posty: 4397
    Pomógł: 323
    Ocena: 48
    U mnie się kompiluje bez błędów;)

    Dodano po 47 [sekundy]:

    Poza tym, tutaj będzi IMO błąd:
    
    Incr_hour:
       Hours = Hours + 1
       If Hours >= 23 Then
          Hours = 0
       End If
    Return
    
  • Pomocny post
    #13 5108577
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    mass85 napisał:
    ... BASCOM nie obsluguje tablic bitow...

    Bascom-AVR obsługuje tablice bitów , jednak z pewnymi ograniczeniami
    a)Tablica nie większa niż 256 bitów.
    b)index/numer bitu , MUSI być zmienną , choć właściwie niekoniecznie MUSI :D

    Piotrek
  • #14 5108907
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    Balu napisał:

    
    Incr_hour:
       Hours = Hours + 1
       If Hours >= 23 Then
          Hours = 0
       End If
    Return
    

    Oczywiscie, przed wklejeniem tego na forum zmienilem 24 na 23, bo wydalo mi sie to bledem :) Ale nie jest :P Co za roztargnienie.

    Wklejona werjsa kodu tez mi sie kompiluje, bo zostal zmienoiny timer0 na timer2. Sprobuj je zamienic. A timer w symulacji odmierza Ci 2ms czy 8ms?

    Zumek, sprobowalem czegos takiego:
    Hours = 5
    Dim Asd(hours) As Bit
    Hours = 4
    Asd(hours) = 1
    Hours = 1
    Asd(hours) = 1

    Mniejsza o nazwy zmiennych :) Okazuje sie, ze program sie skompilowal, ale w symulatorze dzialal zle. Traktowal Asd jak zmienna typu byte, po obu z powyzszych przypisan wartosc przechowywana byla rowna &B00000001.
  • #15 5124780
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    Niestety znow mam problem z kompilatorem.

    Pluje sie o prosta skladnie:
    
             If Dcf_array(1).index = 1 Then Display_values(1) = &B00000110
             Else Display_values(1) = &B00111111

    oraz troche bardziej skomplikowana:

    If((dcf_in = 0) And(dcf_failure = 0) And(synchronized = 1)) Then       'wykryto poczatek przerwy miedzy impulsami
             If(timer_val > 50ms And Timer_val < 150ms) Then    'odebrano bit 0
                Dcf_array(1).bits_rcvd = 0
                Bits_rcvd = Bits_rcvd + 1
             Elseif(timer_val >= 150ms And Timer_val < 250ms) Then       'odebrano 1
                Dcf_array(1).bits_rcvd = 1
                Bits_rcvd = Bits_rcvd + 1
             Else
                Dcf_failure = 1
                Synchronized = 0
             End If
    
    
    
          Else                                                  'wykryto impuls
             If(timer_val > 2000ms Or Timer_val < 600ms) Then   'niepoprawna przerwa miedzy impulsami
                Set Dcf_failure
                Bits_rcvd = 0
                Reset Synchronized
             Elseif(timer_val > 1500ms) Then                    'mamy bit synchronizacyjny
                Set Synchronized
                If(bits_rcvd = 58 And Dcf_failure = 0) Then Gosub Change_time
                Reset Dcf_failure
                Bits_rcvd = 0
             End If
    
     End If



    Kompilator generuje takie oto bledy:
    
    Error : 46    Line :   158   Assignment error [ELSE DISPLAY_VALUES(1): 0   &B00111111: 112]  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS
    Error : 44    Line :   269   2 variables expected  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS
    Error : 1     Line :   270   Unknown statement [IF(TIMER_VAL > 50MS AND TIMER_VAL < 150MS) THEN]  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS
    Error : 323   Line :   273   Label too long [150MS AND TIMER_VAL < 250MS) THEN]  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS
    Error : 46    Line :   273   Assignment error [ELSEIF(TIMER_VAL >): 0   150MS AND TIMER_VAL < 250MS) THEN: 0]  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS
    Error : 1     Line :   284   Unknown statement [IF(TIMER_VAL > 2000MS OR TIMER_VAL < 600MS) THEN]  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS
    Error : 1     Line :   288   Unknown statement [ELSEIF(TIMER_VAL > 1500MS) THEN]  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS
    Error : 44    Line :   290   2 variables expected  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS
    Error : 28    Line :   293   IF THEN expected  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS
    Error : 7     Line :   293   IF THEN expected [END IF in source  293]  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS
    Error : 28    Line :   295   IF THEN expected  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS
    Error : 7     Line :   295   IF THEN expected [END IF in source  295]  , in File : F:\STUDIA\DCF\PROGRAM\NONAME2.BAS


    Ma ktos pojecie dlaczego sie wysypuje? przeciez skladnia jest poprawna. Kombinowalem rowniez z wykorzystaniem nawiasow, ale bez skutku.

    Kod calego programu :
    
    $regfile = "m16def.dat"                                     'dyrektywa dla mikrokontrolera ATmega16
    $crystal = 8000000                                          'częstotliwość taktowania 8 MHz
    
    Ddra = &B11110000                                           'PA.7-4 wyjscia wybierajace wyswietlacz, PA.3-2 wejscia przyciskow
    Config Portc = Output                                       'port sterujacy wyswietlaczem
    Config Portd.2 = Input
    
    D1 Alias Porta.7                                            'linie wybierajace wyswietlacz
    D2 Alias Porta.6
    D3 Alias Porta.5
    D4 Alias Porta.4
    
    B1 Alias Pina.3                                             'przycisk 1   (aktywne 0)
    B2 Alias Pina.2                                             'przycisk 2   (aktywne 0)
    
    Porta.2 = 1
    Porta.3 = 1
    
    Dot Alias Portc.7                                           'linia ustawiajaca kropke
    
    Dcf_in Alias Pind.2
    
    Porta.3 = 1                                                 'ustawienie rezystorow podciagajacych
    Porta.2 = 1                                                 'dla wejsc obslugujacych przyciski
    
    Dim Hours As Byte
    Dim Minutes As Byte
    Dim Seconds As Byte
    Dim 2ms_cntr As Word
    Dim Display_nr As Byte
    
    Dim Umode As Byte                                           'zmienna trybu
    Dim Dcf_allowed As Bit                                      'czy mozna sie synchronizowac z DCF
    Dim Display_values(4) As Byte                               'tablica danych do wyswietlenia
    Dim Temp As Byte
    Dim Temp_segment As Byte
    Dim Timer_val As Word
    
    Dim Dcf_array(8) As Byte                                    'tablica bitow odebranych
    Dim Synchronized As Bit                                     'czy wykryto szczeline synchronizacyjna
    Dim Int0_bit As Bit                                         'pamietana poprzednia wartosc bitu int0
    Dim Dcf_failure As Bit                                      'flaga ustawiana, gdy wystapil jakikolwiek blad odbioru ramki
    Dim Bits_rcvd As Byte                                       'liczba odebranych bitow DCF
    Dim Index As Byte                                           'pomocnicza zmienna
    Int0_bit = Dcf_in
    
    Const 50ms = 234                                            'jeszcze nieprawidlowe liczby
    Const 150ms = 76867
    Const 250ms = 2344
    Const 1500ms = 3213244
    Const 2000ms = 45454544
    
    
    Config Int0 = Change
    
    Config Timer2 = Timer , Prescale = 64
    Config Timer1 = Timer , Prescale = 1024
    
    Timer2 = 6
    Start Timer2
    Hours = 12
    Minutes = 0
    Seconds = 0
    2ms_cntr = 0
    Umode = 0
    Dcf_allowed = 1
    Display_nr = 1
    
    
    On Int0 Interrupt_dcf
    On Timer2 Interrupt_2ms
    
    Enable Interrupts
    Enable Int0
    Enable Timer2
    
    '************************************************
                 'poczatek glownej petli
    '************************************************
    
    Do
       If B1 = 0 Then                                           ' Obsluga Przycisku 1(zmiana Trybu)
          Waitms 20
          If B1 = 0 Then
             Umode = Umode + 1
             If Umode > 5 Then Umode = 0
             Bitwait B1 , Set
          End If
       End If                                                   '===========
    
       Select Case Umode
          Case 0 :
                                                'tryb zegara
             Temp = Makebcd(hours)
             Temp_segment = Temp And &B00001111                 'jednostki godzin
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(3) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(4) = Temp_segment                   'dziesiatki godzin
    
    
             Temp = Makebcd(minutes)
             Temp_segment = Temp And &B00001111                 'jednostki minut
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki minut
    
             Temp = Seconds Mod 2
             If Temp = 0 Then
                Display_values(3) = Display_values(3) And &B01111111
                Display_values(3) = Display_values(3) Or &B10000000
             End If
             If Temp = 1 Then
                Display_values(3) = Display_values(3) And &B01111111
             End If
    
             If Synchronized = 1 Then
                Display_values(1) = Display_values(1) And &B01111111
                Display_values(1) = Display_values(1) Or &B10000000
             End If
    
    
          Case 1:
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 20
                If B2 = 0 Then Toggle Dcf_allowed
                Bitwait B2 , Set
             End If                                             '===========
    
             Display_values(4) = &B00111111                     'kod litery D
             Display_values(3) = &B00111001                     'kod litery C
             Display_values(2) = &B01110001                     'kod litery F
             If Dcf_allowed = 1 Then
                Display_values(1) = &B00000110                  'kod cyfry 1
                Else
                Display_values(1) = &B00111111                  'kod cyfry 0
             End If
    
          Case 2:
                                                       'ostatnio odebrany bit
             Index = Bits_rcvd - 1
             If Index > 59 Then Index = 59
             Temp = Makebcd(index)
             Temp_segment = Temp And &B00001111                 'jednostki nr bitu
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(3) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(4) = Temp_segment                   'dziesiatki numeru bitu
    
             Display_values(2) = &B01000000                     ' Kod Myslnika
             If Dcf_array(1).index = 1 Then Display_values(1) = &B00000110
             'If Dcf_array(1).index = 0 Then Display_values(1) = &B00111111
             Else Display_values(1) = &B00111111
    
          Case 3:                                               ' tryb nastawy godzin
             Display_values(4) = &B01110110                     'kod litery H
             Display_values(3) = &B01110110                     'kod litery H
    
             Temp = Makebcd(hours)                              'wyswietla aktualna godzine
             Temp_segment = Temp And &B00001111                 'jednostki godzin
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki godzin
    
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 20
                If B2 = 0 Then Gosub Incr_hour
                Bitwait B2 , Set
             End If
    
          Case 4:                                               ' tryb nastawy minut
             Display_values(4) = &B00110111                     'kod litery M
             Display_values(3) = &B00110111                     'kod litery M
    
             Temp = Makebcd(minutes)                            'wyswietla aktualna minute
             Temp_segment = Temp And &B00001111                 'jednostki minut
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki minut
    
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 20
                If B2 = 0 Then Gosub Incr_min
                Bitwait B2 , Set
             End If
    
          Case 5:                                               ' tryb nastawy sekund
             Display_values(4) = &B01101101                     'kod litery S
             Display_values(3) = &B01101101                     'kod litery S
    
             Temp = Makebcd(seconds)                            'wyswietla aktualna sekunde
             Temp_segment = Temp And &B00001111                 'jednostki sekund
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki sekund
    
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 20
                If B2 = 0 Then Seconds = 0
                Bitwait B2 , Set
             End If
    
       End Select
    
    
    Loop
    
    End
    
    '************************************************
                      'koniec programu
    '************************************************
    
    
    Interrupt_2ms:
       Timer2 = Timer2 + 6                                      ' Obsluga Timera
       Enable Interrupts
       2ms_cntr = 2ms_cntr + 1
       If 2ms_cntr = 500 Then
          Gosub Incr_sec
          2ms_cntr = 0
       End If
                                                 'obsluga wyswietlacza
       Display_nr = Display_nr + 1
       If Display_nr > 4 Then Display_nr = 1
    
       Select Case Display_nr
          Case 1:
             Reset D4
             Portc = Display_values(display_nr)
             Set D1
          Case 2:
             Reset D1
             Portc = Display_values(display_nr)
             Set D2
          Case 3:
             Reset D2
             Portc = Display_values(display_nr)
             Set D3
          Case 4:
             Reset D3
             Portc = Display_values(display_nr)
             Set D4
       End Select
    Return
    
    '************************************************
    Interrupt_dcf:
    
       Waitus 15                                                'eliminacja zaklocen impulsowych
       If Dcf_in <> Int0_bit Then
          Stop Timer1
          Timer_val = Timer1
          Timer1 = 0
          Start Timer1
          Int0_bit = Dcf_in
    
          If((dcf_in = 0) And(dcf_failure = 0) And(synchronized = 1)) Then       'wykryto poczatek przerwy miedzy impulsami
             If(timer_val > 50ms And Timer_val < 150ms) Then    'odebrano bit 0
                Dcf_array(1).bits_rcvd = 0
                Bits_rcvd = Bits_rcvd + 1
             Elseif(timer_val >= 150ms And Timer_val < 250ms) Then       'odebrano 1
                Dcf_array(1).bits_rcvd = 1
                Bits_rcvd = Bits_rcvd + 1
             Else
                Dcf_failure = 1
                Synchronized = 0
             End If
    
    
    
          Else                                                  'wykryto impuls
             If(timer_val > 2000ms Or Timer_val < 600ms) Then   'niepoprawna przerwa miedzy impulsami
                Set Dcf_failure
                Bits_rcvd = 0
                Reset Synchronized
             Elseif(timer_val > 1500ms) Then                    'mamy bit synchronizacyjny
                Set Synchronized
                If(bits_rcvd = 58 And Dcf_failure = 0) Then Gosub Change_time
                Reset Dcf_failure
                Bits_rcvd = 0
             End If
    
          End If
       End If
    Return
    
    '************************************************
    Change_time:
       Dim Dcf_mins As Byte
       Dim Dcf_hours As Byte
       Dim Crc As Bit
       Dim I As Byte
    
       Index = 21
       For I = 0 To 6
          Crc = Crc + Dcf_array(1).index
          Dcf_mins.i = Dcf_array(1).index
          Index = Index + 1
       Next
       If Crc <> Dcf_array(1).28 Then Return
       Dcf_mins = Makedec(dcf_mins)
       If Dcf_mins > 60 Then Return
    
       Index = 29
       For I = 0 To 5
          Crc = Crc + Dcf_array(1).index
          Dcf_hours.i = Dcf_array(1).index
          Index = Index + 1
       Next
       If Crc <> Dcf_array(1).35 Then Return
       Dcf_hours = Makedec(dcf_hours)
       If Dcf_hours > 24 Then Return
    
       Hours = Dcf_hours
       Minutes = Dcf_mins
       Seconds = 0
    
    Return
    
    
    '************************************************
    Incr_sec:
       Seconds = Seconds + 1
       If Seconds > 59 Then
          Seconds = 0
          Gosub Incr_min
       End If
    Return
    
    Incr_min:
       Minutes = Minutes + 1
       If Minutes > 59 Then
          Minutes = 0
          Gosub Incr_hour
       End If
    Return
    
    Incr_hour:
       Hours = Hours + 1
       If Hours > 23 Then
          Hours = 0
       End If
    Return
    '************************************************
    
    
    7seg_code:
    Data &B00111111 , &B00000110 , &B01011011 , &B01001111 , &B01100110,
    Data &B01101101 , &B01111101 , &B00000111 , &B01111111 , &B01101111
  • REKLAMA
  • #16 5124841
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    mass85 napisał:
    Niestety znow mam problem z kompilatorem.

    Pluje sie o prosta skladnie:
    
             If Dcf_array(1).index = 1 Then Display_values(1) = &B00000110
             Else Display_values(1) = &B00111111

    Składnia jest rzeczywiście prosta , tyle że nie Basic-owa :|
    
             If Dcf_array(1).index = 1 Then 
                Display_values(1) = &B00000110
             Else 
                Display_values(1) = &B00111111
             End If
    

    lub
    
    'w 1 linii
       If Dcf_array(1).index = 1 Then : Display_values(1) = &B00000110 : Else : Display_values(1) = &B00111111 : End If
    
    


    Piotrek
  • #17 5125157
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    Ok, dzieki. A co jest nie tak z warunkami logicznymi w podprogramie Interrupt_dcf?
  • REKLAMA
  • #18 5130144
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    Nikt nie jest w stanie pomoc? Nikt nie wie, dlaczego kompilator zglasza blad w ponizszym fragmencie?

          If((dcf_in = 0) And(dcf_failure = 0) And(synchronized = 1)) Then       'wykryto poczatek przerwy miedzy impulsami 
             If(timer_val > 50ms And Timer_val < 150ms) Then    'odebrano bit 0 
                Dcf_array(1).bits_rcvd = 0 
                Bits_rcvd = Bits_rcvd + 1 
             Elseif(timer_val >= 150ms And Timer_val < 250ms) Then       'odebrano 1 
                Dcf_array(1).bits_rcvd = 1 
                Bits_rcvd = Bits_rcvd + 1 
             Else 
                Dcf_failure = 1 
                Synchronized = 0 
             End If 
    
    
    
          Else                                                  'wykryto impuls 
             If(timer_val > 2000ms Or Timer_val < 600ms) Then   'niepoprawna przerwa miedzy impulsami 
                Set Dcf_failure 
                Bits_rcvd = 0 
                Reset Synchronized 
             Elseif(timer_val > 1500ms) Then                    'mamy bit synchronizacyjny 
                Set Synchronized 
                If(bits_rcvd = 58 And Dcf_failure = 0) Then Gosub Change_time 
                Reset Dcf_failure 
                Bits_rcvd = 0 
             End If 
    
          End If
  • #19 5130234
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    mass85 napisał:
    Nikt nie jest w stanie pomoc? Nikt nie wie, dlaczego kompilator zglasza blad w ponizszym fragmencie?

    Ależ wiedza , tylko myśleli , że sam znajdziesz przyczynę ;)
    Rozwiązanie: w warunkach If,Elseif , zastąp nawiasy spacjami.
    Poza tym , ja tu jeszcze widzę niezły bur.... tzn. nieporządek , który po poprawieniu błędów w warunkach , spowoduje pojawienie się kolejnych :|

    Piotrek
  • #20 5131100
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    Tak, po usunieciu nawiasow pojawil sie blad dotyczacy dodawania bitow. Poradzilem sobie z tym, zastepujac + funkcja Xor.

    Jednak nadal jest jeden niezrozumialy dla mnie blad zwiazany z warunkiem logicznym.
    
    If Timer_val > 2000ms Or Timer_val < 600ms Then
    

    Tutaj pojawia sie taki komunikat:

    Error : 242 Line : 286 Source variable does not match the target variable [ 0] , in File : F:\STUDIA\DCF\PROGRAM\DCF.BAS

    Myslalem, ze problemem jest nazwa stalych zaczynajaca sie od cyfry. Wedlug ksiazki Wiazani w przypadku zmiennych taka nazwa jest niedozwolona. Jednak okazuje sie, ze zmienna o nazwie 2ms_cntr mi sie skompilowala. Tak czy inaczej sprobowalem zmodyfikowac nazwy stalych, ale nie dalo to efektu.

    Wiec co jest nie tak?

    Edit: W linijce, w ktorej pojawil sie blad, zmienilem zdefiniowane stale po prostu na liczby. Program kompiluje sie bez bledow... Tylko kurcze dlaczego w innych miejscach kompilator akceptuje mi te zdefiniowane stale, a w tej linii akurat nie???
  • #21 5132307
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    mass85 napisał:
    ...
    Jednak nadal jest jeden niezrozumialy dla mnie blad zwiazany z warunkiem logicznym.
    
    If Timer_val > 2000ms Or Timer_val < 600ms Then
    

    Tutaj pojawia sie taki komunikat:

    Error : 242 Line : 286 Source variable does not match the target variable [ 0] , in File : F:\STUDIA\DCF\PROGRAM\DCF.BAS


    Ja nie widzę w Twoim kodzie ani zmiennej ani stałej o nazwie 600ms
    
    Const 50ms = 234                                            'jeszcze nieprawidlowe liczby
    Const 150ms = 76867
    Const 250ms = 2344
    Const 1500ms = 3213244
    Const 2000ms = 45454544
    


    Następny kwiatek w/w linii kodu (If Timer_val > 2000ms ... , to sprawdzenie czy zmienna Timer_val typu WORD - gdzie maksymalna wartość tej zmiennej może wynosić 65535 - jest większa od liczby 45454544 (Const 2000ms=45454544) :| Toż to nonsens , nie uważasz :?:
    Mówię Ci: zastanów sie 10 razy zanim coś "chlapniesz" , bo ... będziesz miał kłopoty i to nieliche ;) Powiadam Ci , że tych kwiatków jest więcej ;)

    Piotrek
    PS
    No , chociaż z tym dodawaniem do bitu,zrobiłeś porządek :D
  • #22 5133060
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    Alez jest komentarz, ze liczby sa nieprawidlowe. Wklepalem byle co, zeby pozniej sobie dokladne wartosci obliczyc, a nie zawracac sobie glowy duperelami w tamtym czasie.

    Co masz na mysli piszac "chlapniesz"? Chlapanie tutaj na forum czy w swoim kodzie? :)

    Hm skoro widzisz jeszce jakies kwiatki, to bede wdzieczny, jesli sie nimi podzielisz ze mna. :) Ja juz niestety wiecej bledow nie dostrzegam, a kompilator rowniez. Tylko jedna rzecz mnie martwi - w symulacji Timer2 odmierza mi odcinki 8ms, a nie 2ms... Sprawdzilem ustawienia taktowania uC, jest 8MHz. Preskaler jest ustawiony na 64, licznik zlicza 250impulsow. 8MHz/64/250 = 500Hz, zatem odcinki czasu powinny trwac 2ms.

    Wkleje najswiezsza wersje kodu.
    
    $regfile = "m16def.dat"                                     'dyrektywa dla mikrokontrolera ATmega16
    $crystal = 8000000                                          'częstotliwość taktowania 8 MHz
    
    Ddra = &B11110000                                           'PA.7-4 wyjscia wybierajace wyswietlacz, PA.3-2 wejscia przyciskow
    Config Portc = Output                                       'port sterujacy wyswietlaczem
    Config Portd.2 = Input                                      'port DCF_in (INT0)
    
    D1 Alias Porta.7                                            'linie wybierajace wyswietlacz
    D2 Alias Porta.6
    D3 Alias Porta.5
    D4 Alias Porta.4
    
    B1 Alias Pina.3                                             'przycisk 1   (aktywne 0)
    B2 Alias Pina.2                                             'przycisk 2   (aktywne 0)
    
    Porta = &B11111100
    
    
    Dot Alias Portc.7                                           'linia ustawiajaca kropke
    
    Dcf_in Alias Pind.2
    
    Porta.3 = 1                                                 'ustawienie rezystorow podciagajacych
    Porta.2 = 1                                                 'dla wejsc obslugujacych przyciski
    
    Dim Hours As Byte
    Dim Minutes As Byte
    Dim Seconds As Byte
    Dim T2ms_cntr As Word
    Dim Display_nr As Byte
    
    Dim Umode As Byte                                           'zmienna trybu
    Dim Dcf_allowed As Bit                                      'czy mozna sie synchronizowac z DCF
    Dim Display_values(4) As Byte                               'tablica danych do wyswietlenia
    Dim Temp As Byte
    Dim Temp_segment As Byte
    Dim Timer_val As Word
    
    Dim Dcf_array(8) As Byte                                    'tablica bitow odebranych
    Dim Synchronized As Bit                                     'czy wykryto szczeline synchronizacyjna
    Dim Int0_bit As Bit                                         'pamietana poprzednia wartosc bitu int0
    Dim Dcf_failure As Bit                                      'flaga ustawiana, gdy wystapil jakikolwiek blad odbioru ramki
    Dim Bits_rcvd As Byte                                       'liczba odebranych bitow DCF
    Dim Index As Byte                                           'pomocnicza zmienna
    Int0_bit = Dcf_in
    
    Const T50ms = 390
    Const T150ms = 1171
    Const T250ms = 1953
    Const T600ms = 4684
    Const T1500ms = 11718
    Const T2000ms = 15625
    
    
    Config Int0 = Change
    
    Config Timer2 = Timer , Prescale = 64
    Config Timer1 = Timer , Prescale = 1024
    
    Timer2 = 6
    Start Timer2
    Hours = 12
    Minutes = 0
    Seconds = 0
    T2ms_cntr = 0
    Umode = 0
    Dcf_allowed = 1
    Display_nr = 1
    
    
    On Int0 Interrupt_dcf
    On Timer2 Interrupt_2ms
    
    Enable Interrupts
    Enable Int0
    Enable Timer2
    
    '************************************************
                 'poczatek glownej petli
    '************************************************
    
    Do
       If B1 = 0 Then                                           ' Obsluga Przycisku 1(zmiana Trybu)
          Waitms 20
          If B1 = 0 Then
             Umode = Umode + 1
             If Umode > 5 Then Umode = 0
             Bitwait B1 , Set
          End If
       End If                                                   '===========
    
       Select Case Umode
          Case 0 :
                                                'tryb zegara
             Temp = Makebcd(hours)
             Temp_segment = Temp And &B00001111                 'jednostki godzin
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(3) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(4) = Temp_segment                   'dziesiatki godzin
    
    
             Temp = Makebcd(minutes)
             Temp_segment = Temp And &B00001111                 'jednostki minut
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki minut
    
             Temp = Seconds Mod 2
             If Temp = 0 Then
                Display_values(3) = Display_values(3) And &B01111111
                Display_values(3) = Display_values(3) Or &B10000000
             End If
             If Temp = 1 Then
                Display_values(3) = Display_values(3) And &B01111111
             End If
    
             If Synchronized = 1 Then
                Display_values(1) = Display_values(1) And &B01111111
                Display_values(1) = Display_values(1) Or &B10000000
             End If
    
    
          Case 1:
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 20
                If B2 = 0 Then Toggle Dcf_allowed
                Bitwait B2 , Set
             End If                                             '===========
    
             Display_values(4) = &B00111111                     'kod litery D
             Display_values(3) = &B00111001                     'kod litery C
             Display_values(2) = &B01110001                     'kod litery F
             If Dcf_allowed = 1 Then
                Display_values(1) = &B00000110                  'kod cyfry 1
             Else
                Display_values(1) = &B00111111                  'kod cyfry 0
             End If
    
          Case 2:
                                                       'ostatnio odebrany bit
             Index = Bits_rcvd - 1
             If Index > 58 Then Index = 58
             Temp = Makebcd(index)
             Temp_segment = Temp And &B00001111                 'jednostki nr bitu
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(3) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(4) = Temp_segment                   'dziesiatki numeru bitu
    
             Display_values(2) = &B01000000                     ' Kod Myslnika
             If Dcf_array(1).index = 1 Then
                Display_values(1) = &B00000110
             Else
                Display_values(1) = &B00111111
             End If
    
          Case 3:                                               ' tryb nastawy godzin
             Display_values(4) = &B01110110                     'kod litery H
             Display_values(3) = &B01110110                     'kod litery H
    
             Temp = Makebcd(hours)                              'wyswietla aktualna godzine
             Temp_segment = Temp And &B00001111                 'jednostki godzin
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki godzin
    
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 20
                If B2 = 0 Then Gosub Incr_hour
                Bitwait B2 , Set
             End If
    
          Case 4:                                               ' tryb nastawy minut
             Display_values(4) = &B00110111                     'kod litery M
             Display_values(3) = &B00110111                     'kod litery M
    
             Temp = Makebcd(minutes)                            'wyswietla aktualna minute
             Temp_segment = Temp And &B00001111                 'jednostki minut
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki minut
    
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 20
                If B2 = 0 Then Gosub Incr_min
                Bitwait B2 , Set
             End If
    
          Case 5:                                               ' tryb nastawy sekund
             Display_values(4) = &B01101101                     'kod litery S
             Display_values(3) = &B01101101                     'kod litery S
    
             Temp = Makebcd(seconds)                            'wyswietla aktualna sekunde
             Temp_segment = Temp And &B00001111                 'jednostki sekund
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki sekund
    
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 20
                If B2 = 0 Then Seconds = 0
                Bitwait B2 , Set
             End If
    
       End Select
    
    
    Loop
    
    End
    
    '************************************************
                      'koniec programu
    '************************************************
    
    
    Interrupt_2ms:
       Timer2 = Timer2 + 6                                      ' Obsluga Timera
       Enable Interrupts
       T2ms_cntr = T2ms_cntr + 1
       If T2ms_cntr = 500 Then
          Gosub Incr_sec
          T2ms_cntr = 0
       End If
                                                 'obsluga wyswietlacza
       Display_nr = Display_nr + 1
       If Display_nr > 4 Then Display_nr = 1
    
       Select Case Display_nr
          Case 1:
             Set D4
             Portc = Display_values(display_nr)
             Reset D1
          Case 2:
             Set D1
             Portc = Display_values(display_nr)
             Reset D2
          Case 3:
             Set D2
             Portc = Display_values(display_nr)
             Reset D3
          Case 4:
             Set D3
             Portc = Display_values(display_nr)
             Reset D4
       End Select
    Return
    
    '************************************************
    Interrupt_dcf:
    
       Waitus 15                                                'eliminacja zaklocen impulsowych
       If Dcf_in <> Int0_bit Then
          Stop Timer1
          Timer_val = Timer1
          Timer1 = 0
          Start Timer1
          Int0_bit = Dcf_in
    
          If Dcf_in = 0 And Dcf_failure = 0 And Synchronized = 1 Then       'wykryto poczatek przerwy miedzy impulsami
             If Timer_val > T50ms And Timer_val < T150ms Then   'odebrano bit 0
                Dcf_array(1).bits_rcvd = 0
                Bits_rcvd = Bits_rcvd + 1
             Elseif Timer_val >= T150ms And Timer_val < T250ms Then       'odebrano 1
                Dcf_array(1).bits_rcvd = 1
                Bits_rcvd = Bits_rcvd + 1
             Else
                Dcf_failure = 1
                Synchronized = 0
             End If
    
    
    
          Else                                                  'wykryto impuls
             If Timer_val > T2000ms Or Timer_val < T600ms Then  'niepoprawna przerwa miedzy impulsami
                Set Dcf_failure
                Bits_rcvd = 0
                Reset Synchronized
             Elseif Timer_val > T1500ms Then                    'mamy bit synchronizacyjny
                Set Synchronized
                If Bits_rcvd = 58 And Dcf_failure = 0 Then Gosub Change_time
                Reset Dcf_failure
                Bits_rcvd = 0
             End If
    
          End If
       End If
    Return
    
    '************************************************
    Change_time:
       Dim Dcf_mins As Byte
       Dim Dcf_hours As Byte
       Dim Crc As Bit
       Dim I As Byte
    
       Index = 21
       For I = 0 To 6
          Crc = Crc Xor Dcf_array(1).index
          Dcf_mins.i = Dcf_array(1).index
          Index = Index + 1
       Next
       If Crc <> Dcf_array(1).28 Then Return
       Dcf_mins = Makedec(dcf_mins)
       If Dcf_mins > 60 Then Return
    
       Index = 29
       For I = 0 To 5
          Crc = Crc Xor Dcf_array(1).index
          Dcf_hours.i = Dcf_array(1).index
          Index = Index + 1
       Next
       If Crc <> Dcf_array(1).35 Then Return
       Dcf_hours = Makedec(dcf_hours)
       If Dcf_hours > 24 Then Return
    
       Hours = Dcf_hours
       Minutes = Dcf_mins
       Seconds = 0
    
    Return
    
    
    '************************************************
    Incr_sec:
       Seconds = Seconds + 1
       If Seconds > 59 Then
          Seconds = 0
          Gosub Incr_min
       End If
    Return
    
    Incr_min:
       Minutes = Minutes + 1
       If Minutes > 59 Then
          Minutes = 0
          Gosub Incr_hour
       End If
    Return
    
    Incr_hour:
       Hours = Hours + 1
       If Hours > 23 Then
          Hours = 0
       End If
    Return
    '************************************************
    
    
    7seg_code:
    Data &B00111111 , &B00000110 , &B01011011 , &B01001111 , &B01100110,
    Data &B01101101 , &B01111101 , &B00000111 , &B01111111 , &B01101111
  • #23 5133779
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    mass85 napisał:
    ...Co masz na mysli piszac "chlapniesz"? Chlapanie tutaj na forum czy w swoim kodzie? :)

    Myślałem o kodzie ;)
    mass85 napisał:

    Hm skoro widzisz jeszce jakies kwiatki, to bede wdzieczny, jesli sie nimi podzielisz ze mna. :)

    Jasne
    
    Dcf_array(1).28
    'dla const index
    Dcf_array(4).4   dla Dcf_array() As Byte
    

    Index jest const , a ma być variable.
    Tzn. może być const , ale trzeba to policzyć i zapisać j/w.
    mass85 napisał:

    Tylko jedna rzecz mnie martwi - w symulacji Timer2 odmierza mi odcinki 8ms, a nie 2ms... Sprawdzilem ustawienia taktowania uC, jest 8MHz. Preskaler jest ustawiony na 64, licznik zlicza 250impulsow. 8MHz/64/250 = 500Hz, zatem odcinki czasu powinny trwac 2ms.

    Ot , cały Bascom - czasami tak ma ;)
    Polecam symulator z AVRStudio - czas pomiedzy przerwaniami T2 pokazuje prawidło ~2000uS.

    Inne kwiatki "wyrosna" , załadujesz kod do uC.
    Tyle ja , reszta już Ty

    Piotrek
  • #24 5138214
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    zumek napisał:

    Inne kwiatki "wyrosna" , załadujesz kod do uC.
    Tyle ja , reszta już Ty

    Kurde, ale sie nade mna znecasz... :P Wiesz, ale nie napiszesz.
  • #25 5139685
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    mass85 napisał:
    ...Kurde, ale sie nade mna znecasz... :P Wiesz, ale nie napiszesz.

    Powiadasz , że się znęcam :?: Ja to nazywam ... motywacją
    Zmotywować kogoś do poszerzania wiedzy , jest podobno bardzo pożyteczne :D

    Piotrek
  • #26 5141300
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    No przeciez caly czas poszerzam swoja wiedze, masz w tym swoj udzial. Czy jak wytkniesz tutaj moje bledy, to nie poszerze dzieki temu swojej wiedzy? :D

    Spoko, jutro albo w piatek odpale program na procku i zobaczymy co z tego wyjdzie :P
  • #27 5147906
    mass85
    Poziom 11  
    Posty: 22
    Ocena: 2
    Zaprogramowalem procek. Oto spostrzezenia.

    Zegar odlicza poprawnie czas, ustawienia godziny dzialaja poprawnie.

    Wystapil natomiast problem z miganiem kropki oddzielajacej jednostki godizn od dziesiatek minut. Powinna ona zapalac sie na sekunde, a potem gasnac na sekunde. Jednak okazuje sie, ze w trakcie sekundy, w ktorej powinna sie swiecic, ona migocze.

    Zmienilem odpowiednie linie kodu na:
     Temp = Seconds Mod 2
    If Temp = 0 Then
               Set Display_values(3).7       'zgas kropke
             End If
             If Temp = 1 Then
                Reset Display_values(3).7    'zapal kropke
             End If

    Jednak to zaowoocowalo takim samym swiecenim kropki, ale na wyswietlaczu 1 - jednostki minut (wnoiskuje, ze zostal ustawiany i gaszony bit Display.values(1).7)

    Jednak gdy zmienilem powyzszy kod, na ponizszy:
     Temp = Seconds Mod 2
    If Temp = 0 Then
               Set Display_values(3).index
             End If
             If Temp = 1 Then
                Reset Display_values(3).index
             End If

    to teraz mrugala wlasciwa kropka, ale znow w niewlasciwy sposob (wrocilem do punktu wyjscia)...

    Ostatecznie doszedlem do wniosku, ze ten kod powinien, byc w przerwaniu, w ktorym obsluguje wyswietlacz, poniewaz w przeciwnym wypadku przerwanie moze trafic na moment, gdy jeszcze nie zdazylismy wejsc do warunku i wyzerowac bitu kropki w tablicy.
          Case 3:                'obsluga wyswietlacza nr 3(jednostki godzin)
             Reset D2
             Portc = Display_values(display_nr)
             If Umode = 0 Then
                Temp = Seconds Mod 2
                If Temp = 0 Then Reset Portc.7
             End If
    
             Set D3

    Zniknelo migotanie, jednak teraz ta kropka swieci sie jakos slabo, znaczy sie slabiej niz cyfry. Ale ok, w sumie to moze byc wina po prostu samego wyswietlacza.

    Zauwazylem rowniez, ze nigdy nie nastepuje aktualizacja czasu z DCFu. Blad byl tutaj (wklejam poprawiona wersje, wczesniej bylo Bits_rcvd = 58):
    If Bits_rcvd = 59 And Dcf_failure = 0 Then Gosub Change_time


    Ponadto dodalem dodatkowa korekcje bledow - sprawdzanie poprawnosci bitow, ktore maja stale wartosci.
    Wprowadzilem rowniez sygnalizacje tego, czy wyswietlany czas jest zgodny z DCF.

    Wklejam ponizej aktualna wersje kodu:
    
    $regfile = "m16def.dat"                                     'dyrektywa dla mikrokontrolera ATmega16
    $crystal = 8000000                                          'częstotliwość taktowania 8 MHz
    
    Ddra = &B11110000                                           'PA.7-4 wyjscia wybierajace wyswietlacz, PA.3-2 wejscia przyciskow
    Config Portc = Output                                       'port sterujacy wyswietlaczem
    Config Portd.2 = Input                                      'port DCF_in (INT0)
    
    D1 Alias Porta.7                                            'linie wybierajace wyswietlacz
    D2 Alias Porta.6
    D3 Alias Porta.5
    D4 Alias Porta.4
    
    B1 Alias Pina.3                                             'przycisk 1   (aktywne 0)
    B2 Alias Pina.2                                             'przycisk 2   (aktywne 0)
    
    Porta = &B11111100
    
    
    Dot Alias Portc.7                                           'linia ustawiajaca kropke
    
    Dcf_in Alias Pind.2
    
    Porta.3 = 1                                                 'ustawienie rezystorow podciagajacych
    Porta.2 = 1                                                 'dla wejsc obslugujacych przyciski
    
    Dim Hours As Byte
    Dim Minutes As Byte
    Dim Seconds As Byte
    Dim T2ms_cntr As Word
    Dim Display_nr As Byte
    Dim Dcf_mins As Byte
    Dim Dcf_hours As Byte
    
    Dim Umode As Byte                                           'zmienna trybu
    Dim Dcf_allowed As Bit                                      'czy mozna sie synchronizowac z DCF
    Dim Display_values(4) As Byte                               'tablica danych do wyswietlenia
    Dim Temp As Byte
    Dim Temp_segment As Byte
    Dim Timer_val As Word
    
    Dim Dcf_array(8) As Byte                                    'tablica bitow odebranych
    Dim Synchronized As Bit                                     'czy wykryto szczeline synchronizacyjna
    Dim Int0_bit As Bit                                         'pamietana poprzednia wartosc bitu int0
    Dim Dcf_failure As Bit                                      'flaga ustawiana, gdy wystapil jakikolwiek blad odbioru ramki
    Dim Bits_rcvd As Byte                                       'liczba odebranych bitow DCF
    Dim Index As Byte                                           'pomocnicza zmienna
    Int0_bit = Dcf_in
    
    Const T50ms = 390
    Const T150ms = 1171
    Const T250ms = 1953
    Const T600ms = 4684
    Const T1500ms = 11718
    Const T2000ms = 15625
    
    
    Config Int0 = Change
    
    Config Timer2 = Timer , Prescale = 64
    Config Timer1 = Timer , Prescale = 1024
    
    Timer2 = 6
    Start Timer2
    Hours = 12
    Minutes = 0
    Seconds = 0
    T2ms_cntr = 0
    Umode = 0
    Dcf_allowed = 1
    Display_nr = 1
    Dcf_mins = 100
    
    
    On Int0 Interrupt_dcf
    On Timer2 Interrupt_2ms
    
    Enable Interrupts
    Enable Int0
    Enable Timer2
    
    '************************************************
                 'poczatek glownej petli
    '************************************************
    
    Do
       If B1 = 0 Then                                           ' Obsluga Przycisku 1(zmiana Trybu)
          Waitms 30
          If B1 = 0 Then
             Umode = Umode + 1
             If Umode > 5 Then Umode = 0
             Bitwait B1 , Set
          End If
       End If                                                   '===========
    
       Select Case Umode
          Case 0 :
                                                'tryb zegara
             Temp = Makebcd(hours)
             Temp_segment = Temp And &B00001111                 'jednostki godzin
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(3) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(4) = Temp_segment                   'dziesiatki godzin
    
    
             Temp = Makebcd(minutes)
             Temp_segment = Temp And &B00001111                 'jednostki minut
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki minut
    
    
    
    
          Case 1:
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 30
                If B2 = 0 Then Toggle Dcf_allowed
                If Dcf_allowed = 0 Then Dcf_mins = 100
                Bitwait B2 , Set
             End If                                             '===========
    
             Display_values(4) = &B10000001                     'kod litery D
             Display_values(3) = &B11001001                     'kod litery C
             Display_values(2) = &B11101000                     'kod litery F
             If Dcf_allowed = 1 Then
                Display_values(1) = &B10110111                  'kod cyfry 1
             Else
                Display_values(1) = &B10000001                  'kod cyfry 0
             End If
    
          Case 2:
                                                       'ostatnio odebrany bit
             Index = Bits_rcvd - 1
             If Index > 58 Then Index = 58
             Temp = Makebcd(index)
             Temp_segment = Temp And &B00001111                 'jednostki nr bitu
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(3) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(4) = Temp_segment                   'dziesiatki numeru bitu
    
             Display_values(2) = &B11111110                     ' Kod Myslnika
             If Dcf_array(1).index = 1 Then
                Display_values(1) = &B10110111
             Else
                Display_values(1) = &B10000001
             End If
    
          Case 3:                                               ' tryb nastawy godzin
             Display_values(4) = &B10100100                     'kod litery H
             Display_values(3) = &B10100100                     'kod litery H
    
             Temp = Makebcd(hours)                              'wyswietla aktualna godzine
             Temp_segment = Temp And &B00001111                 'jednostki godzin
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki godzin
    
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 30
                If B2 = 0 Then Gosub Incr_hour
                Bitwait B2 , Set
             End If
    
          Case 4:                                               ' tryb nastawy minut
             Display_values(4) = &B10100001                     'kod litery M
             Display_values(3) = &B10100001                     'kod litery M
    
             Temp = Makebcd(minutes)                            'wyswietla aktualna minute
             Temp_segment = Temp And &B00001111                 'jednostki minut
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki minut
    
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 30
                If B2 = 0 Then Gosub Incr_min
                Bitwait B2 , Set
             End If
    
          Case 5:                                               ' tryb nastawy sekund
             Display_values(4) = &B10011000                     'kod litery S
             Display_values(3) = &B10011000                     'kod litery S
    
             Temp = Makebcd(seconds)                            'wyswietla aktualna sekunde
             Temp_segment = Temp And &B00001111                 'jednostki sekund
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(1) = Temp_segment
             Temp_segment = Temp / 16
             Temp_segment = Lookup(temp_segment , 7seg_code)    'odczyt kodu cyfry
             Display_values(2) = Temp_segment                   'dziesiatki sekund
    
             If B2 = 0 Then                                     ' Obsluga Przycisku 2(zmiana wartosci)
                Waitms 30
                If B2 = 0 Then Seconds = 0
                Bitwait B2 , Set
             End If
    
       End Select
    
    
    Loop
    
    End
    
    '************************************************
                      'koniec programu
    '************************************************
    
    
    Interrupt_2ms:
       Timer2 = Timer2 + 6                                      ' Obsluga Timera
       Enable Interrupts
       T2ms_cntr = T2ms_cntr + 1
       If T2ms_cntr = 500 Then
          Gosub Incr_sec
          T2ms_cntr = 0
       End If
                                                 'obsluga wyswietlacza
       Display_nr = Display_nr + 1
       If Display_nr > 4 Then Display_nr = 1
    
       Select Case Display_nr
          Case 1:
             Reset D4
             Portc = Display_values(display_nr)
             Temp = Seconds Mod 2
             If Synchronized = 1 Then
                Reset Portc.7                                   'swiecenie ciagle kropki gdy tylko wykryto szczeline synchr.
                If Dcf_mins = Minutes And Temp = 1 Then         'miganie kropki, gdy wyswietlany czas jest
                   Set Portc.7                                  'zgodny z czasem dcf
                End If
    
             Elseif Dcf_mins = Minutes And Temp = 0 Then        'miganie kropki, gdy wyswietlany czas jest
                Reset Portc.7                                   'zgodny z czasem dcf
             End If
             Set D1
          Case 2:
             Reset D1
             Portc = Display_values(display_nr)
             Set D2
          Case 3:
             Reset D2
             Portc = Display_values(display_nr)
             Temp = Seconds Mod 2
             If Temp = 0 Then Reset Portc.7
             Set D3
          Case 4:
             Reset D3
             Portc = Display_values(display_nr)
             Set D4
       End Select
    Return
    
    '************************************************
    Interrupt_dcf:
    
       Waitus 15                                                'eliminacja zaklocen impulsowych
       If Dcf_in <> Int0_bit Then
          Stop Timer1
          Timer_val = Timer1
          Timer1 = 0
          Start Timer1
          Int0_bit = Dcf_in
    
          If Dcf_in = 0 And Dcf_failure = 0 And Synchronized = 1 Then       'wykryto poczatek przerwy miedzy impulsami
             If Timer_val > T50ms And Timer_val < T150ms Then   'odebrano bit 0
                Dcf_array(1).bits_rcvd = 0
                Bits_rcvd = Bits_rcvd + 1
             Elseif Timer_val >= T150ms And Timer_val < T250ms Then       'odebrano 1
                Dcf_array(1).bits_rcvd = 1
                Bits_rcvd = Bits_rcvd + 1
             Else                                               'blad
                Dcf_failure = 1
                Synchronized = 0
             End If
    
    
    
          Else                                                  'wykryto impuls
             If Timer_val > T2000ms Or Timer_val < T600ms Then  'blad - niepoprawna przerwa miedzy impulsami
                Set Dcf_failure
                Reset Synchronized
             Elseif Timer_val > T1500ms Then                    'mamy bit synchronizacyjny
                Set Synchronized
                If Bits_rcvd = 59 And Dcf_failure = 0 Then Gosub Change_time
                Reset Dcf_failure
                Bits_rcvd = 0
             End If
    
          End If
       End If
    Return
    
    '************************************************
    Change_time:
    
       Dim Crc As Bit
       Dim I As Byte
    
       If Dcf_allowed = 0 Then Return
       Index = 20
       If Dcf_array(1).index = 0 Then Return
    
       Index = 21
       For I = 0 To 6
          Crc = Crc Xor Dcf_array(1).index
          Dcf_mins.i = Dcf_array(1).index
          Index = Index + 1
       Next
       Index = 28
       If Crc <> Dcf_array(1).index Then Return
       Dcf_mins = Makedec(dcf_mins)
       If Dcf_mins > 60 Then Return
    
       Index = 29
       For I = 0 To 5
          Crc = Crc Xor Dcf_array(1).index
          Dcf_hours.i = Dcf_array(1).index
          Index = Index + 1
       Next
       Index = 35
       If Crc <> Dcf_array(1).index Then Return
       Dcf_hours = Makedec(dcf_hours)
       If Dcf_hours > 24 Then Return
    
       Hours = Dcf_hours
       Minutes = Dcf_mins
       Seconds = 0
    
    Return
    
    
    '************************************************
    Incr_sec:
       Seconds = Seconds + 1
       If Seconds > 59 Then
          Seconds = 0
          Gosub Incr_min
       End If
    Return
    
    Incr_min:
       Minutes = Minutes + 1
       If Minutes > 59 Then
          Minutes = 0
          Gosub Incr_hour
       End If
    Return
    
    Incr_hour:
       Hours = Hours + 1
       If Hours > 23 Then
          Hours = 0
       End If
    Return
    '************************************************
    
    
    7seg_code:
    Data &B10000001 , &B10110111 , &B11000010 , &B10010010 , &B10110100,
    Data &B10011000 , &B10001000 , &B10110011 , &B10000000 , &B10010000


    Teraz pozostaje mi tylko dodac funkcje budzika i ewentualnie rozszerzyc zegarek o jakas mala stacje pogodowa i po sprawie :D

    P.S. W DCF jest przesylana informacj o czasie letnim/zimowym. Czy w zwiazku z tym konieczna jest korekta w przypadku czasu zimowego, czy moze transmitowany czas jest zawsze czasem aktualnym nie trzeba wprowadzac poprawek? Wydaje mi sie, ze to drugie (przeciez "naturalnym" czasem jest czas zimowy, wiec jesli trzebaby wprowadzac ew. poprawke to tylko w przypadku czasu letniego, a w tej chwili mi pokazuje prawidlowa godzine), ale prosze o potwierdzenie.

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy problemu zapisu kolejnych bitów sygnału DCF w BASCOM bez użycia tablic bitów, które są w tym języku zabronione. Uczestnicy sugerują alternatywy, takie jak użycie tablic bajtów, gdzie jeden bajt może przechowywać osiem bitów, co pozwala na efektywne zarządzanie pamięcią i interpretację danych. Proponowane są funkcje do odczytu i zapisu pojedynczych bitów w tablicy bajtów, co upraszcza programowanie w BASCOM. Wspomniano, że BASCOM-AVR obsługuje tablice bitów z ograniczeniem do 256 bitów oraz wymogiem, by indeks bitu był zmienną. Autor pisze program pod mikrokontroler Atmega16 i napotyka problemy z kompilacją, m.in. z błędami składniowymi w warunkach logicznych, używaniem stałych z nazwami zawierającymi cyfry i problemami z konfiguracją timera (Timer0 i Timer2) oraz preskalerem. Wskazano, że w BASCOM nawiasy w warunkach If/Elseif powinny być usunięte, a także zwrócono uwagę na poprawne użycie zmiennych i stałych w porównaniach. Dyskusja obejmuje także kwestie symulacji i rzeczywistego działania programu na mikrokontrolerze, w tym problem z miganiem kropki na wyświetlaczu. Podsumowując, efektywnym rozwiązaniem jest użycie tablic bajtów z funkcjami do manipulacji pojedynczymi bitami, a także poprawna składnia i definicje stałych w BASCOM dla Atmegi16.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA