📄 lcd.c
字号:
////////////////////////////////////////////////////////////////
//
// S C R I P T H E R M
// A SCRIPTABLE THERMOMETER
//
// entry of the National Semiconductor COP8FLASH Design Contest
// submitted by Alberto Ricci Bitti (C) 2001
// a.riccibitti@ra.nettuno.it
//
//--------------------------------------------------------------
// FOR A BETTER VIEW SET TAB SIZE=4, INDENT SIZE=4
//--------------------------------------------------------------
// FILE : lcd.c
// PURPOSE: very portable LCD display driver. Just change the
// #defines for pin assignment and display size
// and check the non-critical wait() delay.
// Works with LCD modules based on the T6963 controller.
//
////////////////////////////////////////////////////////////////
#include <ioc8cdr.h>
#include "lcd.h"
/////////////////////////////////////////////////////////////////////
//vary these according to your display size
/////////////////////////////////////////////////////////////////////
#define PIXELS_X 128
#define PIXELS_Y 64
#define CHAR_WIDTH 6
#define DISPLAY_RAM 8192
/////////////////////////////////////////////////////////////////////
//vary these according to your display connection
/////////////////////////////////////////////////////////////////////
#define SET_LCD_RESET (__PORTDD_bit.bit0 = 1)
#define CLEAR_LCD_RESET (__PORTDD_bit.bit0 = 0)
#define SET_LCD_CD (__PORTDD_bit.bit1 = 1)
#define CLEAR_LCD_CD (__PORTDD_bit.bit1 = 0)
#define SET_LCD_CE (__PORTDD_bit.bit2 = 1)
#define CLEAR_LCD_CE (__PORTDD_bit.bit2 = 0)
#define SET_LCD_RD (__PORTDD_bit.bit3 = 1)
#define CLEAR_LCD_RD (__PORTDD_bit.bit3 = 0)
#define SET_LCD_WR (__PORTDD_bit.bit4 = 1)
#define CLEAR_LCD_WR (__PORTDD_bit.bit4 = 0)
#define BUSDATI_OUT (__PORTBD)
#define BUSDATI_IN (__PORTBP)
#define BUSDATI_OUTPUT (__PORTBC = 0xFF)
#define BUSDATI_INPUT (__PORTBC = 0x00)
/////////////////////////////////////////////////////////////////////
//don't touch these!!!
/////////////////////////////////////////////////////////////////////
#define ROWS (PIXELS_Y / 8)
#define COLUMNS (PIXELS_X / CHAR_WIDTH)
#define CHARS_ROW ((PIXELS_X + CHAR_WIDTH -1) / CHAR_WIDTH)
#define GRAPHICS_HOME (DISPLAY_RAM - CHARS_ROW * ROWS * 8)
#define TEXT_HOME (GRAPHICS_HOME - CHARS_ROW * ROWS)
#define USER_RAM (DISPLAY_RAM - TEXT_HOME)
//current text cursor coordinates
unsigned char cursor_row = 0;
unsigned char cursor_col = 0;
//very quick & dirty wait routine
static void wait(unsigned int x)
{ unsigned int i;
x = x*10;
while (x > 0)
{
for (i=0; i<1000; i++)
{
};;
x--;
}
}
static void LCD_check_status(unsigned char mask)
{
BUSDATI_INPUT;
SET_LCD_CD;
CLEAR_LCD_RD;
CLEAR_LCD_CE;
/*wait 150 nS*/
asm("NOP");
while ( (BUSDATI_IN & mask) != mask)
{
SET_LCD_CE;
CLEAR_LCD_CE;
asm("NOP");
};
SET_LCD_CE;
SET_LCD_RD;
}
void LCD_data(unsigned char D1)
{
LCD_check_status(3);
BUSDATI_OUTPUT;
BUSDATI_OUT = D1;
CLEAR_LCD_CD;
CLEAR_LCD_WR;
CLEAR_LCD_CE;
/*implicit wait: 80nS*/
SET_LCD_CE;
SET_LCD_WR;
}
unsigned char LCD_read(void)
{ unsigned char retval;
LCD_check_status(3);
BUSDATI_INPUT;
CLEAR_LCD_CD;
CLEAR_LCD_RD;
CLEAR_LCD_CE;
/*implicit wait: 80nS*/
asm("NOP");
retval = BUSDATI_IN;
SET_LCD_CE;
SET_LCD_RD;
return retval;
}
void LCD_command(unsigned char command, unsigned char D1, unsigned char D2)
{
LCD_data(D1);
LCD_data(D2);
LCD_check_status(3);
BUSDATI_OUTPUT;
BUSDATI_OUT = command;
SET_LCD_CD;
CLEAR_LCD_WR;
CLEAR_LCD_CE;
/*implicit wait: 80nS*/
SET_LCD_CE;
SET_LCD_WR;
}
void LCD_initialize(void)
{
BUSDATI_INPUT;
SET_LCD_WR;
SET_LCD_RD;
SET_LCD_CD;
CLEAR_LCD_CE;
CLEAR_LCD_RESET;
// wait at least 10mS
wait(1);
SET_LCD_RESET;
SET_LCD_CE;
// wait at least 1 uS
wait(1);
LCD_command( SET_GRAPHIC_HOME_ADDRESS, GRAPHICS_HOME & 0xFF, GRAPHICS_HOME >> 8);
LCD_command( SET_GRAPHIC_COLUMNS, CHARS_ROW, 0);
LCD_command( SET_TEXT_HOME_ADDRESS, TEXT_HOME & 0xFF, TEXT_HOME >> 8);
LCD_command( SET_TEXT_COLUMNS, CHARS_ROW, 0);
LCD_command( SET_XOR_TEXT_GRAPHICS, 0, 0);
LCD_command( DISPLAY_ALL_ON, 0, 0);
LCD_clear_text();
LCD_clear_graphics();
}
void LCD_locate(unsigned char row, unsigned char col)
{ unsigned int address;
if (row >= ROWS) row = 0;
if (col >= CHARS_ROW) col = 0;
address = TEXT_HOME + row * CHARS_ROW + col;
LCD_command(SET_ADDRESS_POINTER, address & 0xFF, address >> 8);
cursor_row = row; cursor_col = col;
}
void LCD_putchar(unsigned char c)
{
LCD_locate(cursor_row, cursor_col);
switch(c)
{
case '\n': //on newline, clear to end of row
case '\r':
do
{
LCD_putchar(' ');
} while (cursor_col != 0);
break;
default:
LCD_command( DATA_WRITE_INCREMENT, 0, c - ' ');
if(++cursor_col == COLUMNS)
{
cursor_col = 0;
if (++cursor_row == ROWS)
cursor_row = 0;
LCD_locate(cursor_row, cursor_col);
};
break;
};
}
void LCD_puts(char * s)
{
while (*s)
LCD_putchar(*s++);
}
void LCD_clear_text(void)
{ unsigned char i;
LCD_command( SET_ADDRESS_POINTER, TEXT_HOME & 0xFF, TEXT_HOME >> 8);
for (i=0; i < ROWS * CHARS_ROW; i++)
{
LCD_command( DATA_WRITE_INCREMENT, 0, 0);
};
LCD_locate(0,0);
}
void LCD_clear_graphics(void)
{
unsigned int i;
LCD_command( SET_ADDRESS_POINTER, GRAPHICS_HOME & 0xFF, GRAPHICS_HOME >> 8);
for (i=0; i < ROWS * CHARS_ROW * 8; i++)
{
LCD_command( DATA_WRITE_INCREMENT, 0, 0);
};
}
// sets or clears the pixel at x,y according to 'command' (0=clear pixel)
void LCD_pset(unsigned char x, unsigned char y, unsigned char command)
{
unsigned int address = GRAPHICS_HOME + (unsigned int)(PIXELS_Y - y) * CHARS_ROW + x / CHAR_WIDTH;
command = ( command == 0 ? RESET_BIT : SET_BIT );
LCD_command( SET_ADDRESS_POINTER, address& 0xFF, address >> 8);
/*the bit position, left-to-right, is x % CHAR_WIDTH;
it is then subtracted from CHAR_WIDTH-1 to reverse direction to right-to-left*/
LCD_command( command | (CHAR_WIDTH - 1 - (x % CHAR_WIDTH)), 0, 0 );
}
void LCD_move_cursor(unsigned char row, unsigned char col)
{
LCD_command( SET_CURSOR_POSITION, col, row);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -