|
/*------------------------------------------------------------ HS12232-9带汉字库的2行7位半汉字LCD模块WINAVR C++演示程序 HotPower@126.com 2005.1.16 -------------------------------------------------------------*/
#include <inttypes.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> #include <avr/wdt.h> #include <avr/ina90.h> #include <avr/eeprom.h> //#include <stdio.h> #include <avr/delay.h> #include <avr/io.h> #include <avr/delay.h>
#define FREQ 8 //Meaga8L,8MHz
#define SS PB2//LCD片选(串行) 0:禁止 1:允许 #define MOSI PB3//LCD输入串行数据(串行) #define SCK PB5//LCD输入串行脉冲(串行)
class LcdSpiObj { public: LcdSpiObj(void); public: void LcdSpiModeSetup(void); 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 LcdDisplay(unsigned char, unsigned char, const char *); void LcdDisplayString(const char *); };
LcdSpiObj::LcdSpiObj(void) { 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命令 return 1; } else return 0; }
void LcdSpiObj::LcdDisplay(unsigned char row, unsigned char col, const char * string) { if (SetLcdDisplayPos(row, col)) { LcdSendData(*string); } }
void LcdSpiObj::LcdDisplayString(const char * string) { while(*string) LcdSendData(*string ++); }
LcdSpiObj LcdSpi;
//main程序 int main(void) { unsigned char i = 0; LcdSpi.LcdInit(); // sei(); for(;;) { LcdSpi.LcdSpiDelayMs(1000);//上电等待延时1000Ms if ((i ++ & 0x01) == 0) LcdSpi.LcdSendCommand(0b00000001);//发送清除显示命令 else { LcdSpi.SetLcdDisplayPos(0, 1);//汉字定位到上行左端 LcdSpi.LcdDisplayString("汉字显示演示"); LcdSpi.SetLcdDisplayPos(1,0);//字符定位到下行左端 LcdSpi.LcdDisplayString("123456789ABCDEF");//必须换行 LcdSpi.SetLcdDisplayPos(1,3);//字符定位到下行左端 LcdSpi.LcdDisplayString("汉字"); } LcdSpi.LcdSpiDelayMs(1000);//上电等待延时1000Ms LcdSpi.LcdSpiDelayMs(1000);//上电等待延时1000Ms LcdSpi.LcdSpiDelayMs(1000);//上电等待延时1000Ms LcdSpi.LcdSpiDelayMs(1000);//上电等待延时1000Ms } }
|