LCD 16x2


lupu1001


incerc sa interfatez un lcd de acest tip cu un atmega32 si nu gasesc niste librarii calumea pe net. Daca aveti ceva idei sau soft va rog postati aici. Mersi
Fratello
De unde ai luat si cu cit ? As vrea si eu sa-mi pun unul la PC, dar folosind SmartLCD...
 
ilya
are la comet electronics cu duiumu. edit: www.comet.srl.ro /edit.
@lupu, man sincer îți recomand să înveți întâi interfața lui low-level, care nu e grea deloc.. ajută enorm la debugging.
lupu1001
QUOTE (ilya @ Dec 31 2007, 11:06) *
are la comet electronics cu duiumu. edit: www.comet.srl.ro /edit.
@lupu, man sincer îți recomand să înveți întâi interfața lui low-level, care nu e grea deloc.. ajută enorm la debugging.



CODE!

#include <avr/io.h>
void setEN(){
PORTD=PORTD | (64);
}
void clearEN(){
PORTD=PORTD & (63);
}
void setRS(){
PORTD=PORTD | (32);
}
void clearRS(){
PORTD=PORTD & (31);
}
void setRW(){
PORTD=PORTD | (16);
}
void clearRW(){
PORTD=PORTD & (15);
}
void delay(void)
{
long i;
for (i=0;i<=9999;i++);
}
void command(unsigned char val)
{
clearRS(); //command mode
PORTA=val;
delay();
setEN();
clearEN();
}
void startup(){

setRS(); // when starting the lcd rs should be set low
clearEN(); // and EN low
}
void ini()
{
command(0x38); // function set (8 bit,2 rows,5x7 dot format)
command(0x38);
command(0xF); //display on off + cursor style / blinking
command(0x1); //clear display
command(0x7);

// cele 5 comenzi de mai sus fac parte din rutina de initializare din datasheet.

setRS(); //switch the chip from command mode to Character mode
PORTA=0x41; //trimit "A" la cd
delay();
setEN();//enables the chip to accept data
clearEN();

}
int main()
{
startup();
ini();
while (1){
}
return 0;
}

LCD 16x2 este legat la portA(toti cei 8 pini) al unui atmega32 si comanda pe PORTD (E legat la pinul 6,RS legat la pinul 5,RW legat la pinul 4).
Ce e in neregula cu acest cod? el ar trebui sa printeze pe LCD caracterul "A" urmat de cursor(blinking) (zic eu).
Pare-se ca nu merge si nu am idee de ce.
Contrastul l-am setat deci nu asta ar fi problema.
Help pls!

am atasat si datasheetul tot aici.
ilya
pai ai putea sa ne spui daca respectivul cod se compileaza ok, daca ai activitate pe pinii ucului si cum se manifesta acum, ce apare pe ecran, daca se intampla ceva in neregula, etc.
lupu1001
QUOTE (ilya @ Jan 2 2008, 20:11) *
pai ai putea sa ne spui daca respectivul cod se compileaza ok, daca ai activitate pe pinii ucului si cum se manifesta acum, ce apare pe ecran, daca se intampla ceva in neregula, etc.


da, codul compileaza:

Build started 2.1.2008 at 19:12:03
avr-gcc -mmcu=atmega32 -Wall -gdwarf-2 -O0 -fsigned-char -Wp,-M,-MP,-MT,vvv.o,-MF,dep/vvv.o.d -c ../vvv.c
avr-gcc -mmcu=atmega32 -Wl,-Map=vvv.map vvv.o -o vvv.elf
avr-objcopy -O ihex -R .eeprom vvv.elf vvv.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex vvv.elf vvv.eep
c:\WinAVR-20070525\bin\avr-objcopy.exe: there are no sections to be copied!
c:\WinAVR-20070525\bin\avr-objcopy.exe: --change-section-lma .eeprom=0x00000000 never used
make: *** [vvv.eep] Error 1
Build succeeded with 0 Warnings...

acel "make: *** [vvv.eep] Error 1" ma cam streseaza la vedere dar hexul pare a fi ok de fiecare data (activitatea pe pini simulata in isis cel putin )

simulat in PROTEUS ... pinii sunt ok... activitate pe ei exact cum ar trebui... numai ca tot ce vad : (IN PROTEUS este lcd-ul apris si atata tot).. iar pe LCD-ul propriu-zis totul este ca si cum controllerul este doar alimentat... observ doar unul din cele doua randuri de caractere mai pronuntat
( de genul
################
################
)

Nothing happens.
Am incercat sa fac sa apara si numai cursorul si tot nimic sad.gif
Any ideea would be helpful w00t.gif
tehnics
Daca ai idee de un pic BASIC , incearca cu BASCOM...acolo ai si un LCD view-er pentru a putea simula si microcontrolerele conectate la LCD.
Are chiar sample pe un LCD de 16x2, numia ca e pentru AT2313 parca, dar il poti modifica tu
 
ilya
tot în proteus simulez și eu. dacă nu îți apare acolo, e f posibil să fi inversat cumva pinii intre ei. lucrezi pe breadboard, placă de teste, pcb?
eu m-am chinuit ceva până am reușit să leg un lcd.

faptul că vezi unul dintre rânduri mai pronunțate e din cauză că semnalele nu au fost trimise corect, și lcdul e încă în modul de lucru pe o singură linie. fă-l să meargă în simulator, vezi ce e greșit. dacă ai semnale pe pini, nu ar trebui să ai probleme. fă-l întâi cu transmisie pe 8 biți (te chinui la separat nibbleuri) și doar în read mode. vezi dacă merge așa. salvează (eventual commit în csv/svn dacă folosești), mai fă o modificare, gen 4 biți sau nu mai folosești delayuri, ci verifici bitul de busy.

apropo, ai pus timpuri ceva mai mari decât în specificații, nu? văd că delayurile tu le ai pe numărare de cicli, sunt în limite acceptabile, nu la nanosecundă, da ? biggrin.gif happy.gif
SuperDuper
1. Cat dureaza incrementarea aia pana la 9999? Are timp data la iesire sa se stabileasca?
2. S-ar putea sa fie prea rapida secventa de comanda de enable urmata de disable. Citirea caracterului in LCD se face pe front crescator (atunci ar fi ok)?
3. Pinul 6 este PB5. Esti sigur cu numerele alea - 64 pentru EN nu te duce la PB6?
lupu1001


QUOTE (SuperDuper @ Jan 3 2008, 02:46) *
1. Cat dureaza incrementarea aia pana la 9999? Are timp data la iesire sa se stabileasca?
2. S-ar putea sa fie prea rapida secventa de comanda de enable urmata de disable. Citirea caracterului in LCD se face pe front crescator (atunci ar fi ok)?
3. Pinul 6 este PB5. Esti sigur cu numerele alea - 64 pentru EN nu te duce la PB6?


3.Numerele alea se refera la numarul pinului de pe portul D. O exprimare mai buna ar fi fost (E legat la PD6, RS legat la PD5,RW la PD4).
Deci de legat sunt ok legati. In plus, este verificata si re-verificata legatura intre LCD si uC. Deci doar codul cred ca este problema. Cel putin, simularea in isis arata (la un delay mai mare sau la o frecventa mai joasa a uC) ca semnalul este trimis corect la pini smile.gif.

2. M-am gandit la asta . Voi incerca sa dau un asm("NOP"); sau un delay ceva. Cat despre Citirea caracterului in lcd.. n-am observat ceva mentionat despre asta in datasheet. Am citit ca de obicei textul apare pe ecran pe falling edge al lui E... daca la asta te referi.

1.Am incercat cu variate delayuri si nu merge.

Am atasat si modul de legare .
ilya
schimbă polaritatea lui enable, sau, mai bine, trimite două pulsuri de clock. eu așa am nimerit-o prima dată. vezi să ții R/W în W (masă).

nu mă refeream la citirea caracterului din lcd, dar poți citi flagul de busy. astfel, în loc să aștepți un timp arbitrar, știi exact când termină, și poți executa următoarea comandă mult mai rapid.
SuperDuper
QUOTE (lupu1001 @ Jan 2 2008, 21:45) *
3.Numerele alea se refera la numarul pinului de pe portul D. O exprimare mai buna ar fi fost (E legat la PD6, RS legat la PD5,RW la PD4).
Deci de legat sunt ok legati. In plus, este verificata si re-verificata legatura intre LCD si uC. Deci doar codul cred ca este problema. Cel putin, simularea in isis arata (la un delay mai mare sau la o frecventa mai joasa a uC) ca semnalul este trimis corect la pini smile.gif.

2. M-am gandit la asta . Voi incerca sa dau un asm("NOP"); sau un delay ceva. Cat despre Citirea caracterului in lcd.. n-am observat ceva mentionat despre asta in datasheet. Am citit ca de obicei textul apare pe ecran pe falling edge al lui E... daca la asta te referi.

1.Am incercat cu variate delayuri si nu merge.

Am atasat si modul de legare .

Deci numerele sunt ok din cate vad acum, intelesesem eu gresit...
Pinii aia de iesire nu cumva ar trebui sa aiba rezistente de pull up (cam 10kohmi) pentru pinii de control ai LCD-ului?
Incerca varianta cu pinul R/W la masa (doar pentru afisare).
Alta idee este sa incerci secventa de initializare in ordinea din exemplul asta http://www.beyondlogic.org/parlcd/parlcd.htm :
init[0] = 0x0F; /* Init Display */
init[1] = 0x01; /* Clear Display */
init[2] = 0x38; /* Dual Line / 8 Bits */
ilya
încearcă să pui pinii cu denumirea lor simbolică de pin. e posibil să te fi încurcat acolo, eu nu știu cum e pinoutul pe atmeluri.
mă refer, în loc să alegi unul din PORTD, cu ANDuri și ORuri, pune-l ca RA1, RB3, etc.. mă rog, nu e cu RA, așa e la pice, dar prinzi ideea.
lupu1001
QUOTE (SuperDuper @ Jan 4 2008, 02:47) *
Deci numerele sunt ok din cate vad acum, intelesesem eu gresit...
Pinii aia de iesire nu cumva ar trebui sa aiba rezistente de pull up (cam 10kohmi) pentru pinii de control ai LCD-ului?
Incerca varianta cu pinul R/W la masa (doar pentru afisare).
Alta idee este sa incerci secventa de initializare in ordinea asta:
init[0] = 0x0F; /* Init Display */
init[1] = 0x01; /* Clear Display */
init[2] = 0x38; /* Dual Line / 8 Bits */


Mersi tuturor de indicatii. Am rezolvat pana la urma asa :

.code
.not my code!
!!!!!!!!!!!!!!!!!!!!!!!!----------------- credit goes to microcarl ( www.avrfreaks.net ) ---------------------!!!!!!!!!!!!!!!!!!!!!!!!!

#include <avr/io.h>

/*
* Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the below copyright notice appears in all copies and that both the copyright notice and this permission notice appear in supporting documentation. Livingston Electronics makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.
*
*
* 8 BIT LCD control program
* Written by Carl W. Livingston
* Modified in a attempt to get working by some other guy
* Copyright Carl W. Livingston
* microcarl@roadrunner.com
* AVR Freaks member - microcarl
* January 02, 2007
* */

/* //// From the LCD perspective \\\\
LCD:R/W <-- PORTD:4
LCD:RS <-- PORTD:5
LCD:E <-- PORTD:6
N/A <-> PORTD:7

LCD:R/W <-- PORTD:4
LCD:RS <-- PORTD:5
LCD:E <-- PORTD:6
LCD:Vee <-- CONTRAST
LCD:DB0 <-- PORTB:0
LCD:DB1 <-- PORTB:1
LCD:DB2 <-- PORTB:2
LCD:DB3 <-- PORTB:3
LCD:DB4 <-- 4.7K Ohm <-- PORTx:4
LCD:DB5 <-- 4.7K Ohm <-- PORTx:5
LCD:DB6 <-- 4.7K Ohm <-- PORTx:6
LCD:DB7 <-- 4.7K Ohm <-- PORTx:7

//// From the I/O PORTD perspective \\\\
PORTD:4 --> LCD:R/W
PORTD:5 --> LCD:RS
PORTD:6 --> LCD:E
PORTD:7 <-> N/A

PORTB:0 --> LCD:DB0
PORTB:1 --> LCD:DB1
PORTB:2 --> LCD:DB2
PORTB:3 --> LCD:DB3
PORTB:4 --> 4.7K Ohm --> LCD:DB4
PORTB:5 --> 4.7K Ohm --> LCD:DB5
PORTB:6 --> 4.7K Ohm --> LCD:DB6
PORTB:7 --> 4.7K Ohm --> LCD:DB7
*/

/*************************************************************/
/*************************************************************/
// If you want to use a different I/O port for LCD control & data,
// do it here!!!
#define LCD_DATA_OUT PORTA
#define LCD_DATA_IN PINA
#define LCD_DATA_DDR DDRA

#define LCD_CONTROL_OUT PORTD
#define LCD_CONTROL_IN PIND
#define LCD_CONTROL_DDR DDRD

// Define LCD Read/Write as PORTx, 0x10;
#define LCD_RW 4
// Define LCD Register Select as PORTx, 0x20;
#define LCD_RS 5
// Define LCD Enable as PORTx, 0x40;
#define LCD_E 6
/*************************************************************/
/*************************************************************/

// LCD busy status bit
#define LCD_BUSY 7
// LED control bit
#define LED 1
// BAUD rate control bits
#define J_1 2
#define J_2 3
#define CGRAM 6

// Turn on power to the display, no cursor
#define PWR_ON 0x0C
// Set 8 data bits
#define DATA_8 0x30
// Set 8 data bits, 4 display lines
#define LINE_8x4 0x38
// Clear display command
#define CLR_DSP 0x01
// Character generator RAM command
#define REG_MODE 0xFE

#define NULL 0x00

void LCD_Delay (unsigned int);
void LCD_PutCmd (char);
void LCD_PutChar (char);
char LCD_BusyWait (void);
void IO_INIT (void);
void LCD_INIT (void);



// Clock cycle = 67nS @ 14.7456MHz
// Delay resolution ~ 1uS @ 14.7456MHz
void LCD_Delay (unsigned int d) {
while (d-- != 0)
;
asm("nop"); // Make the delay time a bit closer to the predicted delay time.
// Experimentally setup with an Oscilloscope.
}

void LCD_PutCmd (char Cmd) {
LCD_CONTROL_OUT &= ~(1<<LCD_RS);
LCD_BusyWait();
LCD_DATA_OUT = Cmd;
asm ("nop");
LCD_CONTROL_OUT |= (1<<LCD_E);
asm ("nop"); // PWeh must be 230nS minimum
asm ("nop"); // nop = 67nS @ 14.7456MHz
asm ("nop");
asm ("nop"); // Here, E = 271nS @ 14.7456MHz
LCD_CONTROL_OUT &= ~(1<<LCD_E);
asm ("nop");
LCD_CONTROL_OUT |= (1<<LCD_RS);
}

void LCD_PutChar (char c) {
LCD_CONTROL_OUT &= ~(1<<LCD_RS);
LCD_BusyWait();
LCD_CONTROL_OUT |= (1<<LCD_RS);
LCD_DATA_OUT = c;
asm ("nop");
LCD_CONTROL_OUT |= (1<<LCD_E);
asm ("nop"); // PWeh must be 230nS minimum
asm ("nop"); // nop = 67nS @ 14.7456MHz
asm ("nop");
asm ("nop"); // Here, E = 271nS @ 14.7456MHz
LCD_CONTROL_OUT &= ~(1<<LCD_E);
}

char LCD_BusyWait (void) {
unsigned char LCDStatus;
LCD_DATA_DDR = 0x00; // Set LCD data port to inputs
LCD_CONTROL_OUT |= (1<<LCD_RW);
asm ("nop");
do {
LCD_CONTROL_OUT |= (1<<LCD_E);
asm ("nop"); // PWeh must be 230nS minimum
asm ("nop"); // nop = 67nS @ 14.7456MHz
asm ("nop");
asm ("nop"); // Here, E = 271nS @ 14.7456MHz
LCDStatus = LCD_DATA_IN;
LCD_CONTROL_OUT &= ~(1<<LCD_E);
} while ((LCDStatus & (1<<LCD_BUSY)) == (1<<LCD_BUSY));
LCD_CONTROL_OUT &= ~(1<<LCD_RW);
LCD_DATA_DDR |= 0xFF; // Set LCD data port to outputs
return (LCDStatus);
}

void IO_INIT (void) {
LCD_Delay (60000); // Wait for the LCD display to boot up
// Set J_2:J_1 PULL-UPS active
LCD_CONTROL_OUT = (1<<J_2) | (1<<J_1);
// Set LCD_control J_2:J_1 to inputs
LCD_CONTROL_DDR = 0xF2;
LCD_CONTROL_OUT |= (1<<LCD_RS); // Set LCD_RS HIGH
// Delay resolution ~ 1uS @ 14.7456MHz
LCD_Delay (15000); // Need 15mS delay for LCD to power up

// Initialize the AVR controller I/O
LCD_DATA_DDR = 0xFF; // Set LCD_DATA_OUT as all outputs
LCD_DATA_OUT = 0x00; // Set LCD_DATA_OUT to logic low
}

void LCD_INIT (void) {
// Initialize the LCD controller
LCD_PutCmd (LINE_8x4); // Set 8 bit data, 4 display lines
LCD_PutCmd (CLR_DSP); // Power up the display
LCD_PutCmd (PWR_ON); // Power up the display
LCD_Delay (30000);
LCD_BusyWait();
}

int main (void) {
// Initialize the Mega16 I/O
IO_INIT ();
// Initialize the HD44780 LCD controller
LCD_INIT ();
LCD_PutChar(' ');
LCD_PutChar(' ');
LCD_PutChar(' ');
LCD_PutChar('A');
LCD_PutChar('V');
LCD_PutChar('R');
LCD_PutChar(' ');
LCD_PutChar('F');
LCD_PutChar('R');
LCD_PutChar('E');
LCD_PutChar('A');
LCD_PutChar('K');
LCD_PutChar('S');
LCD_PutChar(' ');
LCD_PutChar(' ');
LCD_PutChar(' ');

while (1) {

}
}

original link: http://www.avrfreaks.net/index.php?name=PN...pic&t=57816
(inregistrare instantanee, si pentru cei care nu stiu... merita!)

Codul este destinat Atmega16 14.7456MHz, dar eu am folosit Atmega32 cu oscilator de 16Mhz si merge.
In codul de mai sus am facut o mica modificare. Am schimbat fata de shema de la linkul de mai sus portA in loc de portB pentru a se potrivi cu schema mea, RS,E,RV se pare ca au fost alese de autorul codului pe aceiasi pini ca si mine laugh.gif deci nu a mai fost nevoie de modificare.
Functioneaza perfect.

Am observat ca si omul de aici http://www.avrfreaks.net/index.php?name=PN...hlight=lcd+16x2 a avut aceeasi problema ca si mine dar pare-se ca nu a reusit nici cu codul de mai sus :| Ciudat!

Cat despre prima varianta de cod, sunt sigur ca logica e buna(am mai modificat codul pe ici pe colo de la varianta initiala dar nimic!), numai ca, probabil ca delayul acela nu era destul de mare pt 16Mhz.. si.. cel mai probabil trebuia un delay mai mare intre LatchEnable si UnlatchEnable... Cert este ca nu am mai incercat sa mai modific acel cod. Voi sta sa-l depanez alta data.

Sper sa va fie folositor si altora codul de mai sus.

Inca ceva, pentru cei care incep sa invete despre LCD-uri , am atasat inca 2 pdf-uri pe care le gasesc foarte folositoare.

It did the trick for me, hope it does the trick for you too.

Daca mai dau de probleme revin, deocamdata sunt pe drumul cel bun. laugh.gif

Numai bine.

PS. Simularea in isis NU merge! thumbdown.gif
ilya
ai spus că ai rezolvat. merge? sau nu?
ultima soluție ar fi să îți faci tu protocoalele tale, cum am spus inițial, și să experimentezi cu comutatoare hexadice, ca în pdfurile care le-ai atașat. eu așa am început, și am avut o tonă de alte probleme (mi se încingea sursa, mureau picele, etc..)
lupu1001
QUOTE (ilya @ Jan 4 2008, 11:25) *
ai spus că ai rezolvat. merge? sau nu?
ultima soluție ar fi să îți faci tu protocoalele tale, cum am spus inițial, și să experimentezi cu comutatoare hexadice, ca în pdfurile care le-ai atașat. eu așa am început, și am avut o tonă de alte probleme (mi se încingea sursa, mureau picele, etc..)


Da , asa cum am scris si in postul de mai sus, MERGE!
Nu am avut alte probleme iar mersul l-am inteles din prima, doar ca nu mi-am explicat de ce nu mergea happy.gif
Anyway, acum pot folosi lcd-ul in liniste smile.gif.
Ajunsesem pana la urma cu codul meu initial la acelasi layout pe care-l descrie si noul cod, numai ca foloseam nu delay chior (care cred ca lasa mult de dorit) si nu lasam Enable sa stea high destul timp (cred ca astea erau cauzele nefunctionarii).
Reclama
In curand... autoevolution.ro

Teste, stiri, ghiduri, jurnale, forum si multe altele!
Aceasta este o versiune simplificată a paginii originale. Pentru a vizita versiunea originala click aici.