|
| 采购元器件好去处--维库电子市场网推荐 |
| 技术交流 | 电路欣赏 | 工控天地 | 数字广电 | 通信技术 | 电源技术 | 测控之家 | EMC技术 | ARM技术 | EDA技术 | PCB技术 | 嵌入式系统 驱动编程 | 集成电路 | 器件替换 | 模拟技术 | 新手园地 | 单 片 机 | DSP技术 | MCU技术 | IC 设计 | IC 产业 | CAN-bus/DeviceNe |
2行7位半汉字LCD模块WINAVR演示程序(菜鸟作) |
| 作者:hotpower 栏目:单片机 |
| 2行7位半汉字LCD模块WINAVR演示程序(菜鸟作) /*------------------------------------------------------------ HS12232-9带汉字库的2行7位半汉字LCD模块WINAVR演示程序 HotPower@126.com 2005.1.15 -------------------------------------------------------------*/ #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> #define FREQ 8 //Meaga8L,8MHZ #define CS PB2//LCD片选(串行) 0:禁止 1:允许 #define SID PB3//LCD输入串行数据(串行) #define CLK PB5//LCD输入串行脉冲(串行) #define SS PB2//LCD片选(串行) 0:禁止 1:允许 #define MOSI PB3//LCD输入串行数据(串行) #define SCK PB5//LCD输入串行脉冲(串行) void PortIoInit(void) { DDRB = 0;//设置B口全为输入 DDRC = 0;//设置C口全为输入 DDRD = 0;//设置D口全为输入 PORTB = 0xff;//设置B口全部上拉 PORTC = 0xff;//设置C口全部上拉 PORTD = 0xff;//设置D口全部上拉 } void SPI_MasterInit(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 SPI_MasterTransmit(unsigned CHAR cData) { /* 启动数据传输 */ SPDR = cData; /* 等待传输结束 */ while(!(SPSR & (1 << SPIF))); } void DelayMs(unsigned int t) { unsigned int i; for(i = 0; i < t; i++) _delay_loop_2(250 * FREQ); } /*-------------------------------------------------------- 发送8位LCD控制命令 --------------------------------------------------------*/ void LcdSendCommand(unsigned CHAR cCommand) { /*-------------------------------------------------------- 发送同步脉冲11111 WR(0) RS(0) 0发送顺序从左至右) --------------------------------------------------------*/ PORTB |= (1 << SS);//SS=1,启动SPI SPI_MasterTransmit(0xf8);//发送LCD控制命令 SPI_MasterTransmit(cCommand & 0xf0);//发送高4位LCD控制命令 SPI_MasterTransmit(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 LcdSendData(unsigned CHAR cData) { /*-------------------------------------------------------- 发送同步脉冲11111 WR(0) RS(0) 0发送顺序从左至右) --------------------------------------------------------*/ PORTB |= (1 << SS);//SS=1,启动SPI SPI_MasterTransmit(0xfa);//发送LCD显示数据 SPI_MasterTransmit(cData & 0xf0);//发送高4位LCD显示数据 SPI_MasterTransmit(cData << 4);//发送低4位LCD显示数据 PORTB &= ~(1 << SS);//SS=0,关闭SPI _delay_loop_2(72 * FREQ);//ST7920要求等待延时72uS } /*--------------------------------------------------- LCD初始化设置 ----------------------------------------------------*/ void LcdInit(void) { /*--------------------------------------------------- LCD模块上电等待延时 ----------------------------------------------------*/ DelayMs(1000);//上电等待延时1000Ms SPI_MasterInit();//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 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 LCDDISPLAY(unsigned CHAR row, unsigned CHAR col, unsigned CHAR * string) { if (SetLCDDISPLAYPos(row, col)) { LcdSendData(*string); } } void LCDDISPLAYString(unsigned CHAR * string) { while(*string) LcdSendData(*string ++); } //main程序 void main(void) { unsigned CHAR i = 0; PortIoInit(); LcdInit(); // sei(); for(;;) { DelayMs(1000);//上电等待延时1000Ms if ((i ++ & 0x01) == 0) LcdSendCommand(0b00000001);//发送清除显示命令 else { SetLCDDISPLAYPos(0, 1);//汉字定位到上行左端 LCDDISPLAYString("汉字显示演示"); SetLCDDISPLAYPos(1,0);//字符定位到下行左端 LCDDISPLAYString("123456789ABCDEF");//必须换行 SetLCDDISPLAYPos(1,3);//字符定位到下行左端 LCDDISPLAYString("汉字"); } DelayMs(1000);//上电等待延时1000Ms DelayMs(1000);//上电等待延时1000Ms DelayMs(1000);//上电等待延时1000Ms DelayMs(1000);//上电等待延时1000Ms } } |
| 2楼: | >>参与讨论 |
| 作者: hotpower 于 2005-1-16 23:28:00 发布:
HS12232-9带汉字库LCD模块WINAVR C++演示程序 /*------------------------------------------------------------ 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 } } |
|
| 3楼: | >>参与讨论 |
| 作者: hotpower 于 2005-1-16 23:32:00 发布:
刚用新下载的AVR Studio 4.11,C++可以源码调试 刚试了一下,C++可以进行源码调试(有些函数不太行)... 比较了WINAVR的C和C++生成的长度,C++还是比C的要长些... 我将LCDTEST.C改为LCDTEST.CPP编译后长度比为485:665. C++多用了180个字节... 看来只好先打消用C++的念头吧,玩玩了了心愿... |
|
| 4楼: | >>参与讨论 |
| 作者: hotpower 于 2005-1-17 13:02:00 发布:
修改2楼的bug及展示C++函数重载之风采... /*------------------------------------------------------------ HS12232-9带汉字库的2行7位半汉字LCD模块WINAVR C++演示程序 HotPower@126.com 2005.1.17 -------------------------------------------------------------*/ #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> #include <string.h> #include <stdlib.h> #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");//必须换行 Lc |
|
| 5楼: | >>参与讨论 |
| 作者: victorymay 于 2005-1-17 15:47:00 发布:
hello 楼主能否将"12232"与MEGA8的硬件接口电路贴出,我手边刚好也有"12232"一块 或发送*.sch文件 to mueua@21cn.com |
|
| 6楼: | >>参与讨论 |
| 作者: hotpower 于 2005-1-17 18:31:00 发布:
继续重载,所有LCD显示函数都使用一个函数名LCDDISPLAY() /*------------------------------------------------------------ HS12232-9带汉字库的2行7位半汉字LCD模块WINAVR C++演示程序 HotPower@126.com 2005.1.17 -------------------------------------------------------------*/ #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> #include <string.h> #include <stdlib.h> #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 LCDDISPLAY(unsigned CHAR, unsigned CHAR, const CHAR *); void LCDDISPLAY(const CHAR *); void LCDDISPLAY(CHAR); void LCDDISPLAY(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); /* 使能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) { row --; 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 + 1; col = LcdCol + 1; } void LcdSpiObj::LCDDISPLAY(unsigned CHAR row, unsigned CHAR col, const CHAR * string) { if (SetLCDDISPLAYPos(row, col)) LCDDISPLAY(string); } void LcdSpiObj::LCDDISPLAY(const CHAR * string) { while(*string) { LcdSendData(*string ++); LcdCol ++; } } void LcdSpiObj::LCDDISPLAY(CHAR Val) { CHAR str[4]; itoa((int)Val, (CHAR *)str, 10); LCDDISPLAY((CHAR *)str); } void LcdSpiObj::LCDDISPLAY(int Val) { CHAR str[6]; itoa(Val, (CHAR *)str, 10); LCDDISPLAY((CHAR *)str); } /*---------------------------------------------------------- 申请全局类对象LcdSpi.它封装了HS12232-9 LCD模块的基本函数组合 ----------------------------------------------------------*/ LcdSpiObj LcdSpi; //main程序 int main(void) { int i = 0; unsigned CHAR row, col; LcdSpi.LcdInit();//LCD初始化 LcdSpi.SetLCDDISPLAYPos(1, 2);//定位到第1行第2个汉字列上 LcdSpi.LCDDISPLAY("汉字显示演示");//在当前位置显示汉字串 // sei(); for(;;) {//死循环 /*-------------------------------------------------------------------- &n |
|
| 7楼: | >>参与讨论 |
| 作者: hotpower 于 2005-1-17 18:36:00 发布:
victorymay: 线路接的是M8L标准的SPI接口 一共用了3线(SS也可以不要,直接接高电平) #define SS PB2//LCD片选(串行) 0:禁止 1:允许 #define MOSI PB3//LCD输入串行数据(串行) #define SCK PB5//LCD输入串行脉冲(串行) |
|
| 8楼: | >>参与讨论 |
| 作者: hotpower 于 2005-1-17 22:42:00 发布:
适当声明为内联函数可以优化 适当声明为内联函数可以优化,但有些反而增大代码程度. 比较郁闷... 楼上.text=1004 .data=34 本例.text= 744 .data=34 inline LcdSpiObj::LcdSpiObj(void) { LcdRow = 0; LcdCol = 0; LcdSpiModeSetup(); } inline void LcdSpiObj::LcdSpiModeSetup(void) { /* 设置MOSI 和SCK 及SS 为输出,其他为输入 */ DDRB = (1 << MOSI) | (1 << SCK) | (1 << SS); PORTB = (1 << MOSI) | (1 << SCK) | (1 << SS); /* 使能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);//支持!!! } inline void LcdSpiObj::LcdSpiSend(unsigned CHAR cData) { /* 启动数据传输 */ SPDR = cData; /* 等待传输结束 */ while(!(SPSR & (1 << SPIF))); } inline 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显示数据 --------------------------------------------------------*/ inline 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初始化设置 ----------------------------------------------------*/ inline 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命令 } inline unsigned CHAR LcdSpiObj::SetLCDDISPLAYPos(unsigned CHAR row, unsigned CHAR col) { row --; 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; } inline void LcdSpiObj::GetLCDDISPLAYPos(unsigned CHAR &row, unsigned CHAR &col) { row = LcdRow + 1; col = LcdCol + 1; } inline void LcdSpiObj::LCDDISPLAY(unsigned CHAR row, unsigned CHAR col, const CHAR * string) { if (SetLCDDISPLAYPos(row, col)) LCDDISPLAY(string); } void LcdSpiObj::LCDDISPLAY(const CHAR * string)//内联反而增大代码长度 { while(*string) { LcdSendData(*string ++); LcdCol ++; } } inline void LcdSpiObj::LCDDISPLAY(CHAR Val) { CHAR str[4]; itoa((int)Val, (CHAR *)str, 10); LCDDISPLAY((CHAR *)str); } inline void LcdSpiObj::LCDDISPLAY(int Val) { CHAR str[6]; itoa(Val, (CHAR *)str, 10); LCDDISPLAY((CHAR *)str); } |
|
| 9楼: | >>参与讨论 |
| 作者: jacksmart 于 2005-1-18 10:57:00 发布:
强人,学习! |
|
| 10楼: | >>参与讨论 |
| 作者: rongxiang 于 2005-1-19 12:42:00 发布:
能不能提供一个C51的HS12232-9带汉字库LCD模块演示程序-谢了 |
|
| 11楼: | >>参与讨论 |
| 作者: hotpower 于 2005-1-19 13:06:00 发布:
这里有一个商家提供我注解的51asm源程序 ;This program is for 12232F,12864-12,12864M Serial TEST.html">TEST ; RS--------P3.0 ; R/W-------P3.1 ; E---------P3.2 ; DB0~7-----P1 CS EQU P3.0;片选(串行) 0:禁止 1:允许 SID EQU P3.1;输入串行数据(串行) CLK EQU P3.2;输入串行脉冲(串行) PSB EQU P3.3;控制界面 0:串行 1:并行8/4 位(HS12232-9无用) ORG 0000H AJMP START ; ORG 0003H ; LCALL PAUSE ORG 0100h START: ; MOV IE,#81H ;EXT. INT0 PERMIT ; MOV IP,#01H ;INT0 IS FIRST INT. LEVEL ; MOV TCON,#00H ;TIMER/COUNTER CONTROLER INIT. MOV SP, #67H CLR PSB;选择串行工作模式 LCALL DELAY;延时150mS LCALL DELAY;延时150mS LCALL SETUP;LCD初始化设置 LCALL DEF_CHAR;自定义字符显示 /*--------------------------------------------------- 显示4行CGRAM1字符 ----------------------------------------------------*/ MOV A,#80H LCALL WRITE_COM;发送设定DDRAM地址0x00命令 /*--------------------------------------------------- 显示第一行CGRAM1字符 ----------------------------------------------------*/ MOV R3,#8 TEST11: MOV DPTR,#CGRAM1 ;CGRAM TEST LCALL WRITE_CGRAM DJNZ R3,TEST11 MOV A,#90H LCALL WRITE_COM;发送设定DDRAM地址0x10命令 /*--------------------------------------------------- 显示第二行CGRAM1字符 ----------------------------------------------------*/ MOV R3,#8 TEST12: MOV DPTR,#CGRAM1 LCALL WRITE_CGRAM DJNZ R3,TEST12 MOV A,#88H LCALL WRITE_COM;发送设定DDRAM地址0x08命令 /*--------------------------------------------------- 显示第三行CGRAM1字符 ----------------------------------------------------*/ MOV R3,#8 TEST13: MOV DPTR,#CGRAM1 LCALL WRITE_CGRAM DJNZ R3,TEST13 MOV A,#98H LCALL WRITE_COM;发送设定DDRAM地址0x18命令 /*--------------------------------------------------- 显示第四行CGRAM1字符 ----------------------------------------------------*/ MOV R3,#8 TEST14: MOV DPTR,#CGRAM1 LCALL WRITE_CGRAM DJNZ R3,TEST14 /*--------------------------------------------------- CGRAM1字符显示等待延时5秒 ----------------------------------------------------*/ LCALL DELAY;延时150mS LCALL DELAY;延时150mS LCALL DELAY;延时150mS LCALL DELAY;延时150mS LCALL DELAY;延时150mS /*--------------------------------------------------- 显示4行CGRAM2字符 ----------------------------------------------------*/ MOV A,#80H LCALL WRITE_COM;发送设定DDRAM地址0x00命令 /*--------------------------------------------------- 显示第一行CGRAM2字符 ----------------------------------------------------*/ MOV R3,#8 TEST21: MOV DPTR,#CGRAM2 LCALL WRITE_CGRAM DJNZ R3,TEST21 MOV A,#90H LCALL WRITE_COM;发送设定DDRAM地址0x10命令 /*--------------------------------------------------- 显示第二行CGRAM2字符 ----------------------------------------------------*/ MOV R3,#8 TEST22: MOV DPTR,#CGRAM2 LCALL WRITE_CGRAM DJNZ R3,TEST22 MOV A,#88H LCALL WRITE_COM;发送设定DDRAM地址0x08命令 /*--------------------------------------------------- 显示第三行CGRAM2字符 ----------------------------------------------------*/ MOV R3,#8 TEST23: MOV DPTR,#CGRAM2 LCALL WRITE_CGRAM DJNZ R3,TEST23 MOV A,#98H LCALL WRITE_COM;发送设定DDRAM地址0x18命令 /*--------------------------------------------------- 显示第四行CGRAM2字符 ----------------------------------------------------*/ MOV R3,#8 TEST24: MOV DPTR,#CGRAM2 LCALL WRITE_CGRAM DJNZ R3,TEST24 /*--------------------------------------------------- CGRAM2字符显示等待延时 ----------------------------------------------------*/ LCALL DELAY;延时150mS LCALL DELAY;延时150mS LCALL DELAY;延时150mS LCALL DELAY;延时150mS LCALL DELAY;延时150mS /*--------------------------------------------------- 显示4行CGRAM3字符 ----------------------------------------------------*/ MOV A,#80H LCALL WRITE_COM;发送设定DDRAM地址0x00命令 /*--------------------------------------------------- 显示第一行CGRAM3字符 ----------------------------------------------------*/ MOV R3,#8 TEST31: MOV DPTR,#CGRAM3 LCALL WRITE_CGRAM DJNZ R3,TEST31 MOV A,#90H LCALL WRITE_COM;发送设定DDRAM地址0x10命令 /*--------------------------------------------------- 显示第二行CGRAM3字符 ----------------------------------------------------*/ MOV R3,#8 TEST32: MOV   |
|
| 12楼: | >>参与讨论 |
| 作者: hotpower 于 2005-1-20 7:24:00 发布:
HS12232-9并非遵守完整的SPI协议 HS12232-9并非遵守完整的SPI协议,片选先CS(SS)可以直接接高电平,这样实际只需2线(时钟SCK和数据MOSI). 串行接法的缺点是不能读出LCD信息,不过也不是最重要的,重要的是连线最少才是真... |
|
| 13楼: | >>参与讨论 |
| 作者: st_z 于 2005-1-21 10:40:00 发布:
兄台确实很强 佩服! |
|
| 14楼: | >>参与讨论 |
| 作者: hotpower 于 2005-1-27 7:25:00 发布:
12232-9/12864通用程序 只需改写SetLcdDisplayPos()函数即可实现12232-9/12864通用. 注意12232-9 J2的跳线和12864PSB接地将硬件设置为串行方式. inline unsigned CHAR LcdSpiObj::SetLcdDisplayPos(unsigned CHAR row, unsigned CHAR col) { row --; col --; if ((row < 4) && (col < 8)) {//汉字字符为4行8列(汉字必须偶数对齐) LcdSendCommand(0x80 + (row & 1) * 16 + (row >> 1) * 8 + col LcdRow = row; LcdCol = col << 1; return 1; } else return 0; } //main程序 int main(void) { LcdSpi.SetLcdDisplayPos(4, 1);//定位到第4行第1个汉字列上 LcdSpi.LcdDisplay("04汉字显示演示04");//在当前位置显示汉字串 //............................................. return 0;//正常返回操作系统(实际不可能,MCU一般也不需要) } |
|
|
|
| 免费注册为维库电子开发网会员,参与电子工程师社区讨论,点此进入 |
Copyright © 1998-2006 www.dzsc.com 浙ICP证030469号 |