#include "18F2520.h"
#fuses INTRC_IO
#use delay(clock=4000000)
// definitions
#define GLCD_CS1 PIN_A1
#define GLCD_RESET PIN_A2
#define GLCD_A0 PIN_A0
#define GLCD_SCL PIN_C3
#define GLCD_SDA PIN_C4
void glcd_command(unsigned char command);
void glcd_data(unsigned char data);
void main()
{
int i;
output_low(GLCD_CS1);
output_low(GLCD_RESET);
delay_ms(200);
output_high(GLCD_RESET);
delay_ms(10);
glcd_command(0x40); // initialization
glcd_command(0xA1);
glcd_command(0xC0);
glcd_command(0xA6);
glcd_command(0xA2);
glcd_command(0x2F);
glcd_command(0xF8);
glcd_command(0x00);
glcd_command(0x27);
glcd_command(0x81);
glcd_command(0x16);
glcd_command(0xAC);
glcd_command(0x00);
glcd_command(0xAF);
while(1)
{
i = 0;
for(i = 0; i < 63; i++)
{
glcd_command(0x00+i);
glcd_data(0xff);
delay_ms(100);
}
}
}
void glcd_command(unsigned int8 command)
{
int n;
output_low(GLCD_A0);
output_low(GLCD_CS1);
for (n = 0; n < 8; n++)
{
if (command & 0x80)
{
output_high(GLCD_SDA);
}
else
{
output_low(GLCD_SDA);
}
// Pulse SCL
output_high(GLCD_SCL);
delay_ms(10);
output_low(GLCD_SCL);
command <<= 1;
}
output_high(GLCD_CS1);
}
void glcd_data(unsigned int8 data)
{
int n;
output_high(GLCD_A0);
output_low(GLCD_CS1);
for (n = 0; n < 8; n++)
{
if (data & 0x80)
{
output_high(GLCD_SDA);
}
else
{
output_low(GLCD_SDA);
}
// Pulse SCL
output_high(GLCD_SCL);
delay_ms(10);
output_low(GLCD_SCL);
data <<= 1;
}
// Unselect the chip
output_high(GLCD_CS1);
}
#fuses INTRC_IO
#use delay(clock=4000000)
// definitions
#define GLCD_CS1 PIN_A1
#define GLCD_RESET PIN_A2
#define GLCD_A0 PIN_A0
#define GLCD_SCL PIN_C3
#define GLCD_SDA PIN_C4
void glcd_command(unsigned char command);
void glcd_data(unsigned char data);
void main()
{
int i;
output_low(GLCD_CS1);
output_low(GLCD_RESET);
delay_ms(200);
output_high(GLCD_RESET);
delay_ms(10);
glcd_command(0x40); // initialization
glcd_command(0xA1);
glcd_command(0xC0);
glcd_command(0xA6);
glcd_command(0xA2);
glcd_command(0x2F);
glcd_command(0xF8);
glcd_command(0x00);
glcd_command(0x27);
glcd_command(0x81);
glcd_command(0x16);
glcd_command(0xAC);
glcd_command(0x00);
glcd_command(0xAF);
// don't see why this needs to be in a continuous while loop
i = 0;
for(i = 0; i < 63; i++) // This for loop will write 0xff to 63 memory
{ // locations in initial page of memory.
// glcd_command(0x00+i); // not sure what this command is intended to do ??
glcd_data(0xff);
delay_ms(100);
}
while(1)
{
}
}
void glcd_command(unsigned int8 command)
{
int n;
output_low(GLCD_A0);
output_low(GLCD_CS1);
for (n = 0; n < 8; n++)
{
output_high(GLCD_SCL); // scl high before data changes
if (command & 0x80) // clocks data into display
{
output_high(GLCD_SDA);
}
else // set data bit high or low
{
output_low(GLCD_SDA);
}
// Pulse SCL
// output_high(GLCD_SCL);
// delay_ms(10); // scl can be 20 mhz, so delays may not not be needed
output_low(GLCD_SCL); // bring scl low after data is there
command <<= 1; // shift to next bit of data
}
output_high(GLCD_SCL); // bring high at end of data byte
output_high(GLCD_CS1);
}
void glcd_data(unsigned int8 data)
{
int n;
output_high(GLCD_A0);
output_low(GLCD_CS1);
for (n = 0; n < 8; n++)
{
output_high(GLCD_SCL);
if (data & 0x80)
{
output_high(GLCD_SDA);
}
else
{
output_low(GLCD_SDA);
}
// Pulse SCL
// delay_ms(10);
output_low(GLCD_SCL);
data <<= 1;
}
output_high(GLCD_SCL); // bring high at end of data byte
// Unselect the chip
output_high(GLCD_CS1);
}
/** Global buffer to hold the current screen contents. */
// This has to be kept here because the width & height are set in
// st7565-config.h
unsigned char glcd_buffer[SCREEN_WIDTH * SCREEN_HEIGHT / 8];
#ifdef ST7565_DIRTY_PAGES
unsigned char glcd_dirty_pages;
#endif
void glcd_pixel(unsigned char x, unsigned char y, unsigned char colour) {
if (x > SCREEN_WIDTH || y > SCREEN_HEIGHT) return;
// Real screen coordinates are 0-63, not 1-64.
x -= 1;
y -= 1;
unsigned short array_pos = x + ((y / 8) * 128);
#ifdef ST7565_DIRTY_PAGES
#warning ** ST7565_DIRTY_PAGES enabled, only changed pages will be written to the GLCD **
glcd_dirty_pages |= 1 << (array_pos / 128);
#endif
if (colour) {
glcd_buffer[array_pos] |= 1 << (y % 8);
} else {
glcd_buffer[array_pos] &= 0xFF ^ 1 << (y % 8);
}
}
void glcd_blank() {
int n,y,x;
// Reset the internal buffer
for (n = 1; n <= (SCREEN_WIDTH * SCREEN_HEIGHT / 8) - 1; n++) {
glcd_buffer[n] = 0;
}
// Clear the actual screen
for (y = 0; y < 8; y++) {
glcd_command(GLCD_CMD_SET_PAGE | y);
// Reset column to 0 (the left side)
glcd_command(GLCD_CMD_COLUMN_LOWER);
glcd_command(GLCD_CMD_COLUMN_UPPER);
// We iterate to 132 as the internal buffer is 65*132, not
// 64*124.
for (x = 0; x < 132; x++) {
glcd_data(0x00);
}
}
}
void glcd_refresh() {
int y, x;
for (y = 0; y < 8; y++) {
#ifdef ST7565_DIRTY_PAGES
// Only copy this page if it is marked as "dirty"
if (!(glcd_dirty_pages & (1 << y))) continue;
#endif
glcd_command(GLCD_CMD_SET_PAGE | y);
// Reset column to the left side. The internal memory of the
// screen is 132*64, we need to account for this if the display
// is flipped.
//
// Some screens seem to map the internal memory to the screen
// pixels differently, the ST7565_REVERSE define allows this to
// be controlled if necessary.
#ifdef ST7565_REVERSE
if (!glcd_flipped) {
#else
if (glcd_flipped) {
#endif
glcd_command(GLCD_CMD_COLUMN_LOWER | 4);
} else {
glcd_command(GLCD_CMD_COLUMN_LOWER);
}
glcd_command(GLCD_CMD_COLUMN_UPPER);
for (x = 0; x < 128; x++) {
glcd_data(glcd_buffer[y * 128 + x]);
}
}
#ifdef ST7565_DIRTY_PAGES
// All pages have now been updated, reset the indicator.
glcd_dirty_pages = 0;
#endif
}
void glcd_init() {
// Select the chip
output_low(GLCD_CS1);
output_low(GLCD_RESET);
// Datasheet says "wait for power to stabilise" but gives
// no specific time!
delay_ms(50);
output_high(GLCD_RESET);
// Datasheet says max 1ms here
//DelayMs(1);
// Set LCD bias to 1/9th
glcd_command(GLCD_CMD_BIAS_9);
// Horizontal output direction (ADC segment driver selection)
glcd_command(GLCD_CMD_HORIZONTAL_NORMAL);
// Vertical output direction (common output mode selection)
glcd_command(GLCD_CMD_VERTICAL_REVERSE);
// The screen is the "normal" way up
glcd_flipped = 0;
// Set internal resistor. A suitable middle value is used as
// the default.
glcd_command(GLCD_CMD_RESISTOR | 0x3);
// Power control setting (datasheet step 7)
// Note: Skipping straight to 0x7 works with my hardware.
// glcd_command(GLCD_CMD_POWER_CONTROL | 0x4);
// DelayMs(50);
// glcd_command(GLCD_CMD_POWER_CONTROL | 0x6);
// DelayMs(50);
glcd_command(GLCD_CMD_POWER_CONTROL | 0x7);
// DelayMs(10);
// Volume set (brightness control). A middle value is used here
// also.
glcd_command(GLCD_CMD_VOLUME_MODE);
glcd_command(31);
// Reset start position to the top
glcd_command(GLCD_CMD_DISPLAY_START);
// Turn the display on
glcd_command(GLCD_CMD_DISPLAY_ON);
// Unselect the chip
output_high(GLCD_CS1);
}
void glcd_data(unsigned char data) {
int n;
// A0 is high for display data
output_high(GLCD_A0);
// Select the chip
output_low(GLCD_CS1);
for (n = 0; n < 8; n++) {
if (data & 0x80) {
output_high(GLCD_SDA);
} else {
output_low(GLCD_SDA);
}
// Pulse SCL
output_high(GLCD_SCL);
output_low(GLCD_SCL);
data <<= 1;
}
// Unselect the chip
output_high(GLCD_CS1);
}
void glcd_command(char command) {
int n;
// A0 is low for command data
output_low(GLCD_A0);
// Select the chip
output_low(GLCD_CS1);
for (n = 0; n < 8; n++) {
if (command & 0x80) {
output_high(GLCD_SDA);
} else {
output_low(GLCD_SDA);
}
// Pulse SCL
output_high(GLCD_SCL);
output_low(GLCD_SCL);
command <<= 1;
}
// Unselect the chip
output_high(GLCD_CS1);
}
void glcd_flip_screen(unsigned char flip) {
if (flip) {
glcd_command(GLCD_CMD_HORIZONTAL_NORMAL);
glcd_command(GLCD_CMD_VERTICAL_REVERSE);
glcd_flipped = 0;
} else {
glcd_command(GLCD_CMD_HORIZONTAL_REVERSE);
glcd_command(GLCD_CMD_VERTICAL_NORMAL);
glcd_flipped = 1;
}
}
void glcd_inverse_screen(unsigned char inverse) {
if (inverse) {
glcd_command(GLCD_CMD_DISPLAY_REVERSE);
} else {
glcd_command(GLCD_CMD_DISPLAY_NORMAL);
}
}
void glcd_test_card() {
int n;
unsigned char p = 0xF0;
for (n = 1; n <= (SCREEN_WIDTH * SCREEN_HEIGHT / 8); n++) {
glcd_buffer[n - 1] = p;
if (n % 4 == 0) {
unsigned char q = p;
p = p << 4;
p |= q >> 4;
}
}
glcd_refresh();
}
void glcd_contrast(char resistor_ratio, char contrast) {
if (resistor_ratio > 7 || contrast > 63) return;
glcd_command(GLCD_CMD_RESISTOR | resistor_ratio);
glcd_command(GLCD_CMD_VOLUME_MODE);
glcd_command(contrast);
}
/**
* @file st7565.h
* @author David <david@edeca.net>
* @date November, 2011
* @brief Header for ST7565 graphic LCD library.
* @sa <a href="http://XXXXX">ST7565 command reference</a>
* @sa <a href="http://edeca.net/wp/electronics/the-st7565-display-controller/">My ST7565 introduction blog</a>
* @sa <a href="http://www.ladyada.net/learn/lcd/st7565.html">Adafruit tutorial</a>
* @details
*
* A library for using the ST7565 graphic LCD in serial (software SPI) mode.
*
* This library is a low-level interface to the screen only. Graphics functions (text, images
* etc) are separate.
*
* Each screen requires different settings for brightness (the "volume control" and internal
* resistor settings). The initialisation code picks a middle ground, but you may need to
* modify this.
*
* In serial mode it is not possible to read data back from the screen, meaning we
* need an array to hold the current data. For a 128*64 screen, this will require
* 1KiB of RAM. We need to know what data is currently on the screen so that we can overlay
* new pixels onto it, so must keep a copy in local memory.
*
* SPI timings have been checked using the MPLAB Simulator, with Vcc of 3.3v it is impossible
* to violate the datasheet guidelines even up to 64Mhz.
*
* This code has been tested on a PIC 18F26K20 at 64Mhz using the internal PLL. No
* adverse effects were noticed at this speed. You will need the HiTech delay routines
* or an equivalent.
*
* Example usage (initialisation):
* @code
* // Initialise the screen, turning it on
* glcd_init();
*
* // Clear the screen's internal memory
* glcd_blank();
*
* // Set the screen's brightness, if required. See below for information
* // on how this works.
* glcd_contrast(3, 25);
* @endcode
*
* Example usage (writing to the screen):
* @code
* // Set some pixels in the RAM buffer
* glcd_pixel(1, 1, 1);
* glcd_pixel(2, 1, 1);
* glcd_pixel(1, 2, 1);
* glcd_pixel(2, 2, 1);
*
* // Clear a pixel in the RAM buffer
* glcd_pixel(64, 64, 0);
*
* // Copy the RAM buffer to the screen
* glcd_refresh();
* @endcode
*
* @note This is a low level library only, with support for setting & clearing pixels. For text
* or graphics functions, please see my graphics library.
*
* This code is released under the BSD license. Please see BSD-LICENSE.TXT for more information.
*
* @todo Check timings compared to datasheet, supply a max recommended Fosc.
* @todo Handle different sized screens if appropriate, e.g. 128*32 (some code is still
* fixed to certain screen/page sizes).
*/
#ifndef _ST7565_H_
#define _ST7565_H_
/** Command: turn the display on */
#define GLCD_CMD_DISPLAY_ON 0b10101111
/** Command: turn the display off */
#define GLCD_CMD_DISPLAY_OFF 0b10101110
/** Command: set all points on the screen to normal. */
#define GLCD_CMD_ALL_NORMAL 0b10100100
/** Command: set all points on the screen to "on", without affecting
the internal screen buffer. */
#define GLCD_CMD_ALL_ON 0b10100101
/** Command: disable inverse (black pixels on a white background) */
#define GLCD_CMD_DISPLAY_NORMAL 0b10100110
/** Command: inverse the screen (white pixels on a black background) */
#define GLCD_CMD_DISPLAY_REVERSE 0b10100111
/** Command: set LCD bias to 1/9th */
#define GLCD_CMD_BIAS_9 0b10100010
/** Command: set LCD bias to 1/7th */
#define GLCD_CMD_BIAS_7 0b10100011
/** Command: set ADC output direction to normal. */
#define GLCD_CMD_HORIZONTAL_NORMAL 0b10100000
/** Command: set ADC output direction reverse (horizontally flipped).
Note that you should use the glcd_flip_screen function so that
the width is correctly accounted for. */
#define GLCD_CMD_HORIZONTAL_REVERSE 0b10100001
/** Command: set common output scan direction to normal. */
#define GLCD_CMD_VERTICAL_NORMAL 0b11000000
/** Command: set common output scan direction to reversed (vertically flipped). */
#define GLCD_CMD_VERTICAL_REVERSE 0b11001000
/** Command: select the internal power supply operating mode. */
#define GLCD_CMD_POWER_CONTROL 0b00101000
/** Command: set internal R1/R2 resistor bias (OR with 0..7) */
#define GLCD_CMD_RESISTOR 0b00100000
/** Command: enter volume mode, send this then send another command
byte with the contrast (0..63). The second command
must be sent for the GLCD to exit volume mode. */
#define GLCD_CMD_VOLUME_MODE 0b10000001
#define GLCD_CMD_DISPLAY_START 0b01000000
/** Command: set the least significant 4 bits of the column address. */
#define GLCD_CMD_COLUMN_LOWER 0b00000000
/** Command: set the most significant 4 bits of the column address. */
#define GLCD_CMD_COLUMN_UPPER 0b00010000
/** Command: Set the current page (0..7). */
#define GLCD_CMD_SET_PAGE 0b10110000
/** Command: software reset (note: should be combined with toggling GLCD_RS) */
#define GLCD_CMD_RESET 0b11100010
/** Command: no operation (note: the datasheet suggests sending this periodically
to keep the data connection alive) */
#define GLCD_CMD_NOP 0b11100011
/**
* Initialise the screen. This should be called first.
*/
void glcd_init();
/**
* Send a command byte to the screen. See GLCD_CMD_ constants for
* a list of commands.
*/
void glcd_command(char);
/**
* Send a data byte to the screen.
*/
void glcd_data(char);
/**
* Update the screen with the contents of the RAM buffer.
*/
void glcd_refresh();
/**
* Clear the screen, without affecting the buffer in RAM.
*
* Useful at startup as the memory inside the screen may
* contain "random" data.
*/
void glcd_blank();
/**
* Set a single pixel
*
* @param x The x position, from 1 - SCREEN_WIDTH
* @param y The y position, from 1 - SCREEN_HEIGHT
* @param colour 0 = OFF, any other value = ON
*/
void glcd_pixel(unsigned char x, unsigned char y, unsigned char colour);
/**
* Flip the screen in the alternate direction vertically.
*
* Can be used if the screen is mounted in an enclosure upside
* down.
*/
void glcd_flip_screen(unsigned char flip);
/**
* Inverse the screen, swapping "on" and "off" pixels.
*
* This does not affect the RAM buffer or the screen memory, the controller
* is capable of reversing pixels with a single command.
*/
void glcd_inverse_screen(unsigned char inverse);
/**
* Fill the local RAM buffer with a test pattern and send it to the screen.
*
* Useful for ensuring that the screen is receiving data correctly or for
* adjusting contrast.
*/
void glcd_test_card();
/**
* Set the contrast of the screen. This involves two steps, setting the
* internal resistor ratio (R1:R2) and then the contrast.
*
* Tip: Find a resistor ratio that works well with the screen and stick to it
* throughout. Then adjust the contrast dynamically between 0 and 63.
*
* @param resistor_ratio Ratio of the internal resistors, from 0-7
* @param contrast Contrast, from 0-63
*/
void glcd_contrast(char resistor_ratio, char contrast);
/** Global variable that tracks whether the screen is the "normal" way up. */
unsigned char glcd_flipped = 0;
#endif // _ST7565_H_
// Setup for ST7565R in SPI mode
/** The chip select pin */
#define GLCD_CS1 PIN_A1
/** The reset pin (this is required and should not be tied high) */
#define GLCD_RESET PIN_A2
/** The A0 pin, which selects command or data mode */
#define GLCD_A0 PIN_A0
/** The clock pin */
#define GLCD_SCL PIN_C3
/** The data pin */
#define GLCD_SDA PIN_C4
/** Screen width in pixels (tested with 128) */
#define SCREEN_WIDTH 128
/** Screen height in pixels (tested with 64) */
#define SCREEN_HEIGHT 64
/** Define this if your screen is incorrectly shifted by 4 pixels */
#define ST7565_REVERSE
/** By default we only write pages that have changed. Undefine this
if you want less/faster code at the expense of more SPI operations. */
//#undef ST7565_DIRTY_PAGES 1
#include "18F2520.h"
#fuses INTRC_IO // Internal oscillator
#use delay(clock=4000000) // 4Mhz
#include "st7565.h"
#include "st7565-config.h"
#include "st7565.c"
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD); // No analogs
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_comparator (NC_NC_NC_NC); // Disable comparator
glcd_init();
delay_ms(100);
glcd_contrast(10, 25);
while(1)
{
glcd_pixel(1, 1, 1);
glcd_pixel(2, 1, 1);
glcd_pixel(1, 2, 1);
glcd_pixel(2, 2, 1);
delay_ms(1000);
// Clear a pixel in the RAM buffer
glcd_pixel(64, 64, 0);
delay_ms(1000);
glcd_refresh();
}
}
void glcd_command(char command)
{
char a=0x80;
do
{
output_high(GLCD_SCL); // scl high before data changes
if (command & a) // clocks data into display
{
output_high(GLCD_SDA);
output_high(GLCD_SDA);
}
else // set data bit high or low
{
output_low(GLCD_SDA);
output_low(GLCD_SDA);
}
a >>= 1; // shift to next bit of data
}
while(a>0);
}
In the Post # 1 you tell the display where you have to display.. Row and columns..
and also make pin C3 , C4 having pull ups..
I guess, amayilsamy was confused by your pin names GLCD_SDA and GLCD_SCL.Graphic LCD is of spi. Why do it requires a pull up?
glcd_command(0x00+i);
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?