Picproje Elektronik Sitesi

MİKRODENETLEYİCİLER => Atmel => Konuyu başlatan: zakbay - 21 Mart 2012, 10:56:50

Başlık: LCD library hatası sorun ne olabilir?
Gönderen: zakbay - 21 Mart 2012, 10:56:50
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

Başlık: Ynt: LCD library hatası sorun ne olabilir?
Gönderen: parda - 21 Mart 2012, 11:09:17
AvrGcc kullanıyorsanız,
Peter Fleury lcd kütüphanesini kullanıyorum. Oldukça esnek ve profesyonel tavsiye ederim.
Başlık: Ynt: LCD library hatası sorun ne olabilir?
Gönderen: zakbay - 21 Mart 2012, 11:13:32
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


Başlık: Ynt: LCD library hatası sorun ne olabilir?
Gönderen: Kabil ATICI - 21 Mart 2012, 17:33:59
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.
Başlık: Ynt: LCD library hatası sorun ne olabilir?
Gönderen: zakbay - 22 Mart 2012, 00:12:57
@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)