PIC8-Bit Trainer - Module LCD - NHD-C12832A1Z - ST7565R - 128x32 Graphical.

0.Contents

PIC18F Trainer : PIC18F2xJ13 @8MHz Internal oscillator.

1.String & Custom Patterns - MSSP1 SPI - Backlight auto power off.


- SPI MODE0 : CKP = 0, CKE = 1.
- SPI MODE1 : CKP = 0, CKE = 0.
- SPI MODE2 : CKP = 1, CKE = 1.
- SPI MODE3 : CKP = 1, CKE = 0.

// Configuration registers.
#pragma config WDTEN=OFF, PLLDIV=1, CFGPLLEN=OFF, STVREN=ON, XINST=OFF
#pragma config CP0=OFF, OSC=INTOSCO, SOSCSEL=HIGH, CLKOEC=OFF, FCMEN=OFF
#pragma config IESO=OFF, WDTPS=32768, DSWDTOSC=INTOSCREF, RTCOSC=T1OSCREF
#pragma config DSBOREN=ON, DSWDTEN=ON, DSWDTPS=G2
#pragma config IOL1WAY=ON, ADCSEL=BIT10, PLLSEL=PLL4X, MSSP7B_EN=MSK7
#pragma config WPFP=PAGE_63, WPCFG=OFF, WPDIS=OFF, WPEND=PAGE_WPFP

#include <xc.h>
#include <stdint.h>
//#include "font.h"
#define _XTAL_FREQ 8000000
// PIC18FxxJ13 - Compile with XC8(v2.05).
// PIC18FxxJ13 - @8MHz Internal oscillator.

// TODO Pinout.

// LCD - NHD-12832A1Z - ST7565R - MSSP1 SPI Backlight auto power off.
// String & Custom Patterns.

// Expansion Board - NHD-C12832A1Z - Rev.A.

// MODULE.01 -> GND.
// MODULE.02 -> VDD - 3V3.
// MODULE.03 -> MCU.RC2.
// MODULE.04 -> MCU.RC1.
// MODULE.05 -> MCU.RC3.
// MODULE.06 -> MCU.RC5.
// MODULE.07 -> MCU.RC0.
// MODULE.08 -> GND.
// MODULE.09 -> NC.
// MODULE.10 -> NC.
// MODULE.11 -> NC.
// MODULE.12 -> NC.
// MODULE.13 -> NC.
// MODULE.14 -> NC.
// MODULE.15 -> NC.
// MODULE.16 -> NC.

// JP1 - SCL Open.
// JP2 - SDA Open.
// JP3 - VEE Open.
// JP4 - BCKL Not Use.

// Definitions.
// SPI Port.
#define SPI_CS_TRIS												TRISCbits.TRISC1
#define SPI_SCK_TRIS											TRISCbits.TRISC3
#define SPI_SDI_TRIS											TRISCbits.TRISC4
#define SPI_SDO_TRIS											TRISCbits.TRISC5
// ST7032 Port.
#define ST7565R_A0												LATCbits.LATC2
#define ST7565R_A0_TRIS											TRISCbits.TRISC2
#define C12832A1Z_BACKLIGHT										LATCbits.LATC0
#define C12832A1Z_BACKLIGHT_TRIS								TRISCbits.TRISC0


// ST7565R Commands.
#define ST7565R_DISPLAY_OFF										0xAE
#define ST7565R_DISPLAY_ON										0xAF
#define ST7565R_DISPLAY_START_LINE								0x40
#define ST7565R_PAGE_ADDRESS_SET_0								0xB0
#define ST7565R_PAGE_ADDRESS_SET_1								0xB1
#define ST7565R_PAGE_ADDRESS_SET_2								0xB2
#define ST7565R_PAGE_ADDRESS_SET_3								0xB3
#define ST7565R_PAGE_ADDRESS_SET_4								0xB4
#define ST7565R_PAGE_ADDRESS_SET_5								0xB5
#define ST7565R_PAGE_ADDRESS_SET_6								0xB6
#define ST7565R_PAGE_ADDRESS_SET_7								0xB7
#define ST7565R_PAGE_ADDRESS_SET_8								0xB8

#define ST7565R_COLUMN_ADDRESS_SET_LSB							0x00
#define ST7565R_COLUMN_ADDRESS_SET_MSB							0x10
#define ST7565R_ADDRESS_COLUMN_NORMAL							0xA0
#define ST7565R_ADDRESS_COLUMN_REVERSE							0xA1
#define ST7565R_VOLTAGE_BIAS_RATIO_A2							0xA2
#define ST7565R_VOLTAGE_BIAS_RATIO_A3							0xA3
#define ST7565R_DISPLAY_ALL_POINT_RAM							0xA4
#define ST7565R_DISPLAY_ALL_POINT_ON							0xA5
#define ST7565R_DISPLAY_NORMAL									0xA6
#define ST7565R_DISPLAY_INVERSE									0xA7
#define ST7565R_COMMON_MODE_SELECT_NORMAL						0xC0
#define ST7565R_COMMON_MODE_SELECT_REVERSE						0xC8
#define ST7565R_READ_MODIFY_WRITE								0xE0
#define ST7565R_READ_MODIFY_WRITE_END							0xEE

// TODO

#define ST7565R_DISPLAY_CONTRAST								0x81

#define ST7565R_INTERNAL_RESISSTOR_RATIO_0						0x20
#define ST7565R_INTERNAL_RESISSTOR_RATIO_1						0x21
#define ST7565R_INTERNAL_RESISSTOR_RATIO_2						0x22
#define ST7565R_INTERNAL_RESISSTOR_RATIO_3						0x23
#define ST7565R_INTERNAL_RESISSTOR_RATIO_4						0x24
#define ST7565R_INTERNAL_RESISSTOR_RATIO_5						0x25
#define ST7565R_INTERNAL_RESISSTOR_RATIO_6						0x26
#define ST7565R_INTERNAL_RESISSTOR_RATIO_7						0x27

#define ST7565R_POWER_BOOST_OFF_REGULATOR_OFF_FOLLOWER_OFF		0x28
#define ST7565R_POWER_BOOST_OFF_REGULATOR_OFF_FOLLOWER_ON		0x29
#define ST7565R_POWER_BOOST_OFF_REGULATOR_ON_FOLLOWER_ON		0x2B
#define ST7565R_POWER_BOOST_ON_REGULATOR_ON_FOLLOWER_ON			0x2F

// C12832A1Z.
#define C12832A1Z_PAGE											4
#define C12832A1Z_COLUMN										128


// Function prototypes.
void spi_initializeMaster(void);
void st7565r_clearDisplay(void);
void st7565r_clearPage(uint8_t u8Page);
void st7565r_initialize(void);
void st7565r_writeCommand(char cData);
void st7565r_writeData(char cData);
void st7565r_writeFont(uint8_t u8Data);
void st7565r_writeString(const char * cData);
void st7565r_writeStringSetCursor(const char * cData, uint8_t u8Page, uint8_t u8MSB, uint8_t u8LSB);

// Strings & Custom patterns.
const char string0[] = "Tronix I/O";
const char string1[] = "www.tronix.io";
const char string2[] = "Newhaven Display";
const char string3[] = "NHD-C12832A1Z";
// Font 5x7.
const uint8_t font5x7[96][5] =
{
	{0x00, 0x00, 0x00, 0x00, 0x00}, // Space
	{0x00, 0x00, 0x5F, 0x00, 0x00}, // !
	{0x00, 0x07, 0x00, 0x07, 0x00}, // "
	{0x14, 0x7F, 0x14, 0x7F, 0x14}, // #
	{0x24, 0x2A, 0x7f, 0x2A, 0x12}, // $
	{0x23, 0x13, 0x08, 0x64, 0x62}, // %
	{0x36, 0x49, 0x55, 0x22, 0x50}, // &
	{0x00, 0x00, 0x03, 0x00, 0x00}, // '
	{0x00, 0x1C, 0x22, 0x41, 0x00}, // (
	{0x00, 0x41, 0x22, 0x1C, 0x00}, // )
	{0x14, 0x08, 0x3E, 0x08, 0x14}, // *
	{0x08, 0x08, 0x3E, 0x08, 0x08}, // +
	{0x00, 0x50, 0x30, 0x00, 0x00}, // ,
	{0x08, 0x08, 0x08, 0x08, 0x08}, // -
	{0x00, 0x60, 0x60, 0x00, 0x00}, // .
	{0x20, 0x10, 0x08, 0x04, 0x02}, // /
	{0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0
	{0x00, 0x42, 0x7F, 0x40, 0x00}, // 1
	{0x42, 0x61, 0x51, 0x49, 0x46}, // 2
	{0x21, 0x41, 0x45, 0x4B, 0x31}, // 3
	{0x18, 0x14, 0x12, 0x7F, 0x10}, // 4
	{0x27, 0x45, 0x45, 0x45, 0x39}, // 5
	{0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6
	{0x03, 0x71, 0x09, 0x05, 0x03}, // 7
	{0x36, 0x49, 0x49, 0x49, 0x36}, // 8
	{0x06, 0x49, 0x49, 0x29, 0x1E}, // 9
	{0x00, 0x36, 0x36, 0x00, 0x00}, // :
	{0x00, 0x56, 0x36, 0x00, 0x00}, // ;
	{0x08, 0x14, 0x22, 0x41, 0x00}, // <
	{0x14, 0x14, 0x14, 0x14, 0x14}, // =
	{0x00, 0x41, 0x22, 0x14, 0x08}, // >
	{0x02, 0x01, 0x51, 0x09, 0x06}, // ?
	{0x32, 0x49, 0x79, 0x41, 0x3E}, // @
	{0x7E, 0x11, 0x11, 0x11, 0x7E}, // A
	{0x7F, 0x49, 0x49, 0x49, 0x36}, // B
	{0x3E, 0x41, 0x41, 0x41, 0x22}, // C
	{0x7F, 0x41, 0x41, 0x41, 0x3E}, // D
	{0x7F, 0x49, 0x49, 0x49, 0x41}, // E
	{0x7F, 0x09, 0x09, 0x09, 0x01}, // F
	{0x3E, 0x41, 0x41, 0x49, 0x7A}, // G
	{0x7F, 0x08, 0x08, 0x08, 0x7F}, // H
	{0x00, 0x41, 0x7F, 0x41, 0x00}, // I
	{0x20, 0x40, 0x41, 0x3F, 0x01}, // J
	{0x7F, 0x08, 0x14, 0x22, 0x41}, // K
	{0x7F, 0x40, 0x40, 0x40, 0x40}, // L
	{0x7F, 0x02, 0x0C, 0x02, 0x7F}, // M
	{0x7F, 0x04, 0x08, 0x10, 0x7F}, // N
	{0x3E, 0x41, 0x41, 0x41, 0x3E}, // O
	{0x7F, 0x09, 0x09, 0x09, 0x06}, // P
	{0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q
	{0x7F, 0x09, 0x19, 0x29, 0x46}, // R
	{0x26, 0x49, 0x49, 0x49, 0x32}, // S
	{0x01, 0x01, 0x7F, 0x01, 0x01}, // T
	{0x3F, 0x40, 0x40, 0x40, 0x3F}, // U
	{0x1F, 0x20, 0x40, 0x20, 0x1F}, // V
	{0x3F, 0x40, 0x38, 0x40, 0x3F}, // W
	{0x63, 0x14, 0x08, 0x14, 0x63}, // X
	{0x07, 0x08, 0x70, 0x08, 0x07}, // Y
	{0x61, 0x51, 0x49, 0x45, 0x43}, // Z
	{0x00, 0x7F, 0x41, 0x41, 0x00}, // [
	{0x02, 0x04, 0x08, 0x10, 0x20}, //
	{0x00, 0x41, 0x41, 0x7F, 0x00}, // ]
	{0x04, 0x02, 0x01, 0x02, 0x04}, // ^
	{0x40, 0x40, 0x40, 0x40, 0x40}, // _
	{0x00, 0x01, 0x02, 0x04, 0x00}, // '
	{0x20, 0x54, 0x54, 0x54, 0x78}, // a
	{0x7F, 0x48, 0x44, 0x44, 0x38}, // b
	{0x38, 0x44, 0x44, 0x44, 0x20}, // c
	{0x38, 0x44, 0x44, 0x48, 0x7F}, // d
	{0x38, 0x54, 0x54, 0x54, 0x18}, // e
	{0x08, 0x7E, 0x09, 0x01, 0x02}, // f
	{0x08, 0x54, 0x54, 0x54, 0x3C}, // g
	{0x7F, 0x08, 0x04, 0x04, 0x78}, // h
	{0x00, 0x48, 0x7D, 0x40, 0x00}, // i
	{0x20, 0x40, 0x44, 0x3D, 0x00}, // j
	{0x7F, 0x10, 0x28, 0x44, 0x00}, // k
	{0x00, 0x41, 0x7F, 0x40, 0x00}, // l
	{0x7C, 0x04, 0x78, 0x04, 0x78}, // m
	{0x7C, 0x08, 0x04, 0x04, 0x78}, // n
	{0x38, 0x44, 0x44, 0x44, 0x38}, // o
	{0x7C, 0x14, 0x14, 0x14, 0x08}, // p
	{0x08, 0x14, 0x14, 0x18, 0x7C}, // q
	{0x7C, 0x08, 0x04, 0x04, 0x08}, // r
	{0x48, 0x54, 0x54, 0x54, 0x20}, // s
	{0x04, 0x3F, 0x44, 0x40, 0x20}, // t
	{0x3C, 0x40, 0x40, 0x20, 0x7C}, // u
	{0x1C, 0x20, 0x40, 0x20, 0x1C}, // v
	{0x3C, 0x40, 0x30, 0x40, 0x3C}, // w
	{0x44, 0x28, 0x10, 0x28, 0x44}, // x
	{0x0C, 0x50, 0x50, 0x50, 0x3C}, // y
	{0x44, 0x64, 0x54, 0x4C, 0x44}, // z
	{0x00, 0x08, 0x36, 0x41, 0x00}, // {
	{0x00, 0x00, 0x7F, 0x00, 0x00}, // |
	{0x00, 0x41, 0x36, 0x08, 0x00}, // }
	{0x10, 0x08, 0x08, 0x10, 0x08}, // ~
	{0x06, 0x09, 0x09, 0x06, 0x00}  // °
};

// Main.
int main(void)
{
	// MCU Initialization.
	// Internal Oscillator Frequency 8MHz.
	OSCCONbits.IRCF = 0b111;
	// Ports Initialization.
    // Open-drain Output Settings.
    ODCON3 = 0b00000000;
    ODCON2 = 0b00000000;
    ODCON1 = 0b00000000;
	// Analog Input Settings.
	ANCON1 = 0b00011111;
	ANCON0 = 0b00011111;	// For PIC18F2xJ13.
	//ANCON0 = 0b11111111;	// For PIC18F4xJ13.
	// Port A.
	PORTA = 0b00000000;
	TRISA = 0b00000000;
	// Port B.
	PORTB = 0b00000000;
	TRISB = 0b00000000;
	// Port C.
	PORTC = 0b00000000;
	TRISC = 0b00000000;
	// Port D.
	//PORTD = 0b00000000;	// For PIC18F4xJ13.
	//TRISD = 0b00000000;	// For PIC18F4xJ13.
	// Port E.
	//PORTE = 0b00000000;	// For PIC18F4xJ13.
	//TRISE = 0b00000000;	// For PIC18F4xJ13.
	// SPI Port.
	SPI_CS_TRIS = 0;
	SPI_SCK_TRIS = 0;
	SPI_SDI_TRIS = 1;
    SPI_SDO_TRIS = 0;
	// ST7032 Register Select.
	ST7565R_A0 = 0;
	ST7565R_A0_TRIS = 0;
	// ST7032 Backlight.
	C12832A1Z_BACKLIGHT = 1;
	C12832A1Z_BACKLIGHT_TRIS = 0;

	spi_initializeMaster();
	st7565r_initialize();

	// Display String.
	st7565r_clearDisplay();
	st7565r_writeStringSetCursor(string0, ST7565R_PAGE_ADDRESS_SET_0, 0x02, 0x05);
	st7565r_writeStringSetCursor(string1, ST7565R_PAGE_ADDRESS_SET_1, 0x02, 0x00);
	st7565r_writeStringSetCursor(string2, ST7565R_PAGE_ADDRESS_SET_2, 0x01, 0x02);
	st7565r_writeStringSetCursor(string3, ST7565R_PAGE_ADDRESS_SET_3, 0x02, 0x00);

	// Backlight delay.
    uint8_t i;
	uint8_t st7565r_backlight = 10;
	while(1){
		st7565r_backlight--;
		if(!st7565r_backlight){
			C12832A1Z_BACKLIGHT = 0;
		}
        for(i=0; i<60; i++)
            __delay_ms(100);
	}
	return(0);
}

// Functions.
void spi_initializeMaster(void)
{
	// SPI1 - Master - Mode 0.
    SSPSTAT = 0b01000000;
    // SPI1 - Fosc / 16.
	// Clock frequency = 8000000 / 16 = 500kHz.
	SSP1CON1 = 0b00000001;
    // SPI1 Start.
    SSP1CON1bits.SSPEN1 = 1;
}

void st7565r_clearDisplay(void)
{
	uint8_t page;
	uint8_t column;

	for(page=0; page<C12832A1Z_PAGE; page++){
		st7565r_writeCommand(ST7565R_PAGE_ADDRESS_SET_0 + page);
		st7565r_writeCommand(ST7565R_COLUMN_ADDRESS_SET_MSB);
		st7565r_writeCommand(ST7565R_COLUMN_ADDRESS_SET_LSB);
		for (column=0; column<C12832A1Z_COLUMN; column++){
			st7565r_writeData(0x00);
		}
	}
}

void st7565r_clearPage(uint8_t u8Page)
{
	uint8_t column;

	st7565r_writeCommand(u8Page);
	st7565r_writeCommand(ST7565R_COLUMN_ADDRESS_SET_MSB);
	st7565r_writeCommand(ST7565R_COLUMN_ADDRESS_SET_LSB);
	for (column=0; column<C12832A1Z_COLUMN; column++){
		st7565r_writeData(0x00);
	}
}

void st7565r_initialize(void)
{
	uint8_t dummy;

	__delay_ms(5);
	ST7565R_A0 = 0;
	SSP1BUF = ST7565R_DISPLAY_OFF;
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
	SSP1BUF = ST7565R_VOLTAGE_BIAS_RATIO_A2;
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
	SSP1BUF = ST7565R_ADDRESS_COLUMN_NORMAL;
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
	SSP1BUF = ST7565R_COMMON_MODE_SELECT_REVERSE;
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
	SSP1BUF = ST7565R_INTERNAL_RESISSTOR_RATIO_2;
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
	SSP1BUF = ST7565R_POWER_BOOST_ON_REGULATOR_ON_FOLLOWER_ON;
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
    SSP1BUF = ST7565R_DISPLAY_START_LINE;
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
	SSP1BUF = ST7565R_DISPLAY_ON;
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
	SSP1BUF = ST7565R_DISPLAY_CONTRAST;
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
	SSP1BUF = 0x12; //0x10 good.
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
	SSP1BUF = ST7565R_DISPLAY_NORMAL;
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
	__delay_ms(2);
}

void st7565r_writeCommand(char cData)
{
	uint8_t dummy;

	ST7565R_A0 = 0;
	SSP1BUF = (cData);
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
}

void st7565r_writeData(char cData)
{
	uint8_t dummy;

	ST7565R_A0 = 1;
	SSP1BUF = (cData);
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
}

void st7565r_writeFont(uint8_t u8Data)
{
	uint8_t dummy;
	uint8_t column;

	ST7565R_A0 = 1;
	for(column=0; column<5; column++){
		SSP1BUF = (font5x7[(uint8_t)(u8Data - 0x20)][column]);
		while(!SSP1STATbits.BF);
		dummy = SSP1BUF;
	}
    // Add One Space Column before next Character.
	SSP1BUF = 0x00;
	while(!SSP1STATbits.BF);
	dummy = SSP1BUF;
}

void st7565r_writeString(const char * cData)
{
	while(*cData != '\0'){
		st7565r_writeFont(*cData++);
	}
}

void st7565r_writeStringSetCursor(const char * cData, uint8_t u8Page, uint8_t u8MSB, uint8_t u8LSB)
{
	st7565r_writeCommand(u8Page);
	st7565r_writeCommand(ST7565R_COLUMN_ADDRESS_SET_MSB + u8MSB);
	st7565r_writeCommand(ST7565R_COLUMN_ADDRESS_SET_LSB + u8LSB);
	while(*cData != '\0'){
		st7565r_writeFont(*cData++);
	}
}

2.TODO - String & Custom Patterns - MSSP2 SPI - PPS - Backlight auto power off. - TODO

05.2019