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

Wyświetlanie zmiennej na LCD

nelik1987 31 Sie 2009 18:49 8182 26
  • #1 6965075
    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:
    
    #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
    //-------------------------------------------------------------------------------------------------
    // 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
    //-------------------------------------------------------------------------------------------------
    // 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:
    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]);
    }
    }
  • #2 6965133
    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!!
  • #3 6965157
    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
  • #4 6965184
    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!!
  • #7 6965708
    szelus
    Poziom 34  
    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....
  • #10 6966500
    mojsamspam
    Poziom 11  
    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
  • #11 6966752
    rpal
    Poziom 27  
    Doradzę koledze aby sobei zadeklarował taką zmienną
    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:
    
    unsigned char minuta;
    unsigned char sekunda;
    

    (to oczywiście deklaracje zmienny które sa na początku procedury)
    a zamiana moze wyglądać tak
    
    *(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
    
    *(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
    
    *(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 :)
  • #12 6967068
    markosik20
    Poziom 33  
    rpal napisał:
    Doradzę koledze aby sobei zadeklarował taką zmienną
    unsigned char *bufor="00:00";



    Może kolega się zastanowi dobrze przed takim doradzaniem?
  • #13 6967655
    rpal
    Poziom 27  
    markosik20 napisał:
    rpal napisał:
    Doradzę koledze aby sobei zadeklarował taką zmienną
    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 ?
  • #15 6967814
    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
    unsigned char bufor[6]="00:00";
    lub 
    unsigned char bufor[6]={'0','0',':','0','0','\0'};
    

    wszystko to znaczy dokładnie to samo.
  • #16 6967843
    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:

    
    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!!
  • #17 6967865
    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.
  • #18 6967916
    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!!
  • #19 6968242
    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.
  • #20 6968381
    Freddie Chopin
    Specjalista - Mikrokontrolery
    No nie, nie mogę... Tak - wiesz że się mylę...

    Cytat:
    Zachodzi istotna różnica między takimi definicjami:
    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!!
  • #21 6968629
    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.
  • #22 6968762
    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
    
    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ę.
  • #23 6968795
    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!!
  • #24 6968810
    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.
  • #26 6968854
    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
    unsigned char *bufor="00:00";

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


    To jest tylko rada, zrobisz jak chcesz ale dobre nawyki w przyszłości Ci się odwdzięczą :wink:.
  • #27 6970571
    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.
REKLAMA