Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Wyświetlanie zmiennej na LCD

nelik1987 31 Sie 2009 18:49 7279 26
  • #1 31 Sie 2009 18:49
    nelik1987

    Poziom 31  

    Witam piszę prosty program wyświetlający różne zmienne z programu na wyświetlaczu LCD.

    Wyświetlacz podłączyłem i wszstko gra, moge wyświetlać napisy ale nie mogę wyświetlić zmiennych.

    podam kod do mojego programu i krótko go opiszę:

    Program miał wyswietlac godzinę na wyświetlaczu, do odliczania 1 sekundy wykorzystałem timer 16 bitowy z preskalerem 64. Chciałem wyświetlić chociaz jedną zmienna ale nic z tego

    poczytałem troszkę i znalazłem funkcję itoa wykorzystałem ją i było prawie dobrze bo wyświetlało 1,2,3....9 a potem krzaki.

    Jak wyświetlić zmienne wykorzystując gotową bibliotekę zamieszczoną poniżej?

    Oto mój program:

    Code:

    #include <avr/io.h>
    #include <inttypes.h>
    #include <util/delay.h>
    #include <HD44780.c>


    int WriteInt(int variable, int col, int row)
    {
    int i, n, temp, p;
    p=0;
    if(variable == 0)
    {
    LCD_WriteText("0");
    return 0;
    }
    if(variable < 0)
    {
    variable = (-1)*variable;
    LCD_GoTo(col, row);
    LCD_WriteText("-");
    p=1;
    }
    temp = variable;
    n = 0;
    while(temp>0)
    {
    n++;
    temp = temp/10;
    }
    char txt[n];
    for(i=n-1; i>=0; i--)
    {
    txt[i] = variable%10 + 0x30;
    variable = variable/10;
    }
    for(i=0; i<n; i++)
    {
    LCD_GoTo(col+i+p, row);
    LCD_WriteText(txt[i]);
    }
    }



    int main(void)
    {

    LCD_Initalize();
    LCD_Clear();

    LCD_GoTo(1,0);
    LCD_WriteText("W  I  T  A  M");
    LCD_GoTo(3,1);
    LCD_WriteText("NELIK :)");
    DDRC = 0;                               // Ustawienie rejestru B jako wejście (PRZYCISKI)

    //PORTC |= _BV(0);                         //Ustaw PC0 w stan wysoki (podciągnięcie do jedynki)
    //PORTC |= _BV(1);                         //Ustaw PC1 w stan wysoki (podciągnięcie do jedynki)

    unsigned int sekundy = 0;
    unsigned int minuty = 0;
    unsigned int godziny = 0;
    unsigned char buf;

    TCCR1B |= ((1 << CS01) | (1 << CS00));       //Ustawia timer0 z preskalerem Fcpu/64

    while(1)
    {

    if(TCNT1>=15625) // jeżeli mineła 1 sekunda




       {
       sekundy++;
       if(sekundy>=60)
          {
          sekundy=0;   
          minuty++;
          if(minuty>=60)
             {
             minuty=0;
             godziny++;
             if(godziny>=24)
             godziny=0;
             }
          }
       LCD_GoTo(0,0);   
       buf=sekundy;
       itoa(sekundy,buf,10);
       //LCD_WriteText(buf);   
       WriteInt(sekundy,0,0);
       
       TCNT1 = 0; // Zeruje wartość timera   
       }


       





    }
    return 0;
    }



    Jak widać dodałem bibliotekę HD44780 którą widać poniżej:

    HD44780.h
    Code:
    //-------------------------------------------------------------------------------------------------
    
    // Wyświetlacz alfanumeryczny ze sterownikiem HD44780
    // Sterowanie w trybie 4-bitowym bez odczytu flagi zajętości
    // z dowolnym przypisaniem sygnałów sterujących
    // Plik : HD44780.h   
    // Mikrokontroler : Atmel AVR
    // Kompilator : avr-gcc
    // Autor : Radosław Kwiecień
    // Źródło : http://radzio.dxp.pl/hd44780/
    // Data : 24.03.2007
    //-------------------------------------------------------------------------------------------------

    #include <avr/io.h>
    #include <util/delay.h>

    //-------------------------------------------------------------------------------------------------
    //
    // Konfiguracja sygnałów sterujących wyświetlaczem.
    // Można zmienić stosownie do potrzeb.
    //
    //-------------------------------------------------------------------------------------------------
    #define LCD_RS_DIR      DDRD
    #define LCD_RS_PORT    PORTD
    #define LCD_RS_PIN      PIND
    #define LCD_RS         (1 << PD0)

    #define LCD_RW_DIR      DDRD
    #define LCD_RW_PORT      PORTD
    #define LCD_RW_PIN      PIND
    #define LCD_RW         (1 << PD1)

    #define LCD_E_DIR      DDRD
    #define LCD_E_PORT      PORTD
    #define LCD_E_PIN      PIND
    #define LCD_E         (1 << PD2)




    #define LCD_DB4_DIR      DDRB
    #define LCD_DB4_PORT   PORTB
    #define LCD_DB4_PIN      PINB
    #define LCD_DB4         (1 << PB0)

    #define LCD_DB5_DIR      DDRB
    #define LCD_DB5_PORT   PORTB
    #define LCD_DB5_PIN      PINB
    #define LCD_DB5         (1 << PB1)

    #define LCD_DB6_DIR      DDRB
    #define LCD_DB6_PORT   PORTB
    #define LCD_DB6_PIN      PINB
    #define LCD_DB6         (1 << PB2)

    #define LCD_DB7_DIR      DDRB
    #define LCD_DB7_PORT   PORTB
    #define LCD_DB7_PIN      PINB
    #define LCD_DB7         (1 << PB3)

    //-------------------------------------------------------------------------------------------------
    //
    // Instrukcje kontrolera Hitachi HD44780
    //
    //-------------------------------------------------------------------------------------------------

    #define HD44780_CLEAR               0x01

    #define HD44780_HOME               0x02

    #define HD44780_ENTRY_MODE            0x04
       #define HD44780_EM_SHIFT_CURSOR      0
       #define HD44780_EM_SHIFT_DISPLAY   1
       #define HD44780_EM_DECREMENT      0
       #define HD44780_EM_INCREMENT      2

    #define HD44780_DISPLAY_ONOFF         0x08
       #define HD44780_DISPLAY_OFF         0
       #define HD44780_DISPLAY_ON         4
       #define HD44780_CURSOR_OFF         0
       #define HD44780_CURSOR_ON         2
       #define HD44780_CURSOR_NOBLINK      0
       #define HD44780_CURSOR_BLINK      1

    #define HD44780_DISPLAY_CURSOR_SHIFT   0x10
       #define HD44780_SHIFT_CURSOR      0
       #define HD44780_SHIFT_DISPLAY      8
       #define HD44780_SHIFT_LEFT         0
       #define HD44780_SHIFT_RIGHT         4

    #define HD44780_FUNCTION_SET         0x20
       #define HD44780_FONT5x7            0
       #define HD44780_FONT5x10         4
       #define HD44780_ONE_LINE         0
       #define HD44780_TWO_LINE         8
       #define HD44780_4_BIT            0
       #define HD44780_8_BIT            16

    #define HD44780_CGRAM_SET            0x40

    #define HD44780_DDRAM_SET            0x80

    //-------------------------------------------------------------------------------------------------
    //
    // Deklaracje funkcji
    //
    //-------------------------------------------------------------------------------------------------

    void LCD_WriteCommand(unsigned char);
    unsigned char LCD_ReadStatus(void);
    void LCD_WriteData(unsigned char);
    unsigned char LCD_ReadData(void);
    void LCD_WriteText(char *);
    void LCD_GoTo(unsigned char, unsigned char);
    void LCD_Clear(void);
    void LCD_Home(void);
    void LCD_Initalize(void);
    void LCD_ProgrammChar(unsigned char nr, unsigned char znak[]);

    //-------------------------------------------------------------------------------------------------
    //
    // Koniec pliku HD44780.h
    //
    //-------------------------------------------------------------------------------------------------


    HD47780.c
    Code:
    //-------------------------------------------------------------------------------------------------
    
    // Wyświetlacz alfanumeryczny ze sterownikiem HD44780
    // Sterowanie w trybie 4-bitowym bez odczytu flagi zajętości
    // z dowolnym przypisaniem sygnałów sterujących
    // Plik : HD44780.c   
    // Mikrokontroler : Atmel AVR
    // Kompilator : avr-gcc
    // Autor : Radosław Kwiecień
    // Źródło : http://radzio.dxp.pl/hd44780/
    // Data : 24.03.2007
    //-------------------------------------------------------------------------------------------------

    #include "HD44780.h"
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja wystawiająca półbajt na magistralę danych
    //
    //-------------------------------------------------------------------------------------------------
    void _LCD_OutNibble(unsigned char nibbleToWrite)
    {

    if(nibbleToWrite & 0x01)
       LCD_DB4_PORT |= LCD_DB4;
    else
       LCD_DB4_PORT  &= ~LCD_DB4;

    if(nibbleToWrite & 0x02)
       LCD_DB5_PORT |= LCD_DB5;
    else
       LCD_DB5_PORT  &= ~LCD_DB5;

    if(nibbleToWrite & 0x04)
       LCD_DB6_PORT |= LCD_DB6;
    else
       LCD_DB6_PORT  &= ~LCD_DB6;

    if(nibbleToWrite & 0x08)
       LCD_DB7_PORT |= LCD_DB7;
    else
       LCD_DB7_PORT  &= ~LCD_DB7;
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja wystawiająca półbajt na magistralę danych
    //
    //-------------------------------------------------------------------------------------------------
    unsigned char _LCD_InNibble(void)
    {
    unsigned char tmp = 0;

    if(LCD_DB4_PIN & LCD_DB4)
       tmp |= (1 << 0);
    if(LCD_DB5_PIN & LCD_DB5)
       tmp |= (1 << 1);
    if(LCD_DB6_PIN & LCD_DB6)
       tmp |= (1 << 2);
    if(LCD_DB7_PIN & LCD_DB7)
       tmp |= (1 << 3);
    return tmp;
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu bajtu do wyświetacza (bez rozróżnienia instrukcja/dane).
    //
    //-------------------------------------------------------------------------------------------------
    void _LCD_Write(unsigned char dataToWrite)
    {
    LCD_DB4_DIR |= LCD_DB4;
    LCD_DB5_DIR |= LCD_DB5;
    LCD_DB6_DIR |= LCD_DB6;
    LCD_DB7_DIR |= LCD_DB7;

    LCD_RW_PORT &= ~LCD_RW;
    LCD_E_PORT |= LCD_E;
    _LCD_OutNibble(dataToWrite >> 4);
    LCD_E_PORT &= ~LCD_E;
    LCD_E_PORT |= LCD_E;
    _LCD_OutNibble(dataToWrite);
    LCD_E_PORT &= ~LCD_E;
    while(LCD_ReadStatus()&0x80);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja odczytu bajtu z wyświetacza (bez rozróżnienia instrukcja/dane).
    //
    //-------------------------------------------------------------------------------------------------

    unsigned char _LCD_Read(void)
    {
    unsigned char tmp = 0;
    LCD_DB4_DIR &= ~LCD_DB4;
    LCD_DB5_DIR &= ~LCD_DB5;
    LCD_DB6_DIR &= ~LCD_DB6;
    LCD_DB7_DIR &= ~LCD_DB7;

    LCD_RW_PORT |= LCD_RW;
    LCD_E_PORT |= LCD_E;
    tmp |= (_LCD_InNibble() << 4);
    LCD_E_PORT &= ~LCD_E;
    LCD_E_PORT |= LCD_E;
    tmp |= _LCD_InNibble();
    LCD_E_PORT &= ~LCD_E;
    return tmp;
    }

    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu rozkazu do wyświetlacza
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteCommand(unsigned char commandToWrite)
    {
    LCD_RS_PORT &= ~LCD_RS;
    _LCD_Write(commandToWrite);
    }

    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja odczytu bajtu statusowego
    //
    //-------------------------------------------------------------------------------------------------
    unsigned char LCD_ReadStatus(void)
    {
    LCD_RS_PORT &= ~LCD_RS;
    return _LCD_Read();
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu danych do pamięci wyświetlacza
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteData(unsigned char dataToWrite)
    {
    LCD_RS_PORT |= LCD_RS;
    _LCD_Write(dataToWrite);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja odczytu danych z pamięci wyświetlacza
    //
    //-------------------------------------------------------------------------------------------------
    unsigned char LCD_ReadData(void)
    {
    LCD_RS_PORT |= LCD_RS;
    return _LCD_Read();
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja wyświetlenia napisu na wyswietlaczu.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteText(char * text)
    {
    while(*text)
      LCD_WriteData(*text++);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja ustawienia współrzędnych ekranowych
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_GoTo(unsigned char x, unsigned char y)
    {
    LCD_WriteCommand(HD44780_DDRAM_SET | (x + (0x40 * y)));
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja czyszczenia ekranu wyświetlacza.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Clear(void)
    {
    LCD_WriteCommand(HD44780_CLEAR);
    _delay_ms(2);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja przywrócenia początkowych współrzędnych wyświetlacza.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Home(void)
    {
    LCD_WriteCommand(HD44780_HOME);
    _delay_ms(2);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Procedura inicjalizacji kontrolera HD44780.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Initalize(void)
    {
    unsigned char i;
    LCD_DB4_DIR |= LCD_DB4; // Konfiguracja kierunku pracy wyprowadzeń
    LCD_DB5_DIR |= LCD_DB5; //
    LCD_DB6_DIR |= LCD_DB6; //
    LCD_DB7_DIR |= LCD_DB7; //
    LCD_E_DIR    |= LCD_E;   //
    LCD_RS_DIR    |= LCD_RS;  //
    LCD_RW_DIR    |= LCD_RW;  //
    _delay_ms(15); // oczekiwanie na ustalibizowanie się napiecia zasilajacego
    LCD_RS_PORT &= ~LCD_RS; // wyzerowanie linii RS
    LCD_E_PORT &= ~LCD_E;  // wyzerowanie linii E
    LCD_RW_PORT &= ~LCD_RW;
    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
      {
      LCD_E_PORT |= LCD_E; //  E = 1
      _LCD_OutNibble(0x03); // tryb 8-bitowy
      LCD_E_PORT &= ~LCD_E; // E = 0
      _delay_ms(5); // czekaj 5ms
      }

    LCD_E_PORT |= LCD_E; // E = 1
    _LCD_OutNibble(0x02); // tryb 4-bitowy
    LCD_E_PORT &= ~LCD_E; // E = 0

    _delay_ms(1); // czekaj 1ms
    LCD_WriteCommand(HD44780_FUNCTION_SET | HD44780_FONT5x7 | HD44780_TWO_LINE | HD44780_4_BIT); // interfejs 4-bity, 2-linie, znak 5x7
    LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_OFF); // wyłączenie wyswietlacza
    LCD_WriteCommand(HD44780_CLEAR); // czyszczenie zawartosći pamieci DDRAM
    LCD_WriteCommand(HD44780_ENTRY_MODE | HD44780_EM_SHIFT_CURSOR | HD44780_EM_INCREMENT);// inkrementaja adresu i przesuwanie kursora
    LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_ON | HD44780_CURSOR_OFF | HD44780_CURSOR_NOBLINK); // włącz LCD, bez kursora i mrugania
    }

    // funkcja służąca do wpisywania własnych znaków
    // nr - zmienna określająca numer znaku (dostępnych jest 8)  od 0 - 7.
    // znak[] - określa kształt znaku.. przykładowo uint8_t serduszko[] = {4, 10, 17, 23, 23, 17, 31, 0}; definiuje wygląd serca.
    void LCD_ProgrammChar(unsigned char nr, unsigned char znak[])
    {   
       unsigned char i;
       LCD_WriteCommand(HD44780_CGRAM_SET|(nr*8));
       for (i=0; i<=7; i++)
       {
          LCD_WriteData(znak[i]);
       }
       LCD_WriteCommand(HD44780_DDRAM_SET);
    }

    //-------------------------------------------------------------------------------------------------
    //
    // Koniec pliku HD44780.c
    //
    //-------------------------------------------------------------------------------------------------


    Proszę o pomoc w wyswietleniu z zmiennych int lub innych liczbowych

    znalazłem jeszcze coś takiego ale to też działać nie chce:
    Code:
    int WriteInt(int variable, int col, int row)
    
    {
    int i, n, temp, p;
    p=0;
    if(variable == 0)
    {
    LCD_WriteText("0");
    return 0;
    }
    if(variable < 0)
    {
    variable = (-1)*variable;
    LCD_GoTo(col, row);
    LCD_WriteText("-");
    p=1;
    }
    temp = variable;
    n = 0;
    while(temp>0)
    {
    n++;
    temp = temp/10;
    }
    char txt[n];
    for(i=n-1; i>=0; i--)
    {
    txt[i] = variable%10 + 0x30;
    variable = variable/10;
    }
    for(i=0; i<n; i++)
    {
    LCD_GoTo(col+i+p, row);
    LCD_WriteText(txt[i]);
    }
    }

    0 26
  • #2 31 Sie 2009 19:06
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Czy ty w ogóle przeczytałeś jak stosuje się funkcję itoa? Czy w ogóle przejrzałeś warningi jakie produkuje kompilator, czy może powiedziałeś sobie, że żaden program nie będzie ci mówił co jest dobrze a co źle?

    Kod nie działa tak jak trzeba, bo po prostu jest napisany ŹLE. Wystarczy przejrzeć warningi i pomyśleć choć chwilę nad składnią wywołań funkcji itoa(), żeby nie mieć problemu.

    4\/3!!

    0
  • #3 31 Sie 2009 19:11
    nelik1987

    Poziom 31  

    no niestety jestem za mało doświadczony żeby to sam rozwiazac dlatego zwracam się do Was o pomoc. Języka C uczę się sam dlatego tez mam wiele problemów ale zawsze staram się je sam naprawić ten problem mnie przerasta kilka godzin próbowałem ale nic z tego

    0
  • #4 31 Sie 2009 19:17
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Błagam, trochę samodzielności...

    PIERWSZY wynik z google na zapytanie "itoa()" wraz z PRAWIDŁOWYM przykładem:

    http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/

    i teraz zastanów się czym się różni bufor zdefiniowany jako char bufor[33] a czym jako char bufor.

    4\/3!!

    0
  • #6 31 Sie 2009 20:05
    nelik1987

    Poziom 31  

    już sobie poradziłem błąd leżał w tym, zadeklarowałem jeden znak a trzeba było zadeklarować tablice znaków :) unsigned char buf[2];

    dziękuję za pomoc

    0
  • #7 31 Sie 2009 20:59
    szelus
    Specjalista - Mikrokontrolery

    nelik1987 napisał:
    a trzeba było zadeklarować tablice znaków :) unsigned char buf[2];

    Co najmniej buf[3], jeżeli chodzi o ścisłość. Bo inaczej znowu będą problemy....

    0
  • #8 31 Sie 2009 22:31
    nelik1987

    Poziom 31  

    a niby dlaczego miał by7 by problemy jeżeli największą liczbą jaką zapisze bedzie 60 ? na buf[2] działa bez problemów

    0
  • #9 31 Sie 2009 22:57
    Freddie Chopin
    Specjalista - Mikrokontrolery
  • #10 31 Sie 2009 23:31
    mojsamspam
    Poziom 10  

    jeszcze jeden bajt jest potrzebny na znak końca tekstu (bo przecież musi program wiedzieć gdzie kończy się tekst). Dokładnie tak jak kolega Freddie napisał.

    ...'\0', called NUL in ASCII...

    Powodzenia

    0
  • #11 01 Wrz 2009 01:42
    rpal
    Poziom 27  

    Doradzę koledze aby sobei zadeklarował taką zmienną

    Code:
    unsigned char *bufor="00:00";

    tym sposobem masz już na końcu znak końca łańcucha
    potem musisz zamienić po kolei minuty i sekundy na postać tekstową np:
    Code:

    unsigned char minuta;
    unsigned char sekunda;

    (to oczywiście deklaracje zmienny które sa na początku procedury)
    a zamiana moze wyglądać tak
    Code:

    *(bufor) = (minuta/10)+0x30;

    w tej linni pierwsza cyfra minuty (np. jeśli minuta to wartość 34) wpisuje w bufor wartość 3. Uzyskuje się ją z dzielenia 34/10 = 3 i dodania wartości 0x30 aby uzyskać znak wg ASCII odpowiadający znakowi "3"
    druga cyfra to coś takiego
    Code:

    *(bufor+1) = (minuta%10)+0x30;

    na drugiej pozycji twojego bufora wpisujesz znak "4" który odpowiada 4 z wartości mimut na pozycji jednostek, operand % szłuży do uzykania reszty z dzielenia a wynik operacji 34%10 = 4
    separator ":" zostaje
    To samo z sekundami czyli
    Code:

    *(bufor+3) = (minuta/10)+0x30;
    *(bufor+4) = (minuta%10)+0x30;

    Tym sposobem masz już gotową zmienną znakową która siedzi w tablicy o nazwiej bufor razem ze znakiem końca łańcucha, gotową do wyświetlenia na LCD bez kombinowania z itoa i tymi sprawami :)

    0
  • #12 01 Wrz 2009 09:20
    markosik20
    Poziom 33  

    rpal napisał:
    Doradzę koledze aby sobei zadeklarował taką zmienną
    Code:
    unsigned char *bufor="00:00";



    Może kolega się zastanowi dobrze przed takim doradzaniem?

    0
  • #13 01 Wrz 2009 13:00
    rpal
    Poziom 27  

    markosik20 napisał:
    rpal napisał:
    Doradzę koledze aby sobei zadeklarował taką zmienną
    Code:
    unsigned char *bufor="00:00";



    Może kolega się zastanowi dobrze przed takim doradzaniem?

    Co jest w tym złego bo jakoś nie rozumiem uwagi kolegi ?

    0
  • #14 01 Wrz 2009 13:06
    Freddie Chopin
    Specjalista - Mikrokontrolery

    To jest bardzo źle, na AVR działa tylko przypadkiem. Element "00:00" na który wskazujesz technicznie rzecz ujmując jest STAŁĄ.

    4\/3!!

    0
  • #15 01 Wrz 2009 13:51
    rpal
    Poziom 27  

    Freddie Chopin napisał:
    To jest bardzo źle, na AVR działa tylko przypadkiem. Element "00:00" na który wskazujesz technicznie rzecz ujmując jest STAŁĄ.

    4\/3!!

    To nie jest stała tylko wskaźnik z zainicjowaną 5 znakami pamięcią RAM (+znak końca linii) na którą ten wskaźnik wskazuje. Jak dotąd sprawdzałem to na atmega16,32,64,8535,Atiny2313, i wszystko jest OK. Szukacie Panowie dziury w całym zamiast podawać autorowi konkretne rozwiązania o które prosi.:)
    Dla ortodoksów przykłąd równoważny
    Code:
    unsigned char bufor[6]="00:00";
    
    lub
    unsigned char bufor[6]={'0','0',':','0','0','\0'};

    wszystko to znaczy dokładnie to samo.

    0
  • #16 01 Wrz 2009 14:03
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Mówiłem, że działa tylko na AVRach, przypadkiem. Powodem jest to, że AVRy mają Hardwardzki model pamięci i tam uzyskanie stałej w pamięci flash jest mozliwe jedynie poprzez makra PGM.

    Uwierz - bufor to wskaźnik zainicjalizowany na STAŁĄ. Wrzuć ten kod na MSP430, PICa, ARMa to się przekonasz.

    Poprawnym rozwiązaniem jest napisanie:

    char bufor[] = "00:00";

    i wtedy będzie dobrze.

    I to wcale nie jest równoważny przykład, to zupełnie co innego. Zrozum, że na AVR działa to tylko PRZYPADKIEM. Tylko na AVR. Zrób tak na PC, to zobaczysz jak szybko system operacyjny podziękuje za współprace takiemu programowi.

    To co ty proponujesz to:
    const char bufor_init[] = "123";
    char *bufor = bufor_init;

    Teraz sprawdź, co będie jeśli dopiszesz "const" do JAKIEJKOLWIEK zmiennej na AVR - nic to nie da - faktycznie zmienna będzie w RAM, bo na AVR umieszczanie w flash realizowane jest przez PGM. Ale na PC, ARMie czy innym procku już tak łatwo nie będzie.

    Jesli nie wierzysz - dowód:

    Code:

    char *bufor = "123";
    ...
    int main(void) {
       *bufor = 1;
     80017b4:   f240 1300    movw   r3, #256   ; 0x100
     80017b8:   f2c2 0300    movt   r3, #8192   ; 0x2000
     80017bc:   681a         ldr   r2, [r3, #0]
     80017be:   f04f 0301    mov.w   r3, #1   ; 0x1
     80017c2:   7013         strb   r3, [r2, #0]
    }


    Po wejściu do main "bufor" ma wartość 0x08006f5c, co w ARMie którego używam odpowiada pamięci flash. Ostatni zapis: strb r3, [r2, #0] ma następujące parametry: r3 (wartość) = 1, r2 (adres) = 0x8006f5c

    Po wykonaniu ostatniej instrukcji następuje krytyczny wyjątek rdzenia i procesor wisi na obsłudze BusFault.

    4\/3!!

    0
  • #17 01 Wrz 2009 14:13
    rpal
    Poziom 27  

    kol Freddie, znajdujemy się w dziale "Mikrokontrolery AVR", zadziwiające jest to że zawsze znajdzie się osoba która będzie posługując się jakimiś wyjątkami udowadniać z góry ustaloną tezę. Co nawiasem mówiąc czynisz, po co ?
    Kol.Autor chciał rady dostał ją - pisał o AVR, w czym zatem problem ?
    Przykład podałem wręcz książkowy, nawiasem mówiąc w zasięgu ręki miałem podręcznik C aż sprawdziłem czy mam rację, Podaję tytuł dla chętnych "Poznaj C w 24 godziny" autor Tony Zhang wydanie z 2001 r. str 238 rozdział Manipulowanie łańcuchami zankowymi. Na tym się uczyłem a podręcznik traktuje o C jako takim a nie z na konkretny procesor. Opisuje standard ANSI. Zamiast dzielić włos na czworo u udzielić rady koledze który o to prosi, po co szukać wyjątków od reguły. Chłopak będzie miał tylko mętlik w głowie a inni uciechę. Pozdrawiam i życzę miłego dnia.

    0
  • #18 01 Wrz 2009 14:26
    Freddie Chopin
    Specjalista - Mikrokontrolery

    rpal napisał:
    kol Freddie, znajdujemy się w dziale "Mikrokontrolery AVR", zadziwiające jest to że zawsze znajdzie się osoba która będzie posługując się jakimiś wyjątkami udowadniać z góry ustaloną tezę. Co nawiasem mówiąc czynisz, po co ?

    To właśnie ty posługujesz się "jakimś wyjątkiem" i udowadniasz "z góry ustaloną tezę".

    Nie wiem co w tej książce pisze, ale albo jest tam błąd, albo metoda jest używana tylko do odczytu znaków (albo jako parametr funkcji które łańcucha nie zmieniają). No ale ty upieraj się dalej, bo na ATmedze jakiejś tam działa...

    To w jakim dziale się znajdujemy nie ma znaczenia - C to C i należy się uczyć od razu poprawnie, a nie tak jak ty proponujesz - "na AVR działa to po co się męczyć". Tylko czekać aż ty albo ci wyedukowani przez ciebie założą kolejny temat "procesor mi się resetuje, czemu?" jak już skończycie z AVRami. Zresztą - w mojej wersji trzeba nacisnąć JEDEN klawisz więcej, więc w czym problem, żeby było na pewno poprawnie?

    4\/3!!

    0
  • #19 01 Wrz 2009 16:20
    rpal
    Poziom 27  

    Z mojej strony zakonczyłem tę niepotrzebną dyskusję, podałem trzy poprawne deklarację zmiennej typu string, kol. Freddie to kwestionuje. Osobiście , szkod ami czasu na jałowe spory bo wiem że się mylisz.

    0
  • #20 01 Wrz 2009 17:07
    Freddie Chopin
    Specjalista - Mikrokontrolery

    No nie, nie mogę... Tak - wiesz że się mylę...

    Cytat:
    Zachodzi istotna różnica między takimi definicjami:
    Code:
    char amessage[] = "naszedł czas"; /* tablica */
    
    char *pmessage = "nadszedł czas"; /* wskaźnik */

    amessage jest tablicą wystarczająco dużą, aby pomieścić swój inicjator, czyli ciąg znaków zakończony znakiem '\0'. Poszczególne znaki w tablicy można zmieniać, ale nazwa amessage zawsze będzie odwołaniem do tego samego miejsca w pamięci. Z drugiej strony, pmessage jest wskaźnikiem zainicjowanym tak, aby wskazywał stałą napisową; wskaźnik można później zmieniać, by wskazywał na cokolwiek, ale próba zmiany w stałej napisowej ma skutek nieokreślony.


    Kernighan, Ritchie, Język ANSI C, str 144 (polskie wydanie piąte)

    Podać ci do nich adres? Możesz im napisać, że się mylą, bo ty wiesz lepiej.

    Trzy deklaracje które podałeś są poprawne, ale tylko dwie z nich można legalnie zmieniać.

    Dalej uważasz, że markosik20, Brian W. Kernighan, Dennis M. Ritchie i ja jesteśmy w błędzie, a tylko ty masz rację? Czy w ogóle istnieje argument, który potrafiłby przekonać cię o tym, że nie masz racji?

    4\/3!!

    0
  • #21 01 Wrz 2009 18:21
    markosik20
    Poziom 33  

    Nie ma sensu udowadniać koledze rpal że nie ma racji.
    Sam WinAVR wywala warninga przy lini z taką deklaracją.
    Działać to i może będzie na rdzeniu AVR ...ale z jaki skutkami przy rozbudowywaniu kodu?...tego nie wiadomo.
    Kompilator rdzeni ARM (8051 zresztą też) automatycznie ładuje taką stałą znakową do pamięci Flash więc każda próba zapisu pod adres ze wskaźnika powoduje że rdzeń ląduje pod wektorem data abort
    I tylko (jak wspomniał Freddie) inna architektura rdzeni AVR pozwala na "prawie poprawną" pracę takich operacji na adresie wskaźnika.

    0
  • #22 01 Wrz 2009 18:50
    rpal
    Poziom 27  

    Zgodzę się że AVRStudio przy deklaracji unsigned char *bufor="00:00" wywala ostrzeżenia. Na codzień używam Codevision i jest wszystko OK więc sobie z tym radzi. Jednak podałem alternatywne deklaracje które znaczą to samo i oto co Panowie Nieomylni robi sobie z tym AVRStudio

    Code:

    unsigned char bufor[6]="00:00";
     134:   ce 01          movw   r24, r28
     136:   02 96          adiw   r24, 0x02   ; 2
     138:   99 87          std   Y+9, r25   ; 0x09
     13a:   88 87          std   Y+8, r24   ; 0x08
     13c:   ec e7          ldi   r30, 0x7C   ; 124
     13e:   f0 e0          ldi   r31, 0x00   ; 0
     140:   fb 87          std   Y+11, r31   ; 0x0b
     142:   ea 87          std   Y+10, r30   ; 0x0a
     144:   f6 e0          ldi   r31, 0x06   ; 6
     146:   fc 87          std   Y+12, r31   ; 0x0c
     148:   ea 85          ldd   r30, Y+10   ; 0x0a
     14a:   fb 85          ldd   r31, Y+11   ; 0x0b
     14c:   00 80          ld   r0, Z
     14e:   8a 85          ldd   r24, Y+10   ; 0x0a
     150:   9b 85          ldd   r25, Y+11   ; 0x0b
     152:   01 96          adiw   r24, 0x01   ; 1
     154:   9b 87          std   Y+11, r25   ; 0x0b
     156:   8a 87          std   Y+10, r24   ; 0x0a
     158:   e8 85          ldd   r30, Y+8   ; 0x08
     15a:   f9 85          ldd   r31, Y+9   ; 0x09
     15c:   00 82          st   Z, r0
     15e:   88 85          ldd   r24, Y+8   ; 0x08
     160:   99 85          ldd   r25, Y+9   ; 0x09
     162:   01 96          adiw   r24, 0x01   ; 1
     164:   99 87          std   Y+9, r25   ; 0x09
     166:   88 87          std   Y+8, r24   ; 0x08
     168:   9c 85          ldd   r25, Y+12   ; 0x0c
     16a:   91 50          subi   r25, 0x01   ; 1
     16c:   9c 87          std   Y+12, r25   ; 0x0c
     16e:   ec 85          ldd   r30, Y+12   ; 0x0c
     170:   ee 23          and   r30, r30

    Zatem proponuję schować urażoną dumę do kieszeni i dać sobie spokój bo jesteście w błędzie. Ja przynajmniej kończę tę polemikę.

    0
  • #23 01 Wrz 2009 18:58
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Wymiękam... Przecież napisaliśmy DLACZEGO na AVR to działa, a na innych układach (tych w najpopularniejszej architekturze Von Neumana) działać nie będzie... Czemu nie widzisz tego, że to twoje rozwiązanie jest tutaj wyjątkiem i robisz z tego regułę? No chyba że dla ciebie świat zaczyna się i kończy na AVRach?

    Jedyną osobą, która jest tutaj w błędzie jesteś ty. Sorry.

    Jedyną osobą z urażoną dumą ponownie jesteś ty. Sorry again.

    To co proponujesz JEST naruszeniem zasad, zgodnie z tym co napisali samy twórcy języka C. A to że błędnie stworzone strony działają w IE wcale nie czyni z nich stron stworzonych poprawnie.

    Skoro nawet cytat z "Biblii C" cię nie przekonuje, to już nic cię nie przekona.

    4\/3!!

    0
  • #24 01 Wrz 2009 19:03
    markosik20
    Poziom 33  

    rpal napisał:
    .... oto co Panowie Nieomylni robi sobie z tym AVRStudio
    Zatem proponuję schować urażoną dumę do kieszeni i dać sobie spokój bo jesteście w błędzie.


    Nie AVRStudio a WinAVR.
    Nikt tu nie ma urażonej dumy, chcemy tylko żeby inni wiedzieli że taki zapis jest niepoprawny i korzystanie z niego w ten sposób może doprowadzić do niekreślonych zachowań oprogramowania.

    0
  • #25 01 Wrz 2009 19:07
    nelik1987

    Poziom 31  

    no i teraz to ja już sam nie wiem o co chodzi.... cieszę się tylko że u mnie działa to co chciałem

    0
  • #26 01 Wrz 2009 19:12
    markosik20
    Poziom 33  

    nelik1987 napisał:
    no i teraz to ja już sam nie wiem o co chodzi


    Jeżeli chcesz zapisywać coś pod adres wskaźnika nigdy nie deklaruj go tak
    Code:
    unsigned char *bufor="00:00";

    a tak
    Code:
    unsigned char bufor[]="00:00";


    To jest tylko rada, zrobisz jak chcesz ale dobre nawyki w przyszłości Ci się odwdzięczą :wink:.

    0
  • #27 02 Wrz 2009 08:01
    flapo213
    Poziom 21  

    Witam

    Może i ja wtrące tu swoje 3 grosze. Widzę że sytuacja na tym poście jest dosyć napięta. Naturalnie koledzy Markosik i Freddie mają w 100% rację, zgodzę się również iż nie powinno się zamieszczać niepoprawnych informacji na forum bo ktoś nie doczyta dokładnie i gdzieś tam użyje a później data abort itd. Pozatym nie powinno sie ignorować warningów przecież one po to są żeby przeczytać je i zastanowić się czemu one wogóle wyskoczyły.

    0