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

Mega8 TWI + LCD [C]. Po odłączeniu zasilania i włączeniu wyświetla śmieci.

Jebediah 05 Sie 2009 10:10 2144 9
REKLAMA
  • #1 6858689
    Jebediah
    Poziom 2  
    Witam wszystkich :) Od niedawna uczę sie programować uc i mam taki problem.. Wykodziłem sobie programik, który przy pomocy układu PCF8574AP będzie coś wyświetlać na ekraniku LCD 2x16 ze sterownikiem HD44780, program działa prawie dobrze, wyświetla napisy i co tam tylko chce, ale jak odłącze zasilanie i ponownie włączę to na wyświetlacz zostają wyrzucone jakiś losowe śmieci albo pozostaje pusty, dopiero po zresetowaniu megi8 wszystko zaczyna działać poprawnie...
    Oto program:
    
    #define   F_CPU                     8000000L
    #define   E                         3
    #define   RS                        2
    #define   LCD_TWI_ADDR              0x70
    
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <util/twi.h>
    #include "lcd.h"
    
    
    char LCD;
    
    
    void twi_stop() {
       TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
          while ( !(TWCR & (1<<TWINT)) );
    }
    
    
    void twi_start() {
       TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
          while ( !(TWCR & (1<<TWINT)) );
    }
    
    
    void twi_write(char data) {
       TWDR = data;
       TWCR = (1<<TWINT) | (1<<TWEN);
          while ( !(TWCR & (1<<TWINT)) );
    }
    
    
    /* Wysoki stan na linii E */
    void set_e() {
       LCD |= _BV(E);
       twi_write(LCD);
    }
    
    /* Niski stan na linii E */
    void clr_e() {
       LCD &= ~_BV(E);
       twi_write(LCD);
    }
    
    /* Wysoki stan na linii RS */
    void set_rs() {
       LCD |= _BV(RS);
       twi_write(LCD);
    }
    
    /* Niski stan na linii RS */
    void clr_rs() {
       LCD &= ~_BV(RS);
       twi_write(LCD);
    }
    
    
    /* Procedura zapisu bajtu danych do wyswietlacza */
    void lcd_write( char x ) {
       set_e();
       LCD = ((LCD & 0x0F) | (x & 0xF0));		/* Pierwsza polowka bajtu */
       twi_write(LCD);
       clr_e();
       set_e();
       LCD = ((LCD & 0x0F) | ((x & 0x0F) << 4));	/* Druga polowka bajtu */
       twi_write(LCD);
       clr_e();
       _delay_ms(5);
    }
    
    
    /* Zapis tekstu do wyswietlacza */
    void lcd_txt( char * txt ) {
       while ( *txt ) {
          set_rs();
          lcd_write( *txt++ );
       }
    }
    
    
    /* Zapis komendy do wyswietlacza */
    void lcd_cmd( char x ) {
       clr_rs();
       lcd_write(x);
    }
    
    
    void lcd_init() {
       _delay_ms(15);
       twi_start();
       twi_write(LCD_TWI_ADDR);
       clr_e();
       clr_rs();
    
       unsigned char i;
       for ( i = 0; i < 3; i++ ) {
          set_e();
          twi_write(0x03);
          clr_e();
          _delay_ms(5);
       }
    
       set_e();
       twi_write(0x02);
       clr_e();
       _delay_ms(1);
    
       lcd_cmd(HD44780_FUNCTION_SET | HD44780_FONT5x10 | HD44780_TWO_LINE | HD44780_4_BIT);
       lcd_cmd(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_OFF);
       lcd_cmd(HD44780_CLEAR);
       lcd_cmd(HD44780_ENTRY_MODE | HD44780_EM_SHIFT_CURSOR | HD44780_EM_INCREMENT);
       lcd_cmd(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_ON | HD44780_CURSOR_OFF | HD44780_CURSOR_NOBLINK);
    }
    
    
    
    
    int main(void) {
       lcd_init();
       lcd_txt("Dupa!!");
    return 0;
    }
    

    Oraz plik lcd.h:
    #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
    #define HD44780_CLEAR					0x01
    


    Do mikrokontrolera podpięty jest kwarc 8MHz oraz w pobliżu do linii VCC i GND kondensator 100nF, na linii SCL i SDA sa rezystory 4,7k, układ w całości jest zasilany zasilaczem 5V 450mA.
    Wie ktoś dlaczego tak się dzieje?
    Z góry dzięki :)
  • REKLAMA
  • #2 6858790
    maly_elektronik
    Poziom 23  
    Gdzie w kodzie znajdują się takie ustawienia jak:
     PORTx = 0xYY 

    oraz
     DDRx = 0xYY 

    jeżeli tą role spełnia
     LCD &= ~_BV(RS); 

    to dlaczego nigdzie nie ma makra :?:
    A jeżeli zadeklarowałeś to makro gdzieś indziej to dlaczego również istnieje zmienna o takiej samej nazwie , do której ładujesz pół bajtu danych (bo chyba obsługujesz wyświetlacz w trybie 4 bitowym):?:
  • REKLAMA
  • #3 6858793
    wdogli
    Poziom 18  
    Hej.
    Napisz jeszcze od czego odpinasz zasilanie. Od całego układu czy tylko od wyświetlacza.
    Jeśli tylko od wyświetlacza to jest to spowodowane tym że po zresetowaniu sterownika HD44780 (odcięciu zasilania) trzeba przeprowadzić jego inicjalizację a więc to co robi ta funkcja:

  • #4 6858941
    Jebediah
    Poziom 2  
    maly_elektronik napisał:
    Gdzie w kodzie znajdują się takie ustawienia jak:
     PORTx = 0xYY 

    oraz
     DDRx = 0xYY 

    jeżeli tą role spełnia
     LCD &= ~_BV(RS); 

    to dlaczego nigdzie nie ma makra :?:
    A jeżeli zadeklarowałeś to makro gdzieś indziej to dlaczego również istnieje zmienna o takiej samej nazwie , do której ładujesz pół bajtu danych (bo chyba obsługujesz wyświetlacz w trybie 4 bitowym):?:

    To jest cały kod, nigdzie nie ustawiałem PORTx oraz DDRx oraz LCD nie jest makrem, LCD jest zmienna typu char w której znajdują się dane przygotowane do wysłania przez twi do układu PCF8574. Tak wyświetlacz pracuje w trybie 4bitowym :)

    wdogli napisał:
    Napisz jeszcze od czego odpinasz zasilanie. Od całego układu czy tylko od wyświetlacza.

    Odpinam od całego układu :)
  • #5 6860233
    maly_elektronik
    Poziom 23  
    To wztłumacz proszę w jaki sposób ustawiaś pin w stan niski i wysoki :?:
    Jeżeli masz coś takiego:
    
    /* Niski stan na linii E */
    void clr_e() {
       LCD &= ~_BV(E);
       twi_write(LCD);
    }
    
    /* Wysoki stan na linii RS */
    void set_rs() {
       LCD |= _BV(RS);
       twi_write(LCD);
    } 
    


    To żeby twój pin RS był ustawiony w stan niski czy wysoki to trzeba najpierw ustawić te piny dla jakiegoś portu "x" na wyjście czyli:
    
    DDRx |= _BV(RS);
    

    oraz ustawić wartość 1/0 na tym pinie:
    
    PORTx |= _BV(RS) // stan wysoki
    PORTx &= _BV(RS) // stan niski
    


    Mam nadzieje że teraz mnie zrozumiesz :)
    P.S
    Konkretnie w tym przypadku LCD wygląda jak proste makro typu
     #define LCD PORTx //x to identyfikator portu NP A, B ...
    A oprócz tego ty tworzysz zmienną o takiej samej nazwie :idea:
  • REKLAMA
  • #6 6860283
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Kolego Jebediah - dla twojego dobra radzę ignorować posty usera maly_elektronik. W tym wątku definitywnie nie ma on pojęcia o czym pisze.

    Efekty jakie opisujesz są raczej spowodowane "sprzętem" - jakieś stany nieustalone zaraz po włączeniu zasilania, spowodowane (na przykład) tym, że jeden z układów zaczyna działać wcześniej niż inne. Pokaż więc schemat

    4\/3!!
  • #7 6860543
    Jebediah
    Poziom 2  
    maly_elektronik napisał:
    To wztłumacz proszę w jaki sposób ustawiaś pin w stan niski i wysoki :?:
    Jeżeli masz coś takiego:

    
    /* Niski stan na linii E */
    void clr_e() {
       LCD &= ~_BV(E);
       twi_write(LCD);
    }
    
    /* Wysoki stan na linii RS */
    void set_rs() {
       LCD |= _BV(RS);
       twi_write(LCD);
    }
    


    A jak napisze:
    
    /* Niski stan na linii E */
    void clr_e() {
       LCD &= ~(1 << E);
       twi_write(LCD);
    }
    
    /* Wysoki stan na linii RS */
    void set_rs() {
       LCD |= (1 << RS);
       twi_write(LCD);
    }
    

    To czym to będzie się różnić? Zobacz jak działa _BV() i co to są operatory bitowe..


    Dodaje schemat, całość jest złożona na płytce uniwersalnej PDU-14..

    Mega8 TWI + LCD [C]. Po odłączeniu zasilania i włączeniu wyświetla śmieci.
  • #8 6860769
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Standardowo... źle podłączone zasilanie do mikrokontrolera, brak filtracji na układzie PCF, brak filtracji przy LCD, brak jakiegoś elektrolita w całym układzie. To naprawdę jest potrzebne, choćby skrajnie bezsensownie wyglądało.

    4\/3!!
  • REKLAMA
  • #9 6861065
    Jebediah
    Poziom 2  
    Dzięki za podpowiedz :) Popracuje nad tym jeszcze, w razie czego będę pytać :)
  • #10 6861659
    maly_elektronik
    Poziom 23  
    Freddie Chopin ma racje nie sugeruj się tym co napisałem :(
    Dopiero schemat rozjaśnił mi umysł :idea:
    Sorry za wprowadzanie w błąd :)
    Najlepiej zgłoś moje poprzednie posty do raportowania :D
REKLAMA