Lcdohjelmointi

LCD ohjelmoinnista

Pekka Ritamäki 21.10.2008

lcdblue.jpg

Miksi valmiit LCD-ohjelmat eivät toimi?

Ne toimivat, jos osaat laittaa omat parametrisi kuntoon. Alkuperäisen ohjelman tekijä ei tiedä mitä prosessoria käytät, ja mitä nastoja käytät.

Esimerkki CCS/PIC -ohjelmoinnista PIC16/18-sarjalle
Muilla kääntäjillä on ihan samat asiat vain välimerkit muutuvat kielen mukaan

1 Tiedot kääntäjälle, mitä piiriä käännetään ja mikä on kellotajuus
- prosesossorin alustus
Tyyppi
Sulakkeet
oskillaattorityypin valinta
suojaukset
watchdogit

- viive alustus, watchdog viiveen aikana

2. LCD nastojen määritys

3. prosessorin suuntarekisterien alustus

4.
-LCD näytönohjaimen alustuksen suunnittelu
- 8/4-bitin ohjausmenetelmän valinta
-Erittäin tärkeätä on 4-bitin modessa, että LCD:llä on tarpeeksi viiveitä, muuten laite menee 8-bitin modeen ja ei toimi 4-bitin komenoilla
- Valitaan mode, fontit, LCD näyttö päälle/pois, kursorin suunta, näkyykö kursori vai ei
kaikki nämä on kerrottu japanialaisella tyylillä LCD-datalehdissä. Niistä ei aloittelija saa mitään selvää.

5. LCD ohjaimen funktiot
* kirjoita nibble
* kirjoita merkki
* kirjoita ohjauskomento LCD:lle
* Kirjoita merkkijono LCD:lle
* Kirjota merkkijono riville x

6. printf-funtio lcd:lle
Käytä LCD kuten printf-funktiota.

7 . Logo LCD:lle

=== Sitten varsinainen koodi ===

Esimerkissä käytetään PIC18F252 ja LCD 4*20 WH2004-TMC = Winstar sininen===

1 Prosessorin sulakevalinnat otetään käyttöön tästä taulukosta
/*=========fuses ===========================
PUT Power Up Timer
PROTECT Code protected from reads
NOPROTECT Code not protected from reading
BROWNOUT Reset when brownout detected
NOBROWNOUT No brownout reset
NOMCLR Master Clear pin used for I/O
MCLR Master Clear pin enabled
NOLVP No low voltage programming, B3(PIC16) or B5(PIC18) used for I/O
LVP Low Voltage Programming on B3(PIC16) or B5(PIC18)
INTRC Internal RC Osc
EC_IO External clock
INTRC_IO Internal RC Osc, no CLKOUT
EC External clock with CLKOUT
NOCPD No EE protection
CPD Data EEPROM Code Protected
==========================================*/

// Prosessorin tyypin valinta
#include <18F252.h>
// sulakkeet
#fuses NOWDT,HS, PUT, BROWNOUT, NOCPD, NOLVP, CCP2C1

// kello-oskillaattororin valinta 10MHz javahtikoira päälle
#use delay(clock=10000000,RESTART_WDT)

//BYTE PORTIT
#BYTE T0CON = 0xFB5
#BYTE PORTA = 0x0F80
#BYTE PORTB = 0x0F81
#BYTE PORTC = 0x0F82
#BYTE TRISB =

2 LCD bittien määrittely B-porttiin
//BIT portit
#BIT RS =PORTB.5

#BIT ENABLE =PORTB.4

#BYTE LCD = PORTB // LCD on mapattu osoitteeseen 0xF81 eli B-porttiin

struct lcd_pin_map { // Tämä structuuri on B-portille
int8 data : 4 ; // 4 bittiä alusta B3..B6
unsigned int1 RS ; // RS bitti
unsigned int1 ENABLE; // ENABLE bitti
unsigned int1 spare1; // WRITE on kytetty pysyyvästi 0 V
unsigned int1 spare2; // ei käyttöä
} LCD;

// käyttö ->LCD.ENABLE=1;

3 Suuntarekisterit kaikki LCD nastat annoksi

TRISB=0b11000000;

4. LCD asetetaan toimimaan 4-bittisessä modessa

===

Tässä on esimerkki PIC16F18857 tehdystä piiristä.

Tässä uusessa PIC:ssä on 56k Flash koodimuisti, 4kRAM, 256 eeprom, 3 (8bit)+4 (16 bit) ajastinta, ei tarvita kidettä+32MHz sisäinen oskillaattori, DAC-muunnin, ADC muuntimia ja monia muita uusia ominaisuuksia

RinnakkaisLCD.jpg

// Tämä on rinnakkais LCD:n testausohjelma
// PEKKA Ritamäki
// 13.6.2022

#include <16F18857.h> // valitse oikea PIC piiri
#FUSES NOWDT // Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT //Code not protected from reading
#FUSES IESO Internal External Switch Over mode enabled
#FUSES NOBROWNOUT //No reset when brownout detected
#FUSES NOPUT //No power Up Timer
#FUSES NOCPD //No EE protection
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOFCMEN //Fail-safe clock monitor enabled
#FUSES NOIESO Internal External switch over mode disabled
#FUSES NOMCLR //Master Clear pin not enabled
#FUSES BORV21 //tämä pitää olla 3.3V:lla BORV21 (=2.1V) muuten ei toimi. Tässä 5V piirissä ei tarvita
// Muuten Brown Out Reset on BORV40(= 4.0V)!!! 4.5V paristo menee menee alle 4V:n!

#device ADC=10 *=16 // valitaan tarkin ADC-muunnin+ 16bitin Ram

#use delay(internal=32MHz,restart_wdt)
#pin_select U1TX = PIN_C6 // ota käyttöön normaalit TX sarjaliikenteelle
#pin_select U1RX = PIN_C7 // ota käyttöön normaalit RX sarjaliikenteelle

#pin_select SCL1OUT=PIN_C3
#pin_select SDA1OUT=PIN_C4
#use FIXED_IO( A_outputs=PIN_A0 )
#use FIXED_IO(B_outputs=PIN_B0, PIN_B1,PIN_B2,PIN_B3, PIN_B4, PIN_B5,PIN_B6,PIN_B7)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8 ,errors )
// portin IO-nastojen osoitteet
#BYTE PORTB = 6
#BYTE PORTA = 5
#BYTE PORTC= 7
#BYTE TRISA =0x85
#BYTE TRISB =0x86
#byte TXTA = 0x98
#BYTE RCSTA = 0x18
#BIT SPEN = RCSTA.7
#BYTE OPTION_REG = 0x81
#BIT PULLUPSBIT = OPTION_REG.7
#include "lcd1.c" // täällä on varsinaisnen LCD ohjausohjelma

// vilauta lediä 100 ms
void led()
{
output_a(0x1);
delay_ms(100);
output_a(0 );
}
// pääohjelma alkaa
void main()
{

setup_adc_ports(NO_ANALOGS);
set_tris_a(0); // leiä varten suuntärekisteri =0 eli antonasta
output_a(0xF); // laitan neljä alintä bittiä päälle
printf("\rProbyte 3 LCD test %s",DATE);
led() ;
printf( "\rProbyte LCD test %s",DATE);
delay_ms(1000);
lcd_init();
while(1) // jatkuva syöttö
{
led() ; // vilautaä lEDiä A.0
lcd_gotoxy(ROW1);
printf(lcd_putc,"Rivi1" );
lcd_gotoxy(ROW2);
printf(lcd_putc,"Rivi2" );
lcd_gotoxy(ROW3);
printf(lcd_putc,"Rivi3" );
lcd_gotoxy(ROW4);
printf(lcd_putc,"Rivi4" );
delay_ms(1000);
}
}


lcd1.c
// RinnakkaisLCD:n driveri esim. L2034 4*20 merkkiä varten
// LCD on kytketään 4 bitin moodiim
// B.4 -B.7 on data D0 -D3
// enable = B.3
// r/W =B.2= 0V
// RS = B.1
// aluksi LCD_init, sitten esim printf(lcd_putc,"Rivi4" );
// Pekka Ritamäki
#BIT DB3 = PORTB.7
#BIT DB2 = PORTB.6
#BIT DB1 = PORTB.5
#BIT DB0 = PORTB.4
#BIT RS = PORTB.1
#BIT R_W = PORTB.2
#BIT ENABLE = PORTB.3 // LCD enable
#define CMD 0 // komento moodi
#define DAT 1 // data moodi
#define LCD4MODE 3 // tämä laittaa 4-bittiseen moodiin
#define LCD_16_1 1 // 1*16 LCD mode 1 rivinen LCD
#define LCD_CLEAR 1
#define LCD_HOME 2
#define LCD_ENTRY_MODE 6
#define LCD_BACK 0x10
#define ROW1 0x80 // gotoxy (1, 1)*/
#define ROW2 0xC0 // 2*16 40 +80 */
#define ROW3 0x94 // gotoxy (1, 3)
#define ROW4 0xd4 // gotoxy (1, 4)
#define CURSOROFF 0x0C // Display on, cursor off 2, blink off send_bytes(CMD, CURSOROFF );
#define CURSORON 0x0D // Display on, cursor ON , blink off send_bytes(CMD, CURSORON );
#define LCD_CURSOR_ON 0xF // LCD kursoria päälle, käytä komentomodea esim send_bytes(CMD, LCD_CURSOR_ON);
#define LCD_CURSOR_OFF 0xD // LCD kursoria poispäältä, käytä komentomodea esim send_bytes(CMD, LCD_CURSOR_OFF);
#define LCD_CURSOR_RIGHT 0x14 // LCD siirrä kursoria oikealle, käytä komentomodea esim send_bytes(CMD, LCD_CURSOR_OFF);
#define CursorBack 16
// siirrä LCD kursoria taaksepäin, käytä komentomodea esim send_bytes(CMD, CursorBack);
#define CursorFwd 20 // liikutä kursoriä eteenäpäin send_bytes(CMD, CursorFwd );
void lcd_send_byte( byte address, byte n ) ;

int blink_cursor;
// tämän funktio käyttää esim enable lcd.enable =1
struct lcd_pin_map { // Tämä structuuri on B-portille

int data : 4; // 4 bittiä ylinnä B5..B7
int enable; // ENABLE on RB.3
int RW; // RW= B2
int RS; // RS=B.1
int spare; // ei käytössä
} lcd;

#byte lcd = 6 // LCD on mapattu ositteeseen 6 eli B-porttiin

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 riviä
#define lcd_line_two 0x40 // LCD RAM:in osoite toiselle riville vain eräillä LCD:llä

byte CONST LCD_INIT_STRING[4] = {0x20 | (lcd_type « 2), 0xc, 1, 6};
// Nämä bytet pitää lähettää käynnistyksessä LCD
// Seuraavia käytetän IO-portin suunnissa
// asettamaan I/O portin suuntarekisteriä

STRUCT lcd_pin_map const LCD_WRITE = {0,0,0,0,0};
Kirjoita tilassa ( LCD), kaikki io-nastat asetetaan Outputeiksi
//STRUCT lcd_pin_map const LCD_READ = {15,0,0,0,0};

void lcd_send_nibble(int8 nibble)
{

if ( nibble &1)
output_high(PIN_B4);
else
output_low(PIN_B4);
if ( nibble &2)
output_high(PIN_B5);
else
output_low(PIN_B5);
if ( nibble &4)
output_high(PIN_B6);
else
output_low(PIN_B6);
if ( nibble &8)
output_high(PIN_B7);
else
output_low(PIN_B7);

delay_us(1);
// enable=1;
output_high(PIN_B3); // Enable=1
delay_us(10);
printf("\rNibb =%x", nibble);

output_LOW( PIN_b3);// Enable=0
delay_us(10);

}
/*
void lcd_send_nibble( byte n ) {
lcd.data = n;
delay_cycles(1);
ENABLE= 1;
delay_us(6);
ENABLE= 0;
}
*/

void lcd_send_byte( byte address, byte n ) {
RS = 0;
delay_ms(1); // pieni viive koska lcd:tä ei lueta takaisin

if (address)
output_high(PIN_B1); // komentomode =1
else
output_low(PIN_B1); // komentomode =0 eli datamode
printf("\rRS =%x", address);
delay_cycles(1);
delay_cycles(1);
output_low(PIN_B3); // ENABLE=0;
printf("\rBYte =%x", n);
lcd_send_nibble(n » 4); // siirrä data4 bittiä oikealle
lcd_send_nibble(n & 0xf); // ota vain 4 alinta bittiä

}

// alusta lcd 4-bittiseen modeen
void lcd_init(void) {
set_tris_b(0);
byte i;
R_W= 0; // R_W on koko ajan nollissa
RS = 0; // aluksi komemtomoodi päälle

ENABLE=0;
output_low(PIN_B3); // enamble pois
delay_ms(15);
pieni viive
for(i=1;i<=3;++i) {
lcd_send_nibble(LCD4MODE); // 4-bit mode =3
delay_ms(5);
}
lcd_send_nibble(2); // alusta LCD
for(i=0;i<=3;++i)
lcd_send_byte(CMD,LCD_INIT_STRING[i]);
blink_cursor = LCD_CURSOR_ON;
lcd_send_byte(CMD, blink_cursor); /* kursori päälle ja eteenpäin */
}

// Ei tarvitse tätä käyttää
void lcd_gotoxyl( byte x, byte y) { // laita LCD paikkaan c ja riville y
byte address;

if(y!=1)
address=lcd_line_two; #define lcd_line_two 0x40
else
address=0;
address+=x-1;
lcd_send_byte(0,0x80|address);
}
#define ROW1 0x80 /* gotoxy (1, 1)*/
#define ROW2 0xC0 /* 2*16 40 +80 */
#define ROW3 0x94 /* gotoxy (1, 3) */
#define ROW4 0xd4 /* gotoxy (1, 4) */
mene riville 1,2,3 tai 4
void lcd_gotoxy( byte x) { // goto ROW1, ROW2,ROW3 tai ROW4
lcd_send_byte(CMD,x);
}
/*
KIRJOITA yksi merkki LCD:lle
***/
char lcd_putc( char c) {
switch (c) {
// case '\f' : lcd_send_byte(0,1);

case '\n' : lcd_gotoxy(2); break; // contrl/ J = enter riville 2
case '\b' : lcd_send_byte(0,0x10); break; //mode =0 komento 10 0backstep
default : lcd_send_byte(1,c); break; // mode=1, data
}
return c;
}

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License