драйвер ЖК-дисплея Nokia (6125 LCD) программирование
Вот простая схема и код, совместимый с драйвером PCF8833 (драйвер ЖК-дисплея Nokia — mini LCD), например 1208, 1600, 2126, 2310, 6100, 6125, N71 (миниатюрные ЖК-дисплеи).
Схема и код в этом проекте совместимы с драйвером ЖК-дисплея PCF8833 STN RGB — 1321323.
Этот драйвер ЖК-дисплея использовался для некоторых крошечных ЖК-дисплеев Nokia, таких как 1208, 1209, 1600, 2126, 2310, 6100 и 6125, 6136, задний ЖК-дисплей N71.
***»»Проекты по электронике, программированию и Arduino, включая исходные коды, схемы и планы печатных плат для инженеров, студентов и любителей»»***
ЖК-дисплей, над которым я работал, представляет собой ЖК-дисплей размером 98*70 пикселей, который я снял с разбитого Nokia 6125.
Для этого ЖК-дисплея требуется межплатный разъем, который я удалил из печатной платы Nokia. Линия транзакции для моего ЖК-дисплея представляет собой 9-битный SPI, который не имеет линии передачи и принимает только данные или команды от хоста.
Хост (контроллер, драйвер и т. д.), который я использовал, — это микроконтроллер ATMega8A.
ATMega8A имеет 8-битный SPI, а не 9-битный, поэтому я использовал входы/выходы напрямую, а не внутренний модуль SPI.
Схема драйвер ЖК-дисплея Nokia
Вот моя схема на макетной плате:

Схема
Here’s the pinout of my LCD:
1. CLK
2. Data
3. GND
4. CS#
5. RESET#
6. Подсветка LED+, 7,5 В.
7. Подсветка LED-, GND
8. NC
9. VddAN, 2.8V… 3.3V
10. VddIO, 1.8V… 3.3V
Вот схема:

Протокол транзакции
Когда на выводе Reset# низкий уровень, это означает, что ЖК-дисплей находится в состоянии сброса и не принимает команды и данные.
Когда CS# имеет низкий уровень, ЖК-дисплей будет принимать команды/данные.
Вот командный протокол в 9-битном SPI:
        __   __   __   __   __   __   __   __   __  
CLK ___|C1|_|C2|_|C3|_|C4|_|C5|_|C6|_|C7|_|C8|_|C9|____...  
       
Data_______<b7 ><b6 ><b5 ><b4 ><b3 ><b2 ><b1 ><b0 >    ...  
    _                                               __  
CS#  |______________________________________________|  ...  
Вот протокол данных в 9-битном SPI:
        __   __   __   __   __   __   __   __   __  
CLK ___|C1|_|C2|_|C3|_|C4|_|C5|_|C6|_|C7|_|C8|_|C9|____...  
      ___  
Data_|   |_<b7 ><b6 ><b5 ><b4 ><b3 ><b2 ><b1 ><b0 >    ...  
    _                                               __  
CS#  |______________________________________________|  ...  
Инициализация ЖК-дисплея Nokia
Для инициализации я сначала отправил эти команды и данные:
command: 0x11
command: 0x20
command: 0x3A
Data: 0x05
command: 0x36
Data: 0xC8
command: 0x25
Data: 0x30
command: 0x29
command: 0x2A
Data: 0x00
Data: 97 (Кол-во столбцов пикселей — 1)
command: 0x2B;
Data: 0x00
Data: 69 (Количество строк или строк пикселей — 1)
Пример исходного кода
Вот пример исходного кода для изменения цвета фона ЖК-дисплея:
/*******************************************************
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");
  };
}

Автор: М. Мahdi К. Кanan — инженер по электронике и программированию полного цикла, основатель WiCardTech
