Configuración y programación del Nokia LCD (6125)
Aquí hay un circuito y un código simples que son compatibles con el controlador PCF8833 para LCD Nokia antiguos (LCD pequeños) como 1208, 1600, 2126, 2310, 6100, 6125, N71.
El circuito y el código de este proyecto son compatibles con el controlador LCD PCF8833 STN RGB – 1321323.
Este controlador de LCD se ha utilizado para algunas pantallas LCD pequeñas de Nokia, como 1208, 1209, 1600, 2126, 2310, 6100 y 6125, 6136, N71.
La pantalla LCD en la que he trabajado es una pantalla LCD de 98*70 píxeles que saqué de un Nokia 6125 destrozado.
Esta pantalla LCD necesita un conector de placa a placa que quité de la PCB de Nokia. La línea de transacción para mi LCD es un SPI de 9 bits que no tiene línea de transmisión y solo recibe datos o comandos del host.
El host (controlador, driver, etc.) que he utilizado es un microcontrolador ATMega8A.
ATMega8A tiene una función SPI de 8 bits, no de 9 bits, por lo que he usado las E/S directamente en lugar del módulo SPI interno.
El circuito LCD de Nokia
Aquí está mi circuito en una placa de pruebas (breadboard):
El esquema
Aquí está el pinout de mi LCD:
- CLK
- Datos
- GND
- CS#
- RESET#
- Luz trasera LED+, 7,5 V
- Luz de fondo LED-, GND
- Carolina del Norte (NC)
- VddAN, 2,8V… 3,3V
- VddIO, 1,8V… 3,3V
Aquí está el esquema:
Protocolo de transacción
Cuando el pin Reset# está bajo, eso significa que la pantalla LCD está en estado de reinicio y no acepta el comando ni los datos.
Cuando CS# es bajo, la pantalla LCD aceptará los comandos/datos.
Aquí está el protocolo de comando en SPI de 9 bits:
__ __ __ __ __ __ __ __ __
CLK ___|C1|_|C2|_|C3|_|C4|_|C5|_|C6|_|C7|_|C8|_|C9|____...
Data_______<b7 ><b6 ><b5 ><b4 ><b3 ><b2 ><b1 ><b0 > ...
_ __
CS# |______________________________________________| ...
Aquí está el protocolo de datos en SPI de 9 bits:
__ __ __ __ __ __ __ __ __
CLK ___|C1|_|C2|_|C3|_|C4|_|C5|_|C6|_|C7|_|C8|_|C9|____...
___
Data_| |_<b7 ><b6 ><b5 ><b4 ><b3 ><b2 ><b1 ><b0 > ...
_ __
CS# |______________________________________________| ...
Inicialización de la pantalla LCD de Nokia
Para la inicialización envié estos comandos y datos primero:
comando: 0x11
comando: 0x20
comando: 0x3A
Datos: 0x05
comando: 0x36
Datos: 0xC8
comando: 0x25
Datos: 0x30
comando: 0x29
comando: 0x2A
Datos: 0x00
Datos: 97 (Número de columna de píxeles – 1)
comando: 0x2B;
Datos: 0x00
Datos: 69 (Número de líneas o filas de píxeles – 1)
Ejemplo de código fuente
Aquí está el ejemplo del código fuente para cambiar el color de fondo de la pantalla 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");
};
}
Escrito por: M. Mahdi K. Kanan – Ingeniero de programación y electrónica de pila completa y fundador de WiCardTech