Einrichtung und Programmierung des Nokia LCD (6125).
Hier ist eine einfache Schaltung und ein Code für den Nokia LCD-Treiber, die mit dem PCF8833-Treiber für alte Nokia LCDs (winzige LCDs) wie 1208, 1600, 2126, 2310, 6100, 6125 und N71 kompatibel sind.
Die Schaltung und der Code in diesem Projekt sind mit dem LCD-Treiber PCF8833 STN RGB – 1321323 kompatibel.
Dieser LCD-Treiber wurde für einige kleine Nokia-LCDs wie 1208, 1209, 1600, 2126, 2310, 6100 und 6125, 6136 sowie das N71-Rückseiten-LCD verwendet.
Das LCD, an dem ich gearbeitet habe, ist ein 98*70-Pixel-LCD, das ich aus einem zerstörten Nokia 6125 entfernt habe.
Dieses LCD benötigt einen Board-to-Board-Anschluss, den ich von der Nokia-Platine entfernt habe. Die Transaktionsleitung für mein LCD ist ein 9-Bit-SPI, das keine Übertragungsleitung hat und nur die Daten oder Befehle vom Host empfängt.
Der Host (Controller, Treiber usw.), den ich verwendet habe, ist ein ATMega8A-Mikrocontroller.
ATMega8A verfügt über eine 8-Bit-SPI-Funktion, keine 9-Bit-Funktion, daher habe ich die I/Os direkt anstelle des internen SPI-Moduls verwendet.
Die Nokia LCD-Treiber schaltung
Hier ist meine Schaltung auf einem Steckbrett:
Der Schaltplan
Hier ist die Pinbelegung meines LCD:
- CLK
- Daten
- Masse (GND)
- CS#
- RESET#
- Hintergrundbeleuchtung LED+, 7,5 V
- Hintergrundbeleuchtung LED-, GND
- NC
- VddAN, 2,8 V… 3,3 V
- VddIO, 1,8 V… 3,3 V
Hier ist der Schaltplan:
Transaktionsprotokoll
Wenn der Reset#-Pin niedrig ist, bedeutet das, dass sich das LCD im Reset-Zustand befindet und den Befehl und die Daten nicht akzeptiert.
Wenn CS# niedrig ist, akzeptiert das LCD die Befehle/Daten.
Hier ist das Befehlsprotokoll in 9-Bit-SPI:
__ __ __ __ __ __ __ __ __
CLK ___|C1|_|C2|_|C3|_|C4|_|C5|_|C6|_|C7|_|C8|_|C9|____...
Daten_______<b7 ><b6 ><b5 ><b4 ><b3 ><b2 ><b1 ><b0 > ...
_ __
CS# |______________________________________________| ...
Hier ist das Datenprotokoll in 9-Bit-SPI:
__ __ __ __ __ __ __ __ __
CLK ___|C1|_|C2|_|C3|_|C4|_|C5|_|C6|_|C7|_|C8|_|C9|____...
___
Daten_| |_<b7 ><b6 ><b5 ><b4 ><b3 ><b2 ><b1 ><b0 > ...
_ __
CS# |______________________________________________| ...
Initialisierungsbefehle für den Nokia LCD-Treiber
Für die Initialisierung habe ich zunächst diese Befehle und Daten gesendet:
Befehl: 0x11
Befehl: 0x20
Befehl: 0x3A
Daten: 0x05
Befehl: 0x36
Daten: 0xC8
Befehl: 0x25
Daten: 0x30
Befehl: 0x29
Befehl: 0x2A
Daten: 0x00
Daten: 97 (Anzahl der Pixelspalte – 1)
Befehl: 0x2B;
Daten: 0x00
Daten: 69 (Anzahl der Pixelzeilen oder -zeilen – 1)
Beispiel für einen Quellcode
Hier ist das Quellcode-Beispiel zum Ändern der Hintergrundfarbe des LCD:
/*******************************************************
This program was created by the
CodeWizardAVR V3.12 Advanced
Chip type : ATmega8A
AVR Core Clock frequency: 8.000000 MHz (Internal)
*******************************************************/
#include <mega8.h>
register unsigned char ucI,rucJ,rucK,i,j;
void vCMD();
void vData();
void vSend();
void vClk();
void vDelay();
// 1mS Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
rucJ++;
TCNT0 = 125;//about 1mS
TIFR = 0x01;
}
void main(void)
{
//Microcontroller init
PORTB = 0x0A;
DDRB = 0x3F;
OSCCAL = 0x99;
//Low level external interrupts - sleep enable
MCUCR = 0x8A;
//Timer 0
TCNT0 = 0;
TCCR0 = 0x03;
TIFR = 0x01;
TIMSK = 0x01;
#asm("sei");
//PORTB.PORTB0 //RST#
//PORTB.PORTB1 //CS#
//PORTB.PORTB2 //SI
//PORTB.PORTB3 //SCK
PORTB.PORTB0 = 0; //RST#
rucK = 250;
//1 second delay
vDelay();
vDelay();
vDelay();
vDelay();
PORTB.PORTB4 = 1; //Status LED 1 On
vDelay();
//LCD Reset
rucK = 1;
PORTB.PORTB0 = 1; //RST#
vDelay();
PORTB.PORTB0 = 0; //RST#
vDelay();
PORTB.PORTB0 = 1; //RST#
//LCD Init
ucI = 0x11;
vCMD();
ucI = 0x20;
vCMD();
ucI = 0x3A;
vCMD();
ucI = 0x05;
vData();
ucI = 0x36;
vCMD();
ucI = 0xC8;
vData();
ucI = 0x25;
vCMD();
ucI = 0x30;
vData();
ucI = 0x29;
vCMD();
PORTB.PORTB5 = 1;
rucK = 250;
vDelay();
//98*70
ucI = 0x2A;
vCMD();
ucI = 0;
vData();
ucI = 97;
vData();
ucI = 0x2B;
vCMD();
ucI = 0;
vData();
ucI = 69;
vData();
//0xFFFF White
//0x0000 Black
while(1)
{
ucI = 0x2c; // Screen data command
vCMD();
//First line
//Border white
for(j = 0; j < 98; j++)
{
//1st byte: BBBBB GGG
//2nd byte: GGG RRRRR
ucI = 0xFF;
vData();
ucI = 0xFF;
vData();
}
//Second line
ucI = 0xFF;
vData();
ucI = 0xFF;
vData();
//Border Black
for(j = 0; j < 96; j++)
{
//1st byte: BBBBB GGG
//2nd byte: GGG RRRRR
ucI = 0x00;
vData();
ucI = 0x00;
vData();
}
ucI = 0xFF;
vData();
ucI = 0xFF;
vData();
//Blue screen
for(i = 0; i < 66; i++)
{
//Border
ucI = 0xFF;
vData();
ucI = 0xFF;
vData();
ucI = 0x00;
vData();
ucI = 0x00;
vData();
for(j = 0; j < 94; j++)
{
//1st byte: BBBBB GGG
//2nd byte: GGG RRRRR
ucI = 0xF8;
vData();
ucI = 0x00;
vData();
}
ucI = 0x00;
vData();
ucI = 0x00;
vData();
ucI = 0xFF;
vData();
ucI = 0xFF;
vData();
}
//Border
ucI = 0xFF;
vData();
ucI = 0xFF;
vData();
for(j = 0; j < 96; j++)
{
//1st byte: BBBBB GGG
//2nd byte: GGG RRRRR
ucI = 0x00;
vData();
ucI = 0x00;
vData();
}
ucI = 0xFF;
vData();
ucI = 0xFF;
vData();
//White border
for(j = 0; j < 98; j++)
{
//1st byte: BBBBB GGG
//2nd byte: GGG RRRRR
ucI = 0xFF;
vData();
ucI = 0xFF;
vData();
}
vDelay(); //250 mS Delay
//Green screen
ucI = 0x2c; // Screen data command
vCMD();
for(i = 0; i < 70; i++)
{
for(j = 0; j < 98; j++)
{
ucI = 0x07;
vData();
ucI = 0xE0;
vData();
}
}
vDelay(); // 250mS Delay
//Red Screen
ucI = 0x2c; // Screen data command
vCMD();
for(i = 0; i < 70; i++)
{
for(j = 0; j < 98; j++)
{
ucI = 0x00;
vData();
ucI = 0x1F;
vData();
}
}
vDelay(); //250mS
};
}
void vCMD()
{
PORTB.PORTB1 = 0; //CS#
#asm("NOP");
#asm("NOP");
#asm("NOP");
#asm("NOP");
PORTB.PORTB2 = 0; //SI#
#asm("NOP");
#asm("NOP");
#asm("NOP");
#asm("NOP");
vSend();
}
void vData()
{
PORTB.PORTB1 = 0; //CS#
#asm("NOP");
#asm("NOP");
#asm("NOP");
#asm("NOP");
PORTB.PORTB2 = 1; //SI#
#asm("NOP");
#asm("NOP");
#asm("NOP");
#asm("NOP");
vSend();
}
void vSend()
{
vClk();
if(ucI & 0x80)
PORTB.PORTB2 = 1; //SI#
else
PORTB.PORTB2 = 0; //SI#
vClk();
if(ucI & 0x40)
PORTB.PORTB2 = 1; //SI#
else
PORTB.PORTB2 = 0; //SI#
vClk();
if(ucI & 0x20)
PORTB.PORTB2 = 1; //SI#
else
PORTB.PORTB2 = 0; //SI#
vClk();
if(ucI & 0x10)
PORTB.PORTB2 = 1; //SI#
else
PORTB.PORTB2 = 0; //SI#
vClk();
if(ucI & 0x08)
PORTB.PORTB2 = 1; //SI#
else
PORTB.PORTB2 = 0; //SI#
vClk();
if(ucI & 0x04)
PORTB.PORTB2 = 1; //SI#
else
PORTB.PORTB2 = 0; //SI#
vClk();
if(ucI & 0x02)
PORTB.PORTB2 = 1; //SI#
else
PORTB.PORTB2 = 0; //SI#
vClk();
if(ucI & 0x01)
PORTB.PORTB2 = 1; //SI#
else
PORTB.PORTB2 = 0; //SI#
vClk();
PORTB.PORTB1 = 1; //CS#
}
void vClk()
{
PORTB.PORTB3 = 0; //SCK#
#asm("NOP");
#asm("NOP");
#asm("NOP");
#asm("NOP");
PORTB.PORTB3 = 1; //SCK#
#asm("NOP");
#asm("NOP");
#asm("NOP");
#asm("NOP");
}
void vDelay()
{
rucJ = 0;
while(rucJ < rucK) //100 mS delay
{
#asm("sleep");
};
}
Geschrieben von: M. Mahdi K. Kanan – Full-Stack-Elektronik- und Programmieringenieur und Gründer von WiCardTech