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

[Atmega16][C] PCF zwariował po użyciu EEPROMu

adivip125 22 Kwi 2011 10:40 1401 13
  • #1 9427499
    adivip125
    Poziom 10  
    Witam Was!
    Programuję sobie właśnie mój sterownik do terrarium i napotkałem wczoraj na problem którego nie mogę za Chiny przeskoczyć... otóż wczoraj przed nabrojeniem miałem sobie kod:

    #include <avr/io.h>
    #include <util/delay.h>
    #define F_CPU 1000000UL
    
    #include "HD44780.c"
    #include "config.h"
    #include "i2c.h"
    #include "PCF8583.h"
    
    #define PODSWIETLENIE_ON PORTB |= _BV(3)
    #define PODSWIETLENIE_OFF PORTB &= ~_BV(3)
    
    #define C11_ON PORTD |= _BV(6)
    #define C12_OFF PORTD &= ~_BV(7)
    #define P2_ON PORTD |= _BV(3)
    #define P2_OFF PORTC &= ~_BV(7)*/
    
    #define C3a_ON PORTD |= _BV(3)
    #define C3a_OFF PORTD &= ~_BV(3)
    #define C3b_ON PORTC |= _BV(7)
    #define C3b_OFF PORTC &= ~_BV(7)
    
    
    
    #define UP 4
    #define DOWN 3
    #define RIGHT 6
    #define LEFT 2
    #define ENTER 5
    
    void konwert2(char tekst[], int liczba)
    {
       tekst[0]=(liczba%100-liczba%10)/10+48;
       tekst[1]=liczba%10+48;
    }
    
    
    uint8_t godz, min, sek, hsek;
    uint8_t dzien, miesiac;
    uint16_t rok;
    uint8_t tekst[17];
    
    int main(void)
    {
      DDRB=0xFF;
      DDRA  = 0xFF;
      PORTA= 0x00;
      //char buforek[12];
    
      DDRC  = 0x00;
      PORTC = 0xFF;
      LCD_Initalize(); 
         i2cInit();
       PCF8583_init();
       
       PCF8583_set_time(0, 10, 0,0 );
       
      PODSWIETLENIE_ON;
      LCD_GoTo(4,0);
     LCD_WriteText("Witaj w");
     LCD_GoTo(1,1);
     LCD_WriteText("sterowniku v 1.0");
      _delay_ms(3000);
     LCD_Clear();
     
      PODSWIETLENIE_OFF;
       volatile char wyswietl[1];
       wyswietl[0]='0';
       unsigned int cozegar=1, godzina, minuta;
       char pomoc;
    
      while(1)
      {
         switch(wyswietl[0])
         {
    //==================================================0
    	    case '0':
    		   LCD_Clear();
    		   while(wyswietl[0]=='0')
    		   {
    	          LCD_Home();
    		      LCD_GoTo(0,0);
    		      PCF8583_get_time( &godz, &min, &sek, &hsek );
    		      konwert2(pomoc,godz);
    		      LCD_WriteText(pomoc);
    		      LCD_GoTo(0,1);
    			  
    		      if(hsek<50)
    		         LCD_WriteText(":");
    		      else
    		         LCD_WriteText(" ");
    			  
    		      konwert2(pomoc,min);
    		      LCD_WriteText(pomoc);
    			  
    			  
    			  
    			  
    			  if(bit_is_clear(PINC, RIGHT))
    			  {
    			     wyswietl[0]='3';
    				 _delay_ms(200);
    			  }
    			  
    			  if(bit_is_clear(PINC, LEFT))
    			  {
    			     wyswietl[0]='2';
    				 _delay_ms(200);
    			  }
    			  
    			  if(bit_is_clear(PINC, ENTER))
    			  {
    			     wyswietl[0]='4';
    				 _delay_ms(200);
    			  }
    		   }
    		break;
    //===============================================2
    		case '2':
         /* dalsza, nieistotna część menu  */
          }
       }
    return 0;
    }


    Kod jest we wczesnej fazie testów więc nie zwracajcie uwagi na sprawy optymalizacyjne, chodzi mi o jedną sprawę...

    Na początku po kompilacji kodu na LCD wyświetla mi sie ładnie godzina w formacie (np. dla 9:47):

    09:
    47

    Otóż chciałem spróbować czy zadziała mi EEPROM, bo miałem zapisywać do niego jakieś tam zmienne. Dodałem odpowiedni plik nagłówkowy avr/eeprom.h no i zastosowałem takie oto funkcje:
    uint8_t EEMEM pierwszy=5;

    potem
     eeprom_busy_wait();
     eeprom_write_byte((uint8_t*)2,42);  
     eeprom_busy_wait();
     eeprom_write_byte((uint8_t*)1,52);
     eeprom_busy_wait();
     eeprom_write_byte((uint8_t*)0,3);

    a następnie przy odczycie:
    eeprom_busy_wait();
    konwert2(pomoc,eeprom_read_byte((uint8_t*)2));
    eeprom_busy_wait();
    LCD_WriteText(pomoc);
    LCD_WriteText("-");
    eeprom_busy_wait();
    konwert2(pomoc,eeprom_read_byte((uint8_t*)1));
    eeprom_busy_wait();
    LCD_WriteText(pomoc);


    Instrukcje powyżej stosowałem kilkakrotnie w różnych miejscach programu dla testu - i teraz zaczyna sie mój problem - po usunięciu wszystkich powyższych instrukcji (tzn po skopiowaniu kodu sprzed zastosowaniu EEPROMu) LCD wyświetla mi jakieś dodatkowe śmieci, teraz wygląda to tak:

    09||E
    :47||E

    wczoraj przykładowo miałem coś takiego:

    0055627
    :1055627

    Czyli dodaje do godziny COŚ, jakiś adres albo inne odpady. Najlepsze że nie mogę tego okroić, tzn zamienić na łańcuch znaków i wyświetlić tylko dwóch pierwszych znaków - takie sztuczki nic nie dają.

    Czy namieszałem coś przez użycie EEPROMa w danych komórkach? Co sie stało że wyświetla mi takie głupoty? Bardzo proszę o jakieś wskazówki

    Edit: zapomniałem dodać, że chodzi o PCF8583, biblioteki ściągnąłem z elektrody i wszystko hulało póki nie ruszyłem tego EEPROMa... idę malować jajka, musze troche ochłonąć... ;)
  • #2 9427551
    michalko12
    Specjalista - Mikrokontrolery
    przyczyna jest :

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    to musi być tablica.
  • #3 9427599
    piotrva
    VIP Zasłużony dla elektroda
    a jaki to eeprom?
    bo jeśli 24c16 to wtedy jest na 100% konflikt adresów, a jeśli inny mniejszy z rodziny 24cXX to sprawdź jakie masz adresy ustawione nogami Ax w PCF8583 i pamięci
  • #4 9427617
    michalko12
    Specjalista - Mikrokontrolery
    piotrva napisał:
    a jaki to eeprom?

    wewnętrzny :cunning:
  • #5 9427763
    adivip125
    Poziom 10  
    no właśnie moją intencją było użycie eepromu wewnętrznego Atmegi. char pomoc nie jest przyczyną bo maglowałem tym parametrem chyba na wszystkie sposoby, robiłem pomoc[], pomoc[2] i inne typowe dla tablic. PCF podłączony jest do atmegi tylko nogami SCL i SDA, A0 w PCF podpiete do plusa. obstawiałem adresowanie komórek pamięci, tylko jak to teraz odwrócić?

    Edit:
    Sprawdziłem dla pewności jeszcze raz, char pomoc[2]; nic nie zmienia. Wyświetla mi sie teraz:

    00_||||
    :11_||||
  • #6 9427940
    michalko12
    Specjalista - Mikrokontrolery
    No ale zastanów się jaki format ma string.
    Każdy string musi być zakończony '\0'
    czyli jak chcesz mieć napis "00" to tablica musi mieć co najmniej 3 znaki
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #7 9428003
    adivip125
    Poziom 10  
    okej w takim razie dlaczego wyświetla mi się "00_||||" zamiast "0" skoro tablica pomoc[2] zmieści mi tylko jeden znak i zakończenie?
  • #8 9428060
    michalko12
    Specjalista - Mikrokontrolery
    A jak myślisz, na jakiej podstawie funkcja LCD_WriteText() "wie" jakiej długości jest string? Wyświetla co leci do momentu napotkania znaku '\0'.
  • #9 9428119
    piotrva
    VIP Zasłużony dla elektroda
    michalko12 napisał:
    piotrva napisał:
    a jaki to eeprom?

    wewnętrzny :cunning:

    :D Przepraszam za "odpał nie na temat" ale się zasugerowałem tym, że taki temat niedawno był poruszany na forum.
  • #10 9428440
    adivip125
    Poziom 10  
    michalko12, zgoda, masz racje. tylko wiem na 100% że to nie tu jest ten problem! pisząc większy program zapisuje sobie jego wersje jak zrobie jakiś milowy kroczek i mam w ten sposób chronologicznie 20 plików, każdy ma coś więcej. no i teraz chodzi o to że przysłałem Wam kod jednego z tych plików który wyświetlał POPRAWNIE godzine na LCD. po manipulacji eepromem coś rypnęło i po wklejeniu TEGO SAMEGO kodu do kompilatora - LCD wyświetla śmieci. nie chce się tu kłócić jak jest zbudowana tablica i co ona tam ma - to wszystko działało póki nie ruszyłem eeproma. co sie mogło stać? jak to odwrócić? CO jest powodem takiego stanu rzeczy - uC, PCF, LCD?

    Edit:
    Zastanawia mnie tylko jedna rzecz: miganie dwukropka jest napisane w oparciu o wartość setnych sekund i to o dziwo działa - wariat mruga doskonale. Sugeruje to, że wartość liczbowa z PCFa jest poprawna... nie wiem już co o tym myśleć. Mam sposób na poprawne wyświetlanie, lecz jest on strasznie idiotyczny - tzn wypisać na ekranie godzine tak jak jest z tymi śmieciami, potem nadpisać śmieci dwukropkiem i minutami ze śmieciami, a śmieci z minuty nadpisać spacjami... sposób zadziała ale wg mnie to straszne przekombinowanie... jak nie da rady odwrócić tego co narobiłem z eepromem to tak będe zmuszony chyba zrobić :/
  • Pomocny post
    #11 9428567
    michalko12
    Specjalista - Mikrokontrolery
    Ciężko ci to zrozumieć że od samego początku masz źle?

    void konwert2(char tekst[], int liczba)
    char pomoc;

    Napisz mi jak ma się char tekst[] do char pomoc?
  • Pomocny post
    #12 9428577
    janbernat
    Poziom 38  
    A spróbuj wyjąć wyświetlacz z układu, po 1min ponownie wsadzić i zrobić reset.
    Albo wyłączyć zasilanie na jakiś czas.
    Co prawda robisz Clear() ale może po tym Clear() poczekaj i zobacz czy wyświetlacz jest pusty.
    To polecenie Clear() zajmuje zwykle 2ms- często właśnie zamiast tego wpisuje się łańcuch z samych spacji żeby wykasować cały napis a potem wyświetla to co się chce.
    Tak jest dużo szybciej- no i pozostałości z poprzedniego wyświetlania nie zostają.
  • Pomocny post
    #13 9428735
    Andrzej__S
    Poziom 28  
    Cytat:

    Sprawdziłem dla pewności jeszcze raz, char pomoc[2]; nic nie zmienia.
    ...
    okej w takim razie dlaczego wyświetla mi się "00_||||" zamiast "0" skoro tablica pomoc[2] zmieści mi tylko jeden znak i zakończenie?

    Ponieważ Twoja funkcja void konwert2(char tekst[], int liczba) nie dodaje znaku '\0' w tablicy tekst[].
    Elementy Twojej tablicy to tekst[0]='0' i tekst[1]='0' (nie mylić z '\0'), a jaka będzie wartość komórki, która znajduje się za tablicą to czysty przypadek. Z kolei instrukcja LCD_WriteText(pomoc); będzie wyświetlać kolejne komórki pamięci do momentu natrafienia na znak '\0'.
    Zmienna char pomoc; powinna być zadeklarowana jako char pomoc[3];, a na końcu funkcji void konwert2(char tekst[], int liczba) powinna być instrukcja tekst[3] = '\0';.
    Niezależnie od tego, czy ten kod kiedyś działał, proponuję zastosować się do rad kolegi michalko12, bo ten kod jest po prostu napisany nieprawidłowo i będzie działał nieprzewidywalnie.
  • #14 9428763
    adivip125
    Poziom 10  
    ehhh ciemnota moja... dzięki Andrzej__S, już wiem co na myśli miał michalko12, źle to zrozumiałem :) działa wszystko już, zastosowałem się do powyższego postu.

    Dzięki za pomoc no i Wesołych Świąt!
REKLAMA