Op de site van Pros vond ik een interessante 3-draads LCD interface.
Ik heb Pros z'n voorbeeldcode schaamteloos overgenomen en geprobeert om deze uit te breiden tot een werkend geheel.
Mijn code werkt, ik kan alle stuurcommando's sturen (1e lijn, 2e lijn, clear, blink on/off...), maar letters komen niet juist aan.

Ik gebruik onderstaande code. In comments staat achter elk lcd_putchar commando welke letter er getoond wordt op het LCD als dat commando uitgevoerd wordt.


#define COM           0
#define LCD_PORT      PORTB
#define LCD_DDR       DDRB
#define LCD_DATA_PIN  PB1
#define LCD_CLK_PIN   PB2
#define LCD_E_PIN     PB0
#define TXT           1

#define lcd_delay(x) _delay_loop_1(x)
#define lcd_command(x) char2LCD3(x, COM)
#define lcd_putchar(x) char2LCD3(x, TXT)

#define F_CPU 9600000UL

#include <avr/io.h>  
#include <util/delay.h>

int main(void) {
	DDRB |= 0x0F;
	//3 keer 0x30 sturen om lcd te starten
	_delay_ms(20);
	lcd_command(0x30);
	_delay_ms(5);
	lcd_command(0x30);
	_delay_us(160);
	lcd_command(0x30);
	_delay_us(160);

	lcd_command(0x38); //2line 8bit 5x7-dot
	lcd_command(0x08); //disp off
	lcd_command(0x01); //clear
	_delay_ms(2);
	lcd_command(0x06); //entry mode: increment, no shift
	lcd_command(0x0C); //disp on
	lcd_command(0x02); //cursor home
	lcd_command(0x0F); //cursor blink	

	_delay_ms(1);
	//Tekst tonen op LCD:
	lcd_putchar("a"); //"`"
	lcd_putchar("b"); //"b"
	lcd_putchar("c"); //"d"
	lcd_putchar("d"); //"f"
	lcd_putchar("e"); //"h"

	lcd_command(0xC0); //2e lijn
	lcd_putchar("A"); //"j"
	lcd_putchar("B"); //"l"
	lcd_putchar("C"); //"n"
	lcd_putchar("D"); //"p"
	lcd_putchar("E"); //"r"

	while(1){
		//knipperend ledje
		LCD_PORT |= 0x08;
		_delay_ms(100);
		LCD_PORT &= 0xF7;
		_delay_ms(100);
	}

}

//Functie van Pros:
void char2LCD3(unsigned char karakter, unsigned char RS)
{
    unsigned char cnt;

    for (cnt = 0; cnt < 8; cnt++) {
        if ((karakter & 0x80) == 0x80) {                        // een '1'
            LCD_PORT |= (1 << LCD_DATA_PIN);                    // LCD_DATA_PIN hoog
        } else {                                                // een '0'
            LCD_PORT &= ~(1 << LCD_DATA_PIN);                   // LCD_DATA_PIN laag
        }
        lcd_delay(5);
        LCD_PORT |= (1 << LCD_CLK_PIN);                         // Seriele klok hoog
        lcd_delay(5);
        LCD_PORT &= ~(1 << LCD_CLK_PIN);                        // Seriele klok terug laag
        karakter = karakter << 1;                               // Bits een plaatsje naar rechts schuiven
    }
    if (RS == TXT) {
        LCD_PORT |= (1 << LCD_DATA_PIN);                        // Tekst, RS moet hoog
    } else {
        LCD_PORT &= ~(1 << LCD_DATA_PIN);                       // Instructie, RS moet laag
    }
    lcd_delay(5);
    LCD_PORT |= (1 << LCD_E_PIN);                               // schuifregister -> par. uitgang
    lcd_delay(20);
    LCD_PORT &= ~(1 << LCD_E_PIN);                              // par. uitgang -> LCD-module

	//extra wachttijd:
	_delay_us(50);
}

Ik gebruik een Attiny13 microcontroller op 9.6MHz. Clock is verbonden met PB2, Data met PB1 en Latch met PB0.
Net alsof er geschoven wordt met de letters door het alfabet, maar er worden letters overgeslagen...?

Wie ziet wat ik fout doe?

Alvast bedankt,

Stijn

Edit:
Verder prutsen toont aan dat er geen verband is tussen opgegeven karakters en wat er op het scherm komt. Enkel de hoeveelheid tekens komt overeen.
Ik heb volgende code:


	lcd_putchar("0");
	lcd_putchar("1");
	lcd_putchar("2");
	lcd_putchar("3");
	lcd_putchar("4");
	lcd_putchar("5");
	lcd_putchar("6");
	lcd_putchar("7");

Maar op het scherm komt "`bdfhjln"???

Je moet het verschil tussen een "character" en een "string" weten...

Een karakter staat tussen quotes. Er is weinig verschil in C tussen 'A' en 65.

De functie "lcdputchar" zal wel met een karakterteken moeten worden aangeroepen. dus: lcdputchar (65); of lcdputchar ('A');

Als je een string wilt in C, moet het tussen dubbele aanhalingstekens zetten. De string HELLO komt als 48 45 4c 4c 4f 00 in opeenvolgende locaties. Maar de string "A" mag ook: 41 00 . Nu wordt niet het hele stringgebied als argument aan een functie doorgegeven, maar alleen een pointer.
Dus als op adres 0x30 je string "A" komt te staan, dus op 0x30 de "A" 41, en op 0x31 de 00, en je roept lcdputchar ("A") aan, dan krijg je het cijfer '0' op je scherm omdat lcdputchar de laagste 8 bits als te printen karakter opvat.....

P.S. (Haha! het is mooi te zien dat iedere volgende regel de 2-byte string precies 2 bytes verder in het geheugen gezet is! )
P.P.S. Zowel in je eerste posting als in de edit!

*Slaat zichzelf tegen de kop*

Inderdaad, als ik de dubbele quotes vervang door enkele dan werkt het wel. Had ik maar beter opgelet in de les C... |:(
Bedankt!

Op 10 december 2010 17:11:28 schreef pros:
Je zou ook kunnen letten op de warnings van de compiler. Die waarschuwt je, als je zulke foutjes maakt.

Inderdaad... Net even gecontroleerd:
../3wireLCD.c:67: warning: passing argument 1 of 'char2LCD3' makes integer from pointer without a cast

[Bericht gewijzigd door Stijn S op (52%)]

Je zou ook kunnen letten op de warnings van de compiler. Die waarschuwt je, als je zulke foutjes maakt.