LCD library hatası sorun ne olabilir?

Başlatan zakbay, 21 Mart 2012, 10:56:50

zakbay

Arkadaşlar merhaba

Atmelle uğraştığım sürece sisteme yabancılığım yüzünden sanırım daha fazla problemle karşılaşacağım.

Aşağıdaki lcd sürücüsünü atmega88 dahili 8mhz de kullanıyorum.

Zaman zaman lcd deki karakterler saçmalıyor. Bu sorunu aşmak içinde ara sıra lcd yi yeniden init etmek gerekiyor.

Hatta init kısmıda tam olarak işi çözmüyordu swordwish lcd kütüphanesini inceleyip aynısını yaptığımda init sorunu halloldu.

Gerçek uygulamada da simülasyonda da karışma olabiliyor bazen birkaç dakika bazen 10 dk sonra yapabiliyor.

isis hata penceresinde herhangi bir hatayla karşılaşmıyorum karıştığı zaman

Böyle bir sorunla karşılaşan oldu mu?


Atmega 88 ve 2 satır 16 karakter lcd kullanıyorum.

LCD.c
//*****************************************************************************
//
// File Name	: 'lcd_lib.c'
// Title		: 4 bit LCd interface
// Author		: Scienceprog.com - Copyright (C) 2007
// Created		: 2007-06-18
// Revised		: 2007-06-18
// Version		: 1.0
// Target MCU	: Atmel AVR series
//
// This code is distributed under the GNU Public License
//		which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************
#include "lcd_lib.h"
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

void LCD_4bitBas(uint8_t veri){
	if (veri&1){LCD_veri4_1;}else{LCD_veri4_0;}
	if (veri&2){LCD_veri5_1;}else{LCD_veri5_0;}
	if (veri&4){LCD_veri6_1;}else{LCD_veri6_0;}
	if (veri&8){LCD_veri7_1;}else{LCD_veri7_0;}
}

void LCDsendChar(uint8_t ch)		//Sends Char to LCD
{
		RS1;								//karakter gonder
		_delay_us(1);
		E1;									//strobeEn
		_delay_us(1);
		LCD_4bitBas((ch&0b11110000)>>4);
		E0;
		_delay_us(DataUs);

		E1;
		_delay_us(1);
		LCD_4bitBas(ch&0b00001111);
		E0;
		_delay_us(DataUs);

//	LDP=((ch&0b11110000)>>4); //once ust bit
//	LCP|=1<<LCD_RS;
//	LCP|=1<<LCD_E;
//	_delay_us(DataUs);
//	LCP&=~(1<<LCD_E);
//	LCP&=~(1<<LCD_RS);
//	_delay_us(DataUs);
//
//	LDP=(ch&0b00001111);	//sonra alt bit
//	LCP|=1<<LCD_RS;
//	LCP|=1<<LCD_E;
//	_delay_us(DataUs);
//	LCP&=~(1<<LCD_E);
//	LCP&=~(1<<LCD_RS);
//	_delay_us(DataUs);
}
void LCDsendCommand(uint8_t cmd)	//Sends Command to LCD
{
	RS0;								//komut gonder
	_delay_us(1);
	E1;									//strobeEn
	_delay_us(1);
	LCD_4bitBas((cmd&0b11110000)>>4);
	E0;
	_delay_us(CmdUs);

	E1;
	_delay_us(1);
	LCD_4bitBas(cmd&0b00001111);
	E0;
	_delay_ms(1);//bu 1ms olmalı
	_delay_us(DataUs);

//	LDP=((cmd&0b11110000)>>4);
//	LCP|=1<<LCD_E;
//	_delay_ms(1);
//	LCP&=~(1<<LCD_E);
//	_delay_ms(1);
//	LDP=(cmd&0b00001111);
//	LCP|=1<<LCD_E;
//	_delay_ms(1);
//	LCP&=~(1<<LCD_E);
//	_delay_ms(1);
}
void LCDinit(void)//Initializes LCD
{
	//GİRİS CIKIS AYARLARI
	LDDR |= 1<<LCD_D7 | 1<<LCD_D6 | 1<<LCD_D5 | 1<<LCD_D4;
	LCDR |= 1<<LCD_E | 1<<LCD_RS; //|1<<LCD_RW

	//_delay_ms(100); bu normal init te olacak kırpışmaması için kapatıldı ilk init öncesi 100ms verildi
	RS0;
	E0;
	_delay_ms(15);
	LDP=0x00;
	LCP=0x00;

	LDP &= ~(1 << LCD_D7);  //0
	LDP &= ~(1 << LCD_D6);  //0
	LDP &= ~(1 << LCD_D5);  //0
	LDP &= ~(1 << LCD_D4);  //0

	LDP &= ~(1 << LCD_D7);  //0
	LDP &= ~(1 << LCD_D6);  //0
	LDP |= 1 << LCD_D5;     //1
	LDP |= 1 << LCD_D4; 	//1
	E1;
	E0;

	_delay_ms(5);

	LDP &= ~(1 << LCD_D7); //0
	LDP &= ~(1 << LCD_D6);
	LDP &= ~(1 << LCD_D5);
	LDP &= ~(1 << LCD_D4);

	LDP &= ~(1 << LCD_D7);
	LDP &= ~(1 << LCD_D6);
	LDP |= 1 << LCD_D5;
	LDP |= 1 << LCD_D4;
	E1;
	E0;
	_delay_us(160);

	LDP &= ~(1 << LCD_D7);
	LDP &= ~(1 << LCD_D6);
	LDP &= ~(1 << LCD_D5);
	LDP &= ~(1 << LCD_D4);

	LDP &= ~(1 << LCD_D7);
	LDP &= ~(1 << LCD_D6);
	LDP |= 1 << LCD_D5;
	LDP |= 1 << LCD_D4;
	E1;
	E0;
	_delay_us(160);

	LDP &= ~(1 << LCD_D7);
	LDP &= ~(1 << LCD_D6);
	LDP &= ~(1 << LCD_D5);
	LDP &= ~(1 << LCD_D4);

	LDP &= ~(1 << LCD_D7);
	LDP &= ~(1 << LCD_D6);
	LDP |= 1 << LCD_D5;
	LDP &= ~(1 << LCD_D4);
	E1;
	E0;
	_delay_us(160);

// 	problemli init kısmı sağlıklı çalışmıyor
//   //---------one------
//	LDP = 0<<LCD_D7 | 0<<LCD_D6 | 1<<LCD_D5 | 1<<LCD_D4; //4 bit mode
//	LCP |= 1<<LCD_E | 0<<LCD_RS; //|0<<LCD_RW
//	_delay_ms(2);
//	LCP&=~(1<<LCD_E);
//	_delay_ms(2);
//	//-----------two-----------
//	LDP = 0<<LCD_D7 | 0<<LCD_D6 | 1<<LCD_D5 | 1<<LCD_D4; //4 bit mode
//	LCP|=1<<LCD_E|0<<LCD_RS;//|0<<LCD_RW
//	_delay_ms(2);
//	LCP&=~(1<<LCD_E);
//	_delay_ms(2);
//	//-------three-------------
//	LDP=0<<LCD_D7|0<<LCD_D6|1<<LCD_D5|0<<LCD_D4; //4 bit mode
//	LCP|=1<<LCD_E|0<<LCD_RS;//|0<<LCD_RW
//	_delay_ms(2);
//	LCP&=~(1<<LCD_E);
//	_delay_ms(2);


	//--------4 bit--dual line---------------
	LCDsendCommand(0b00101000); //Fonksiyon belirleme: 4 bit arabirim, 2 satır, 5*8 font,
   //-----increment address, cursor shift------
	//LCDsendCommand(0b00001110); orjinal kütüphanede sadece bu var

	LCDsendCommand(0b00001000);    // D = 0, C = 0, B = 0
	LCDsendCommand(0b00000001);    // Clear
	LCDsendCommand(0b00000110);    // ID = 1, S = 0
	LCDsendCommand(0b00001100);    // D = 1, C = 0, B = 0
}			
void LCDclr(void)				//Clears LCD
{
	LCDsendCommand(1<<LCD_CLR);
}
void LCDhome(void)			//LCD cursor home
{
	LCDsendCommand(1<<LCD_HOME);
}
void LCDstring(uint8_t *data, uint8_t nBytes)	//Outputs string to LCD
{
register uint8_t i;

	// check to make sure we have a good pointer
	if (!data) return;

	// print data
	for(i=0; i<nBytes; i++)
	{
		LCDsendChar(data[i]);
	}
}
void LCDGotoXY(uint8_t sutun, uint8_t satir)	//Cursor to X Y position
{
	register uint8_t DDRAMAddr;
	// remap lines into proper order
	switch(satir)
	{
	case 0: DDRAMAddr = LCD_LINE0_DDRAMADDR+sutun; break;
	case 1: DDRAMAddr = LCD_LINE1_DDRAMADDR+sutun; break;
	case 2: DDRAMAddr = LCD_LINE2_DDRAMADDR+sutun; break;
	case 3: DDRAMAddr = LCD_LINE3_DDRAMADDR+sutun; break;
	default: DDRAMAddr = LCD_LINE0_DDRAMADDR+sutun;
	}
	// set data address
	LCDsendCommand(1<<LCD_DDRAM | DDRAMAddr);
	
}
//Copies string from flash memory to LCD at x y position
//const uint8_t welcomeln1[] PROGMEM="AVR LCD DEMO\0";
//CopyStringtoLCD(welcomeln1, 3, 1);	
void CopyStringtoLCD(const uint8_t *FlashLoc, uint8_t x, uint8_t y)
{
	uint8_t i;
	LCDGotoXY(x,y);
	for(i=0;(uint8_t)pgm_read_byte(&FlashLoc[i]);i++)
	{
		LCDsendChar((uint8_t)pgm_read_byte(&FlashLoc[i]));
	}
}

void LCDyaziyaz(char yazi[],uint8_t adet){
	uint8_t i;
	for (i=0;i<adet;i++){
		LCDsendChar(yazi[i]);
	}
}
//defines char symbol in CGRAM
/*
const uint8_t backslash[] PROGMEM= 
{
0b00000000,//back slash
0b00010000,
0b00001000,
0b00000100,
0b00000010,
0b00000001,
0b00000000,
0b00000000
};
LCDdefinechar(backslash,0);
LCDsendChar(8);
*/
//LCDsendChar(0);
//doluok
const uint8_t derecesembol[] PROGMEM = { 0x06, 0x09, 0x09, 0x06, 0x00, 0x00, 0x00, 0x00};//derece 0
const uint8_t isitmasembol[] PROGMEM = { 0x12, 0x09, 0x12, 0x09, 0x00, 0x1F, 0x1F, 0x00};
void LCDdefinechar(const uint8_t *pc,uint8_t char_code){
	uint8_t a, pcc;
	uint16_t i;
	a=(char_code<<3)|0x40;
	for (i=0; i<8; i++){
		pcc=pgm_read_byte(&pc[i]);
		LCDsendCommand(a++);
		LCDsendChar(pcc);
		}
}

void LCDshiftLeft(uint8_t n)	//Scrol n of characters Right
{
	for (uint8_t i=0;i<n;i++)
	{
		LCDsendCommand(0x1E);
	}
}
void LCDshiftRight(uint8_t n)	//Scrol n of characters Left
{
	for (uint8_t i=0;i<n;i++)
	{
		LCDsendCommand(0x18);
	}
}
void LCDcursorOn(void) //displays LCD cursor
{
	LCDsendCommand(0x0E);
}
void LCDcursorOnBlink(void)	//displays LCD blinking cursor
{
	LCDsendCommand(0x0F);
}
void LCDcursorOFF(void)	//turns OFF cursor
{
	LCDsendCommand(0x0C);
}
void LCDblank(void)		//blanks LCD
{
	LCDsendCommand(0x08);
}
void LCDvisible(void)		//Shows LCD
{
	LCDsendCommand(0x0C);
}
void LCDcursorLeft(uint8_t n)	//Moves cursor by n poisitions left
{
	for (uint8_t i=0;i<n;i++)
	{
		LCDsendCommand(0x10);
	}
}
void LCDcursorRight(uint8_t n)	//Moves cursor by n poisitions left
{
	for (uint8_t i=0;i<n;i++)
	{
		LCDsendCommand(0x14);
	}
}


//*****************************************************************************
//
// File Name	: 'lcd_lib.h'
// Title		: 4 bit LCd interface header file
// Author		: Scienceprog.com - Copyright (C) 2007
// Created		: 2007-06-18
// Revised		: 2007-06-18
// Version		: 1.0
// Target MCU	: Atmel AVR series
//
// This code is distributed under the GNU Public License
//		which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************
#ifndef LCD_LIB
#define LCD_LIB

#include <inttypes.h>

#define LCD_RS	5 	//define MCU pin connected to LCD RS
//#define LCD_RW	1 	//define MCU pin connected to LCD R/W
#define LCD_E	4	//define MCU pin connected to LCD E
#define LCD_D4	0	//define MCU pin connected to LCD D3
#define LCD_D5	1	//define MCU pin connected to LCD D4
#define LCD_D6	2	//define MCU pin connected to LCD D5
#define LCD_D7	3	//define MCU pin connected to LCD D6
#define LDP PORTB	//define MCU port connected to LCD data pins
#define LCP PORTB	//define MCU port connected to LCD control pins
#define LDDR DDRB	//define MCU direction register for port connected to LCD data pins
#define LCDR DDRB	//define MCU direction register for port connected to LCD control pins

#define DataUs	350 	//data 100us yeterli swordfish de 50us
#define CmdUs	350

#define RS0	LCP &= ~(1 << LCD_RS)
#define RS1 LCP |= 1 << LCD_RS

#define E0	LCP &= ~(1 << LCD_E)
#define E1 	LCP |= 1 << LCD_E

#define LCD_veri4_1		LDP |= 1 << LCD_D4
#define LCD_veri5_1		LDP |= 1 << LCD_D5
#define LCD_veri6_1		LDP |= 1 << LCD_D6
#define LCD_veri7_1		LDP |= 1 << LCD_D7

#define LCD_veri4_0		LDP &= ~(1 << LCD_D4)
#define LCD_veri5_0		LDP &= ~(1 << LCD_D5)
#define LCD_veri6_0		LDP &= ~(1 << LCD_D6)
#define LCD_veri7_0		LDP &= ~(1 << LCD_D7)

#define LCD_CLR             0	//DB0: clear display
#define LCD_HOME            1	//DB1: return to home position
#define LCD_ENTRY_MODE      2	//DB2: set entry mode
#define LCD_ENTRY_INC       1	//DB1: increment
#define LCD_ENTRY_SHIFT     0	//DB2: shift
#define LCD_ON_CTRL         3	//DB3: turn lcd/cursor on
#define LCD_ON_DISPLAY      2	//DB2: turn display on
#define LCD_ON_CURSOR       1	//DB1: turn cursor on
#define LCD_ON_BLINK        0	//DB0: blinking cursor
#define LCD_MOVE            4	//DB4: move cursor/display
#define LCD_MOVE_DISP       3	//DB3: move display (0-> move cursor)
#define LCD_MOVE_RIGHT      2	//DB2: move right (0-> left)
#define LCD_FUNCTION        5	//DB5: function set
#define LCD_FUNCTION_8BIT   4	//DB4: set 8BIT mode (0->4BIT mode)
#define LCD_FUNCTION_2LINES 3	//DB3: two lines (0->one line)
#define LCD_FUNCTION_10DOTS 2	//DB2: 5x10 font (0->5x7 font)
#define LCD_CGRAM           6	//DB6: set CG RAM address
#define LCD_DDRAM           7	//DB7: set DD RAM address
// reading:
#define LCD_BUSY            7	//DB7: LCD is busy
#define LCD_LINES			2	//visible lines
#define LCD_LINE_LENGTH		16	//line length (in characters)
// cursor position to DDRAM mapping
#define LCD_LINE0_DDRAMADDR		0x00
#define LCD_LINE1_DDRAMADDR		0x40
#define LCD_LINE2_DDRAMADDR		0x14
#define LCD_LINE3_DDRAMADDR		0x54

void LCDsendChar(uint8_t);		//forms data ready to send to 74HC164
void LCDsendCommand(uint8_t);	//forms data ready to send to 74HC164
void LCDinit(void);			//Initializes LCD
void LCDclr(void);				//Clears LCD
void LCDhome(void);			//LCD cursor home
void LCDstring(uint8_t*, uint8_t);	//Outputs string to LCD
void LCDGotoXY(uint8_t, uint8_t);	//Cursor to X Y position
void CopyStringtoLCD(const uint8_t*, uint8_t, uint8_t);//copies flash string to LCD at x,y
void LCDdefinechar(const uint8_t *,uint8_t);//write char to LCD CGRAM 
void LCDshiftRight(uint8_t);	//shift by n characters Right
void LCDshiftLeft(uint8_t);	//shift by n characters Left
void LCDcursorOn(void);		//Underline cursor ON
void LCDcursorOnBlink(void);	//Underline blinking cursor ON
void LCDcursorOFF(void);		//Cursor OFF
void LCDblank(void);			//LCD blank but not cleared
void LCDvisible(void);			//LCD visible
void LCDcursorLeft(uint8_t);	//Shift cursor left by n
void LCDcursorRight(uint8_t);	//shif cursor right by n
void LCD_4bitBas(uint8_t veri);
#endif
Tek dostum çalışmak...

parda

AvrGcc kullanıyorsanız,
Peter Fleury lcd kütüphanesini kullanıyorum. Oldukça esnek ve profesyonel tavsiye ederim.
Bildiğim tek şey, hiç bir şey bilmediğimdir.

zakbay

Evet hocam Eclipse-winavr kullanıyorum.

Aynı kütüphaneyi daha önce 4mhz de atmega16 ile kullanmıştım herhangi bir sorunla karşılaşmamıştım.

Peter Fleury lcd kütüphanesini araştırıyorum sonucu buradan yazacağım
sağolun


Tek dostum çalışmak...

Kabil ATICI

Doğrudan atmega serisinde değilde at89cxx sewrisinde bu tipte sorunlarla karşılaştım. Çözüm olarak;
Vo bacağı (kontrast ayarı) toprak (gnd) arasına 10µF kondansatör bağlama;
LCD için kodlarda meşguliyet kontrolu yapma;
baskı devrede gnd bağlantısında geniş alanlar ayırma. Aksi durumda kartı bir metal yüzeye yakın (temas ettirmesizin) monte etme;
Program için ekranın e,rs,rw bacakları kontrolleri için ve veri portu için gerekli zamanı tanıyacak şekilde düzenleme.
Kristalin GND ucu bağlanması.
Bu gibi düzenlemeler ile karakter LCD kullanımından kaynaklanan hatalar ortadan kaldırıldı. Sonuçta bu gibi düzenlemeler atmega serisinde de kullandığım için bir sorunla karşılaşmadım.
ambar7

zakbay

#4
@ambar7
Hocam merhaba anlattıklarınızı not ettim. Fakat problem sadece dış etkilerden kaynaklanmıyor. Simülasyonda da aynı şekilde hata yapması driverdan kaynaklandığını gösteriyor. Tam olarak tespit edemedim. Bazen 10 dakikada bazen 1 dakikada bazen 3 saatte yapabiliyor.

Birde hiç bahsetmemişim ana programda timer1 kesmesi kullanarak 1sn elde ediyorum her saniyede ekran sürekli güncelleniyor.

Peter Fleury kütüphanesini inceledim rw bacağınıda kullanıp okuma yapmış bu saatten sonra baskı devreyi değiştiremem mecburen 6 pinle sorunsuz bir şekilde lcdyi kullanmak zorundayım.

Birde şöyle ilginç bir gelişme oldu.

void LCD_4bitBas(uint8_t veri){
    if (veri&1){LCD_veri4_1;}else{LCD_veri4_0;}
    if (veri&2){LCD_veri5_1;}else{LCD_veri5_0;}
    if (veri&4){LCD_veri6_1;}else{LCD_veri6_0;}
    if (veri&8){LCD_veri7_1;}else{LCD_veri7_0;}
}

RS1;								//karakter gonder
        _delay_us(1);
        E1;									//strobeEn
        _delay_us(1);
        LCD_4bitBas((ch&0b11110000)>>4);
        E0;
        _delay_us(DataUs);

        E1;
        _delay_us(1);
        LCD_4bitBas(ch&0b00001111);
        E0;
        _delay_us(DataUs);


Yukarıdaki kod sık sık problem çıkarırken aşağıdaki kod nispeten daha az problem çıkarıyor. Arasındaki fark yukarıdaki kodda data verisi porta tek tek basılırken aşağıdaki kodda veri bir kerede porta basılıyor.

LDP=((ch&0b11110000)>>4); //once ust bit

	LCP|=1<<LCD_RS;
	LCP|=1<<LCD_E;
	_delay_us(DataUs);
	LCP&=~(1<<LCD_E);
	LCP&=~(1<<LCD_RS);
	_delay_us(DataUs);


Aklıma şu da geliyor saçma gelebilir ama

Verileri tek tek ekrana basarken aşağıdaki gibi makroları kullanıyoruz. Bu makro kullanımı doğrumu? Doğrudan port üzerinde işlem yapılıyor.
Acaba bu sırada enable yada rs pinlerinde de bir değişiklik oluyormudur?

Problemi çözemediğim için en alakasız şeyleride düşünür hale geldim :)

#define LCD_veri7_1      LDP |= 1 << LCD_D7
#define LCD_veri4_0      LDP &= ~(1 << LCD_D4)

Tek dostum çalışmak...