Funkcje obsługi wyświetlacza LCD 2-wierszowego 24-znakowego (2 x 24), z interfejsem 4-bitowym

    -- Sebastian Pawlak, 2003, 2004.


Przedstawiam tu moją bibliotekę (wersja poprawiona) obsługującą standardowy wyświetlacz LCD. Zamieściłem także kod krótkiego programu wykorzystującego bibliotekę do wyświetlania kolejnych liczb na wyświetlaczu. Program łatwo skompilować za pomocą makefile`a zamieszczonego na mojej stronie.



Kod źródłowy pliku "lcd.h":

/* Obsluga wyswietlacza LCD z interfejsem 4-bitowym, dla
 * procesora Atmel AVR.
 * LCD: 2 x 24 znaki
 * Sebastian Pawlak, 2003, 2004 r.
 */

#ifndef _LCD_H_
#define _LCD_H_


#define PORT_LCD PORTC
#define PORT_LCD_DDR DDRC
#define ENABLE PC1
#define RS PC0
#define P4 PC2       /* P4, P5, P6, P7 musza stanowic kolejne piny portu */
#define P5 PC3
#define P6 PC4
#define P7 PC5

#define MASK  ((1 << ENABLE) | (1 << RS) | (1 << P4) | (1 << P5) |\
(1 << P6) | (1 << P7))

#define MASK2 ((1 << P4) | (1 << P5) | (1 << P6) | (1 << P7))

/* Entry mode set */
#define CURSOR_DIRECTION (1 << P5)
#define DISPLAY_SHIFT (1 << P4)

/* Display On/Off control */
#define DISPLAY_ON (1 << P6)
#define CURSOR_ON (1 << P5)
#define CURSOR_BLINK (1 << P4)

/* Cursor/display shift */
#define CURMOVE_DISPSHIFT (1 << P7)
#define SHIFT_DIRECTION (1 << P6)

#define F_CPU 11000000       /* czestotliwosc procesora */

#define K_DELAY_100us F_CPU/61349
#define K_DELAY_1ms F_CPU/6013
#define K_DELAY_10ms F_CPU/600


void Delay_100us(unsigned char t);
void Delay_1ms(unsigned char t);
void Delay_10ms(unsigned char t);
void enable(void);
void clearDisplay(void);
void cursorHome(void);
void entryMode(unsigned char flags);
void displayControl(unsigned char flags);
void curdispShift(unsigned char flags);
void blinkCursor(void);
void stopBlinkCursor(void);
void setCursorPos(unsigned char x);
void initLCD(void);
void showChar(unsigned char z);
void showString(const unsigned char *s);

#endif

Kod źródłowy pliku "lcd.c":

/* Obsluga wyswietlacza LCD z interfejsem 4-bitowym, dla
 * procesora Atmel AVR
 * LCD: 2 x 24 znaki
 * Sebastian Pawlak, 2003, 2004 r.
 */

#include <avr/io.h>
#include "lcd.h"

int charNo;


/* Wait for a specific time in 100 uSec
 * (15 + t*( ((K_DELAY_100us-1)*6)+5 ))
 * Funkcja zapozyczona
 */
void Delay_100us(unsigned char t) {
    unsigned int i;

    if (t == 0)
        return;

    while (t--)
        for (i = 0; i < K_DELAY_100us; i++)
            ;
}


/* Wait for a specific time in 1 mSec
 * (15 + t*( ((K_DELAY_1ms-1)*6)+5 ))
 */
void Delay_1ms(unsigned char t) {
    unsigned int i;

    if (t == 0)
        return;

    while (t--)
        for (i = 0; i < K_DELAY_1ms; i++)
            ;
}


/* Wait for a specific time in 10 mSec
 * (15 + t*( ((K_DELAY_10ms-1)*6)+5 ))
 */
void Delay_10ms(unsigned char t) {
    unsigned int i;

    if (t == 0)
        return;

    while (t--)
        for (i = 0; i < K_DELAY_10ms; i++)
            ;
}


/* enable: funkcja strobujaca
 */
void enable(void)
{
    sbi(PORT_LCD, ENABLE);
    cbi(PORT_LCD, ENABLE);
    Delay_100us(4);
}


/* clearDisplay: czyszczenie wyswietlacza
 */
void clearDisplay(void)
{
    PORT_LCD &= ~MASK;
    enable();

    PORT_LCD &= ~MASK;
    sbi(PORT_LCD, P4);
    enable();
    Delay_10ms(20);

    charNo = 0;
}


/* cursorHome: kursor na pozycje zero
 */
void cursorHome(void)
{
    PORT_LCD &= ~MASK;
    enable();

    PORT_LCD &= ~MASK;
    sbi(PORT_LCD, P5);
    enable();
    Delay_10ms(5);

    charNo = 0;
}


/* entryMode: wybor trybu pracy LCD
 */
void entryMode(unsigned char flags)
{
    PORT_LCD &= ~MASK;
    enable();

    PORT_LCD &= ~MASK;
    PORT_LCD |= (flags & MASK2);
    sbi(PORT_LCD, P6);
    cbi(PORT_LCD, P7);
    enable();
}


/* displayControl: sterowanie LCD
 */
void displayControl(unsigned char flags)
{
    PORT_LCD &= ~MASK;
    enable();

    PORT_LCD &= ~MASK;
    PORT_LCD |= (flags & MASK2);
    sbi(PORT_LCD, P7);
    enable();
}


/* curdispShift: sposob zachowania kursora
 */
void curdispShift(unsigned char flags)
{
    PORT_LCD &= ~MASK;
    sbi(PORT_LCD, P4);
    enable();

    PORT_LCD &= ~MASK;
    PORT_LCD |= (flags & MASK2);
    enable();
}


/* blinkCursor: wlaczenie migania kursora
 */
void blinkCursor(void)
{
    PORT_LCD &= ~MASK;
    enable();

    PORT_LCD &= ~MASK;
    sbi(PORT_LCD, P7);
    sbi(PORT_LCD, P6);
    sbi(PORT_LCD, P5);
    sbi(PORT_LCD, P4);
    enable();
}


/* stopBlinkCursor: wylaczenie migania kursora
 */
void stopBlinkCursor(void)
{
    PORT_LCD &= ~MASK;
    enable();

    PORT_LCD &= ~MASK;
    sbi(PORT_LCD, P7);
    sbi(PORT_LCD, P6);
    enable();
}


/* setCursorPos: ustawienie pozycji kursora
 */
void setCursorPos(unsigned char x)
{
    charNo = x;

    if (x >= 24)
        x = 0x40 + x - 24;

    PORT_LCD &= ~MASK;
    PORT_LCD |= (((x & 0xf0) >> 4) <<  P4);
    sbi(PORT_LCD, P7);

    enable();
    PORT_LCD &= ~MASK;
    PORT_LCD |= ((x & 0x0f) << P4);
    enable();
    Delay_10ms(15);
}


/* initLCD: inicjalizacja LCD
 */
void initLCD(void)
{
    /* PORT_LCD jako wyjscie */
   PORT_LCD_DDR = 0xff;

    Delay_10ms(15);

    /* 3 x RESET */
    PORT_LCD &= ~MASK;
    sbi(PORT_LCD, P4);
    sbi(PORT_LCD, P5);
    enable();    Delay_10ms(15);
    enable();    Delay_10ms(15);
    enable();    Delay_10ms(15);


    /* tryb 4-bitowy */
    PORT_LCD &= ~MASK;
    sbi(PORT_LCD, P5);
    enable();

    /* ustawienia w trybie 4-bitowym */
    PORT_LCD &= ~MASK;
    sbi(PORT_LCD, P5);
    enable();

    PORT_LCD &= ~MASK;
    sbi(PORT_LCD, P7);
    enable();

    entryMode(CURSOR_DIRECTION /*| DISPLAY_SHIFT*/);

    curdispShift(CURMOVE_DISPSHIFT | SHIFT_DIRECTION);

    /* kursor */
    displayControl(DISPLAY_ON /*| CURSOR_ON | CURSOR_BLINK*/);

    /* czyszczenie ekranu */
    clearDisplay();
}


/* showChar: wypisanie znaku na LCD
 */
void showChar(unsigned char z)
{
    PORT_LCD &= ~MASK;
    PORT_LCD |= ((z & 0xf0) >> 4) << P4;
    sbi(PORT_LCD, RS);
    enable();

    PORT_LCD &= ~MASK;
    PORT_LCD |= (z & 0xf) << P4;
    sbi(PORT_LCD, RS);
    enable();

    charNo++;
}


/* showString: wypisanie napisu na LCD
 */
void showString(const unsigned char *s)
{
    for ( ; *s; s++)
        showChar(*s);
}

Kod źródłowy pliku "testlcd.c":

/* Program ilustruje dzialanie biblioteki obslugujacej
 * wyswietacz LCD.
 * Sebastian Pawlak, 2003 r.
 */

/*#define __AVR_AT90S8535__*/
#include <stdio.h>
#include "lcd.h"

int main(void)
{
    char s[16];
    long int i;

    initLCD();

    for (i = 0; ; i++) {
        cursorHome();
        sprintf(s, "%ld ", i);
        showString(s);
    }

    return 0;
}
w3cw3c
automatyka przemysłowa