[资料分享] HS12232-9带汉字库的2行7位半汉字LCD模块WINAVR C++演示程序

zfbipt   2008-7-1 09:54 楼主
/*------------------------------------------------------------
    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);
};

回复评论 (2)

回复 楼主 的帖子

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);
}
点赞  2008-7-1 09:54

回复 沙发 的帖子

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;
}
点赞  2008-7-1 09:55
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复