原创 学做万年历(1)——LCD1602

2009-1-16 13:25 2819 12 13 分类: MCU/ 嵌入式

最近闲来无事,想做个万年历,它的主要元件是DS1302和LCD1602显示,到目前为止,LCD1602显示已经完成,DS1302还在编写,现在就把编写的思路描述一下。


 


本文采用的是8位数据口,首先是对端口和功能设置的初始化,这里主要是参考数据手册,完成功能设置。


//--------数据端口-------------
#define LCD_DATA_DDR   DDRA
#define LCD_DO                 PORTA
#define LCD_DI                  PINA


//--------控制端口-------------
#define LCD_CTRL_DDR   DDRB
#define LCD_CTRL            PORTB
#define LCD_RS                 PB0
#define LCD_RW                PB1
#define LCD_EN                 PB2


#define LCD_SET_RS       LCD_CTRL|=1<<LCD_RS
#define LCD_SET_RW      LCD_CTRL|=1<<LCD_RW
#define LCD_SET_EN       LCD_CTRL|=1<<LCD_EN
#define LCD_CLR_RS       LCD_CTRL&=~(1<<LCD_RS)
#define LCD_CLR_RW      LCD_CTRL&=~(1<<LCD_RW)
#define LCD_CLR_EN       LCD_CTRL&=~(1<<LCD_EN)


//--------------------初始化设置----------------------
#define iDat   1
#define iCmd   0


//L L H DL N F  DL:1--8,0--4;N:1--2行,0--1行;F:1--5*10,0--5*7
#define LCD_FUNCTION  0x38
#define LCD_CLS       0x01 //清屏
#define LCD_HOME      0x02 //地址返回原点,不改变DDRAM内容
//L L L L L H I/D S  I/D:1--增量方式,0--减量方式;S:1--屏幕移动,0--屏幕不移动
#define LCD_ENTRY     0x06
//L L L H S/C R/L L L
#define LCD_C2L       0x10 //光标左移
#define LCD_C2R       0x14 //光标右移
#define LCD_S2L       0x18 //屏幕左移
#define LCD_S2R       0x1C //屏幕右移
//L L L L 1 D C B   D:1--开显示,0--关显示;C:1--显示光标,0--不显光标;B:1--光标闪烁,0--光标不闪
#define LCD_ON        0x0C
#define LCD_OFF       0x08
#define LCD_CURON     0x0E
#define LCD_CURFLA    0x0F


#define LCD_L1  0x80 //第一行的地址:0x80+addr ,addr为列数
#define LCD_L2  0xC0 //第二行的地址:0x80+0x40+addr


功能函数主要包括读写,检测状态,LCD初始化等。相应的延迟函数也是必须的,这里就不详说。在读操作完成后必须将端口设置为输出,判断LCD是否忙这个也是必须的。


/*******************************************
函数名称: readbyte
功    能: 从1602液晶读出一个字节数据或者指令
参    数: DatCmd--为iDat时是数据,为iCmd时是指令
返回值  : dbyte--读回的数据或者指令
********************************************/
uchar readbyte(uchar DatCmd)
{
  uchar dbyte;
  if(DatCmd==iDat)
    LCD_SET_RS;
  else
    LCD_CLR_RS;
  LCD_SET_RW;
  LCD_SET_EN;
  LCD_DATA_DDR=0x00; //设置端口为输入
  dbyte="LCD"_DI;
  Delayms(1);
  LCD_CLR_EN;
  LCD_DATA_DDR|=0xFF;  //数据总线还原为输出,这个是必须的
  return dbyte;
}
/*******************************************
函数名称: writebyte
功    能: 向1602液晶写入一个字节数据或者指令
参    数: DatCmd--为iDat时是数据,为iCmd时是指令
      dbyte--为写入1602的数据或者指令
返回值  : 无
********************************************/
void writebyte(uchar DatCmd,uchar dbyte)
{
  if(DatCmd==iDat)
    LCD_SET_RS;
  else
    LCD_CLR_RS;
  LCD_CLR_RW;
  LCD_SET_EN;
  LCD_DO=dbyte;
  Delayms(1);
  LCD_CLR_EN;
}


/*******************************************
函数名称: writestr
功    能: 向1602液晶写入一个字符串
参    数: pstr--字符串指针
返回值  : 无
********************************************/
void writestr(uchar *pstr)
{
  while((*pstr)!='\0')
    writebyte(iDat,*pstr++);
}
/*******************************************
函数名称: readbusy
功    能: 检测1602液晶是否忙
参    数: 无
返回值  : busy--为1时是忙状态,为0时可以接收指令
********************************************/
uchar readbusy(void)
{
  uchar busy;
  busy="readbyte"(iCmd);
  if(busy&0x80)
    busy="1";
  else
    busy="0";
  return busy;
}


/*******************************************
函数名称: lcd_clear
功    能: 1602液晶清屏
参    数: 无
返回值  : 无
********************************************/
void lcd_clear(void)
{
  writebyte(iCmd,LCD_CLS);//写入清屏指令
  Delayms(2);// 清屏指令写入后,2ms 的延时是很必要的!!!
}
/*******************************************
函数名称: lcd_gotoXY
功    能: 移动到指定位置
参    数: Row--指定的行
   Col--指定的列
返回值  : 无
********************************************/
void lcd_gotoXY(uchar Row, uchar Col)
{
  switch (Row)    //选择行
  {
  case 2:
    writebyte(iCmd, LCD_L2 + Col); break; //写入第2行的指定列 
  default:
    writebyte(iCmd, LCD_L1 + Col); break; //写入第1行的指定列 
  }
}
/*******************************************
函数名称: lcd_init
功    能: 1602液晶初始化
参    数: 无
返回值  : 无
********************************************/
void lcd_init(void)
{
  Delayms(100);
  LCD_CTRL_DDR|=(1<<LCD_RS)|(1<<LCD_RW)|(1<<LCD_EN);
  LCD_DATA_DDR=0xFF;
 
  writebyte(iCmd,LCD_FUNCTION);
  while(readbusy());
  writebyte(iCmd,LCD_ON);
  while(readbusy());
  lcd_clear();
  while(readbusy());
  writebyte(iCmd,LCD_ENTRY);
}


将清屏功能拿出来设置是为了方便控制LCD。虽然程序只完成简单的功能,但是我觉得比较好理解。故在使用到LCD1602液晶时可以当作模板。

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户1518700 2009-1-23 10:26

支持您,新年好啊\(^o^)/~
相关推荐阅读
用户1513083 2009-07-14 14:52
ucos2.86在44b0上移植问题
程序使用从ucos主页上下载的最新ucos2.86和开发板的启动代码,但是怎么也得不到想要的结果,main.c应用程序中利用ucos2系统提供函数创建的3个任务本来应该循环得到调度的,但却均只被调度一...
用户1513083 2009-06-11 19:47
气晕了
今天四点从实验室出来直奔邮局,到了大厅,说挂号,告诉我到那边买信封。我写好后,给她,他在电子秤上称了一下,给我5.4元的邮票。我就到对面去贴邮票,贴好后我就投进去了,现在才发现,原来没有挂号成。突然想...
用户1513083 2009-05-31 21:29
心已决
拿一年的时间来分手已经很长了,应该考虑清楚了,这一年里,我完全变了,最明显的就是自己静不下来学习,自己都讨厌自己,累了,身心疲惫,为何要如此折磨,已经没有信任了,又何必再让别人伤心流泪。我现在这样是对...
用户1513083 2009-05-12 12:14
MCU和CPLD实现VGA图像显示可行否
请问各位一个问题。我手上有块CPLD板EPM3256,板上没有SRAM,所以只是实现了VGA接口横条、竖条和棋盘格显示,汉字也就只能显示设定好的。我手上还有一块自己做的ATmega128,上面外扩了3...
用户1513083 2009-05-10 20:11
累呀
觉得自己很累,很累。摸不清自己的方向,应该多和人交流交流。从去年七月份出了点问题后,总感觉自己不在状态,不能很好的静下心来,个人问题没处理好,搞得自己很狼狈,最近一阶段自己学习,感觉好像懂了,其实真正...
用户1513083 2009-04-28 22:05
有点开小差
感觉最近一个星期学习的效果不理想,有点不在状态,有点没有方向不知该学些什么,学的很累,要好好调整一下,我觉得只要问题还是自己闭门造车,没有人可以交流。总的来说,就是在做UCOS移植,其实UCOS我去年...
EE直播间
更多
我要评论
1
12
关闭 站长推荐上一条 /3 下一条