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

[ATMEGA8][C] (odwieczny) Problem z LCD

esh0 12 Mar 2009 16:25 1749 13
REKLAMA
  • #1 6272055
    esh0
    Poziom 19  
    Witam!

    Krótko:
    - przepisałem kod z kursu C w EdW do obsługi LCD
    - na płytce prototypowej (firmowa, nie zawiera błędów) połączyłem procek z lcd
    - sprawdziłem czy jest przejście między nóżkami procka a LCD - jest
    - podczas programowania zapisałem fusebity na LOW:C3, HIGH:99, odpowiadające za wewnętrzny oscylator 4MHz
    - nie działa

    Efekt taki, że na wszystkich wyjściach non stop stan wysoki (widać po podłączeniu do ledów). Sytuacja jest o tyle dziwna, że przy takim podłączeniu programator nie wykrywa procesora... dopiero gdy odłączę port B6 można zaprogramować...

    Kod programu:
    
    #include <avr/io.h>
    #include <inttypes.h>
    
    #define OSC 4
    
    #define PORT(X) XPORT(X)
    #define XPORT(X) (PORT##X)
    
    #define PIN(X) XPIN(X)
    #define XPIN(X) (PIN##X)
    
    #define DDR(X) XDDR(X)
    #define XDDR(X) (DDR##X)
    
    #define LCD_RSPORT B
    #define LCD_RS 2
    #define LCD_EPORT B
    #define LCD_E 1
    #define LCD_DPORT B
    #define LCD_D4 4
    #define LCD_D5 5 
    #define LCD_D6 6
    #define LCD_D7 7
    
    #define LCDC_CLS 0x01
    #define LCDC_HOME 0x02
    #define LCDC_MODE 0x04
    	#define LCDC_MODER 0x02
    	#define LCDC_MODEL 0
    	#define LCDC_MODEMOVE 0x01
    #define LCDC_ON 0x08
    	#define LCDC_ONDISPLAY 0x04
    	#define LCDC_ONCURSOR 0x02
    	#define LCDC_ONBLINK 0x01
    #define LCDC_SHIFT 0x10
    	#define LCDC_SHIFTDISP 0x08
    	#define LCDC_SHIFTR 0x04
    	#define LCDC_SHIFTL 0
    #define LCDC_FUNC 0x20
    	#define LCDC_FUNC8b 0x10
    	#define LCDC_FUNC4b 0
    	#define LCDC_FUNC2L 0x08
    	#define LCDC_FUNC1L 0
    	#define LCDC_FUNC5x10 0x4
    	#define LCDC_FUNC5x7 0
    #define LCDC_CGA 0x40
    #define LCDC_DDA 0x80
    
    #define delay250ns() {asm volatile("nop"::);}
    
    #define delayus8(t)\
    	{asm volatile( \
    		"delayus8_loop%=: \n\t"\
    			"nop \n\t"\
    			"dec %[ticks] \n\t"\
    			"brne delayus8_loop%= \n\t"\
    	::[ticks]"r"(t) );}
    
    void delay100us8(uint8_t t)
    {
    	while(t>0)
    	{
    		delayus8(100);
    		--t;
    	}
    }
    
    #define LCD_EPULSE() \
    	{PORT(LCD_EPORT) |= 1<<LCD_E; \
    	delay250ns(); \
    	PORTB &= ~(1<<LCD_E);}
    
    void LCDsendHalf(uint8_t data)
    {
    	data = (data & 0x0F) << LCD_D4;
    	PORT(LCD_DPORT) = (PORT(LCD_DPORT) & ~(0x0F<<LCD_D4)) | data;
    	LCD_EPULSE();
    }
    
    void LCDsend(uint8_t data)
    {
    	LCDsendHalf(data>>4);
    	LCDsendHalf(data);
    	delayus8(120);
    }
    
    void LCDcommand(uint8_t command)
    {
    	PORT(LCD_RSPORT) &= ~(1<<LCD_RS);
    	LCDsend(command);
    }
    
    void LCDdata(uint8_t data)
    {
    	PORT(LCD_RSPORT) |= 1<<LCD_RS;
    	LCDsend(data);
    }
    
    void LCDcls(void)
    {
    	LCDcommand(LCDC_CLS);
    	delay100us8(48);
    }
    
    void LCDhome(void)
    {
    	LCDcommand(LCDC_HOME);
    	delay100us8(48);
    }
    
    void LCDinit(void)
    {
    	delay100us8(150);
    	PORT(LCD_RSPORT) &= ~(1<<LCD_RS);
    	LCDsendHalf(LCDC_FUNC|LCDC_FUNC8b);
    	delay100us8(41);
    	LCDsendHalf(LCDC_FUNC|LCDC_FUNC8b);
    	delay100us8(2);
    	LCDsendHalf(LCDC_FUNC|LCDC_FUNC4b);
    	delay100us8(2);
    
    	LCDcommand(LCDC_FUNC|LCDC_FUNC4b|LCDC_FUNC2L|LCDC_FUNC5x7);
    	LCDcommand(LCDC_ON);
    	LCDcls();
    	LCDcommand(LCDC_MODE|LCDC_MODER);
    	LCDcommand(LCDC_ON|LCDC_ONDISPLAY|LCDC_ONCURSOR);
    }
    
    int main(void)
    {
    	DDR(LCD_DPORT) = 1<<LCD_E | 1<<LCD_RS | 0X0F<<LCD_D4;
    	LCDinit();
    	LCDcls();
    
    	LCDdata('W'); LCDdata('I'); LCDdata('T'); LCDdata('A'); LCDdata('J');
    	return 0;
    }
    


    Jakaś sugestia?
  • REKLAMA
  • #2 6272217
    kaktus_c++
    Poziom 18  
    możesz dodać do tego programu mryganie diodą np 1 /sekunde i zobaczyć czy chociaż ta dioda działa i czy mryga z oczekiwaną częstotliwością.
  • REKLAMA
  • #3 6272425
    esh0
    Poziom 19  
    kaktus_c++ napisał:
    możesz dodać do tego programu mryganie diodą np 1 /sekunde i zobaczyć czy chociaż ta dioda działa i czy mryga z oczekiwaną częstotliwością.


    Zrobiłem. Dodałem na początku
    
    #define TEST_PORT D
    #define TEST_PIN0 0


    i zmieniłem kod na:
    
    int main(void)
    {
    	uint8_t i;
    	DDR(LCD_DPORT) = 1<<LCD_E | 1<<LCD_RS | 0X0F<<LCD_D4;
    	DDR(TEST_PORT) = 0xFF;
    
    	LCDinit();
    	LCDcls();
    
    	LCDdata('W'); LCDdata('I'); LCDdata('T'); LCDdata('A'); LCDdata('J');
    	for(;;)
    	{
    		PORTD |= _BV(TEST_PIN0);
    		for(i=0;i<10;i++) delay100us8(250);
    		PORTD &= ~_BV(1<<TEST_PIN0);
    		for(i=0;i<10;i++) delay100us8(250);
    	};
    	return 0;
    }


    Dioda podłączona do portu D0 nie mryga (próbowałem dla większego opóźnienia - też nic)...
  • #4 6272624
    kaktus_c++
    Poziom 18  
    Więc najpierw musi zadziałać dioda, potem zajmij się lcd
    możesz dodać gdzieś na początku takie makro
    #define LED_D0_FLIP DDRD|=0x01; PORTD ^= 1;

    potem pętlę zrobić tak
    while(1)
    {
    LED_D0_FLIP;
    //przerwa czasowa (#include <util/delay.h>)
    _delay_ms(250);
    }
    

    i to powinno mrygać 2x na sekundę, bo te funkcje opóźniające z Twojego programu nie budzą mojego zaufania
    no i wogóle to czy kwarc 4mHz jest tutaj Ci potrzebny?
  • #5 6272632
    _Robak_
    Poziom 33  
    A funkcja delay jest twoja? Dziala tak jak powinna? 10*250 mikrosekund to 2.5ms. Nie wiem jak tam z twoimi oczami, ale moje takie odjechane nie sa zeby zobaczyc takie mryganie ;)
  • REKLAMA
  • #6 6272665
    esh0
    Poziom 19  
    Nie działa Twój pomysł :( Dioda ciągle świeci...
  • #7 6272667
    kaktus_c++
    Poziom 18  
    ja po nazwie delay100us8 bym się spodziewał że opóźnienie będzie wynosić 10* 100us*250 ale cholera wie...,
    po to są gotowe funkcje żeby z nich kożystać - takie jak delay_ms :D
  • #8 6272668
    esh0
    Poziom 19  
    _Robak_ napisałem, że próbowałem z o wiele więcej, czyli 1000*250us ;) A to już powinno być widać.
  • REKLAMA
  • #9 6272685
    _Robak_
    Poziom 33  
    Jak juz nie wiemy co tak na prawde jest nie tak, proponuje najpierw zaladowac swietna biblioteke, dzieki ktorej w mig odpalisz LCDka.
    http://homepage.hispeed.ch/peterfleury/group__pfleury__lcd.html
    Jak juz cos zobaczysz, to bedziesz wiedzial ze wszystko jest na dobrej drodze zeby dzialalo i bedziesz mial nowe sily na walke :) Moze napisze czemu akurat ta biblioteka, nie wazne co toba kierowalo podczas podlaczania LCDka, kazdy pin LCDka mozesz sobie skonfigurowac na dowlolnym pinie dowolnego portu uC.
    A jesli dalej bedziesz chcial sie bawic w swoja biblioteke to bedziesz mial na czym sie wzorowac :)
  • #10 6272759
    kaktus_c++
    Poziom 18  
    W tej sytuacji mogę zaproponować taki tok postępowania.
    1)wywalić wszystko co jest związane z obsługą lcd z programu
    2)fusebity ustawić na takie jak były na początku 1MHz
    3) Trenować diodę aż będzie działać jak należy
    4) http://radzio.dxp.pl/hd44780/ tu masz bibliotekę do lcd, każdy pin sobie ustawiasz jak chcesz, opis po polsku, sprawdziłem działa na pewno i używam ją.
    5)Stworzyć prosty program z lcd i go trenować do skutku tu masz pomoc http://wkretak.pl/readarticle.php?article_id=16
    6) Kombinacje z kwarcem 4MHz i fusebitam zostawić na koniec

    powodzenia
  • #11 6275820
    esh0
    Poziom 19  
    Paranoja jakaś...
    Fusebity: C1/99
    Program:
    
    #include <avr/io.h>
    #define F_CPU 1000000
    #include <util/delay.h>
    
    int main(void)
    {
    	DDRD |= 0x03;
    
    	while(1)
    	{
    		PORTD |= _BV(0);
    		PORTD |= _BV(1);
    		_delay_ms(250);
    		_delay_ms(250);
    		PORTD &= ~_BV(0);
    		PORTD &= ~_BV(1);
    		_delay_ms(250);
    		_delay_ms(250);
    	} 
    	return 0;
    }
    

    I co? i tylko delikatnie świecą diody na portach D0 i D1...
  • #12 6275878
    _Robak_
    Poziom 33  
    Kolega niech wylaczy watch doga!! Do budy z nim albo go resetowac co jakis czas!!
    Ustaw fusy na C1/D9 i bedzie smigac az milo
  • #13 6275952
    esh0
    Poziom 19  
    _Robak_ DZIĘKI!! Działa :)

    Mógłbyś jeszcze mi wyjaśnić dlaczego watchdog przeszkadzał w tym?
  • #14 6275954
    _Robak_
    Poziom 33  
    Bo go nie resetowales, a wsciekly pies za to ci procka resetowal, co objawialo sie szybko mrygajaca dioda ;)
REKLAMA