/*------------------------------------------------------------
HS12232-9带汉字库的2行7位半汉字LCD模块WINAVR C++演示程序
HotPower@126.com 2005.1.17
-------------------------------------------------------------*/
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#include
#include
#include
#define FREQ 8 //Meaga8L,8MHz
#define SS PB2//LCD片选(串行) 0:禁止 1:允许
#define MOSI PB3//LCD输入串行数据(串行)
#define SCK PB5//LCD输入串行脉冲(串行)
class LcdSpiObj {
private:
unsigned char LcdRow,LcdCol;
void LcdSpiModeSetup(void);
public:
LcdSpiObj(void);//LcdSpiObj的构造函数
void LcdSpiSend(unsigned char);
void LcdSpiDelayMs(unsigned int);
void LcdInit(void);
void LcdSendCommand(unsigned char);
void LcdSendData(unsigned char);
unsigned char SetLcdDisplayPos(unsigned char, unsigned char);
void GetLcdDisplayPos(unsigned char &, unsigned char &);
void LcdDisplayPos(unsigned char, unsigned char, const char *);
void LcdDisplayString(const char *);
void LcdDisplayNumber(char);
void LcdDisplayNumber(int);
};
回复 楼主 的帖子
LcdSpiObj::LcdSpiObj(void)
{
LcdRow = 0;
LcdCol = 0;
LcdSpiModeSetup();
}
void LcdSpiObj::LcdSpiModeSetup(void)
{
/* 设置MOSI 和SCK 及SS 为输出,其他为输入 */
DDRB = (1 << MOSI) | (1 << SCK) | (1 << SS);
PORTB = (1 << MOSI) | (1 << SCK) | (1 << SS);
// PORTB = 0xff;
/* 使能SPI 主机模式,设置时钟速率为fck/16 ,SPI方式0*/
// SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);//不支持!!!
/* 使能SPI 主机模式,设置时钟速率为fck/16 ,SPI方式1*/
// SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPHA) | (1 << SPR0);//支持!!!
/* 使能SPI 主机模式,设置时钟速率为fck/16 ,SPI方式2*/
// SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL) | (1 << SPR0);//不支持!!!
/* 使能SPI 主机模式,设置时钟速率为fck/16 ,SPI方式3*/
SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL) | (1 << CPHA) | (1 << SPR0);//支持!!!
}
void LcdSpiObj::LcdSpiSend(unsigned char cData)
{
/* 启动数据传输 */
SPDR = cData;
/* 等待传输结束 */
while(!(SPSR & (1 << SPIF)));
}
void LcdSpiObj::LcdSpiDelayMs(unsigned int t)
{
unsigned int i;
for(i = 0; i < t; i++)
_delay_loop_2(250 * FREQ);
}
/*--------------------------------------------------------
发送8位LCD控制命令
--------------------------------------------------------*/
void LcdSpiObj::LcdSendCommand(unsigned char cCommand)
{
/*--------------------------------------------------------
发送同步脉冲11111 WR(0) RS(0) 0发送顺序从左至右)
--------------------------------------------------------*/
PORTB |= (1 << SS);//SS=1,启动SPI
LcdSpiSend(0xf8);//发送LCD控制命令
LcdSpiSend(cCommand & 0xf0);//发送高4位LCD控制命令
LcdSpiSend(cCommand << 4);//发送低4位LCD控制命令
PORTB &= ~(1 << SS);//SS=0,关闭SPI
if (cCommand == 0x01) _delay_loop_2(1600 * FREQ);//1.6mS
else _delay_loop_2(72 * FREQ);//st7920要求等待72uS
}
/*--------------------------------------------------------
发送8位LCD显示数据
--------------------------------------------------------*/
void LcdSpiObj::LcdSendData(unsigned char cData)
{
/*--------------------------------------------------------
发送同步脉冲11111 WR(0) RS(0) 0发送顺序从左至右)
--------------------------------------------------------*/
PORTB |= (1 << SS);//SS=1,启动SPI
LcdSpiSend(0xfa);//发送LCD显示数据
LcdSpiSend(cData & 0xf0);//发送高4位LCD显示数据
LcdSpiSend(cData << 4);//发送低4位LCD显示数据
PORTB &= ~(1 << SS);//SS=0,关闭SPI
_delay_loop_2(72 * FREQ);//st7920要求等待延时72uS
}
/*---------------------------------------------------
LCD初始化设置
----------------------------------------------------*/
void LcdSpiObj::LcdInit(void)
{
/*---------------------------------------------------
LCD模块上电等待延时
----------------------------------------------------*/
LcdSpiDelayMs(1000);//上电等待延时1000Ms
LcdSpiModeSetup();//SPI初始化
LcdSendCommand(0b00100000);//发送4位控制命令
// LcdSendCommand(0b00110000);//发送8位控制命令//与8位4位无关!!!
LcdSendCommand(0b00000010);//发送位址归位命令,设定DDRAM位址计数器为0
LcdSendCommand(0b00000100);//发送进入点命令
LcdSendCommand(0b00001100);//发送开显示关光标命令
LcdSendCommand(0b00000001);//发送清除显示命令
LcdSendCommand(0b10000000);//发送设定DDRAM地址0x00命令
}
unsigned char LcdSpiObj::SetLcdDisplayPos(unsigned char row, unsigned char col)
{
if ((row < 2) && (col < 8)) {//汉字字符为2行7.5列(汉字必须偶数对齐)
LcdSendCommand(0x80 + row * 16 + col);//发送设定DDRAM地址row * 16 + col命令
LcdRow = row;
LcdCol = col << 1;
return 1;
}
else
return 0;
}
void LcdSpiObj::GetLcdDisplayPos(unsigned char &row, unsigned char &col)
{
row = LcdRow;
col = LcdCol;
}
void LcdSpiObj::LcdDisplayPos(unsigned char row, unsigned char col, const char * string)
{
if (SetLcdDisplayPos(row, col)) LcdDisplayString(string);
}
回复 沙发 的帖子
void LcdSpiObj::LcdDisplayString(const char * string)
{
while(*string) {
LcdSendData(*string ++);
LcdCol ++;
}
}
//注意下列2个函数(函数重载)
void LcdSpiObj::LcdDisplayNumber(char Val)
{
char str[4];
itoa((int)Val, (char *)str, 10);
LcdDisplayString((char *)str);
}
void LcdSpiObj::LcdDisplayNumber(int Val)
{
char str[6];
itoa(Val, (char *)str, 10);
LcdDisplayString((char *)str);
}
LcdSpiObj LcdSpi;
//main程序
int main(void)
{
unsigned int i = 0;
unsigned char row, col;
LcdSpi.LcdInit();
LcdSpi.SetLcdDisplayPos(0, 1);//汉字定位到上行左端
LcdSpi.LcdDisplayString("汉字显示演示");
// sei();
for(;;) {
LcdSpi.LcdSpiDelayMs(1000);//上电等待延时1000Ms
LcdSpi.SetLcdDisplayPos(1,0);//字符定位到下行左端
LcdSpi.LcdDisplayString("123456789ABCDEF");//必须换行
LcdSpi.LcdDisplayPos(1, 4, "汉字");
LcdSpi.GetLcdDisplayPos(row, col);//解除C语言的&row,&col之烦恼
LcdSpi.SetLcdDisplayPos(1, 6);
LcdSpi.LcdDisplayNumber(row);//字节型数字(0~255)
LcdSpi.LcdDisplayNumber(col);
LcdSpi.SetLcdDisplayPos(1, 0);
LcdSpi.LcdDisplayNumber(i ++);//字型数字(0~65535)
}
return 0;
}