📄 c51程序-fm1602液晶底层驱动程序.txt
字号:
/*******************************************************************************
* 本程序是用51单片机的定时器模拟时钟,并且在1602液晶上显示
*
* 本程序名:timer-lcd.C
* 本程序完成时间:2009年6月20日
* 程序设计:sdyzxue
*******************************************************************************/
#define LCD1602
#include <stc.h>
#include <intrins.h>
#include <absacc.h>
#include <string.h>
/*******************************************************************************
* 本程序使用单片机为STC89C52,晶体频率:11.0592
* 定时器时长:20ms
* 各sfr定义如下:
*******************************************************************************/
sbit LCD_RS = P2^1;
sbit LCD_RW = P2^2;
sbit LCD_EN = P2^0;
sbit LCD_BL = P2^3; //液晶背光控制
sbit LCD_RST = P2^5; //12864液晶复位引脚
sbit LCD_CS1 = P2^7; //12864液晶左半屏片选
sbit LCD_CS2 = P2^6; //12864液晶右半屏片选
sbit LED1 = P1^2; //500ms定时监测LED
sbit LED2 = P1^3; //1s定时监测LED
sbit BEE = P2^4; //beep
#define ClearWatchdog WDT_CONTR = 0x3d //STC单片机软件喂狗
#define LCDDataBus P0
#define BUSY 0x80 //液晶忙标志
#define NNOP(); (_nop_();_nop_();_nop_();_nop_();_nop_();_nop_())
#define AnyNop(); _nop_();_nop_();_nop_();_nop_()
typedef bit bool;
#define TH2_ 0xb8
#define TL2_ 0x63
#define T20MS 0xb863
#define OpenLcdBL() LCD_BL = 0; //液晶背光开
#define CloseLcdBL() LCD_BL = 1; //液晶背光关
/*******************************************************************************
*宏定义部分
*******************************************************************************/
#define INT8U unsigned char
#define INT8 char
#define INT16U unsigned int
#define INT16 int
#define INT32U unsigned long
#define INT32 long
/*******************************************************************************
* 本程序的重点试验部分,结构体
* 结构体内涵盖有 年月日时分秒,定时器使用的标志等
* 说明:
* 参数:
*******************************************************************************/
typedef struct
{
INT8U Sec;
INT8U Min;
INT8U Hour;
INT8U Day;
INT8U Week;
INT8U Month;
INT8U Year;
}TIME;
TIME xdata TimeVal;
typedef struct
{
INT8U Flag;
INT8U TimeWork;
INT8U LcdFlag;
INT8U LcdWork;
INT8U LedWork;
INT8U LcdWorkTimes;
}TIMER;
TIMER xdata Cnt;
typedef struct
{
INT8U BeepCnt;
INT8U BeepCntBak;
INT8U BeepTims;
INT8U SpkFlag;
}BEEPCTR;
BEEPCTR xdata BeepCtr;
/*******************************************************************************
* 本程序使用到的显示星期数组 指针*DData
*******************************************************************************/
INT8U code Dis1[]= {"Mon.1 "};
INT8U code Dis2[]= {"Tues.2 "};
INT8U code Dis3[]= {"Wed.3 "};
INT8U code Dis4[]= {"Thurs.4"};
INT8U code Dis5[]= {"Friday5"};
INT8U code Dis6[]= {"Sat.6 "};
INT8U code Dis7[]= {"Sun.7 "};
/*******************************************************************************
* 本程序使用到的函数声明
*******************************************************************************/
void Config(void);
void DelayMs(INT16U k);
void InitVal(void);
bool LCD_BZ(void);
void WriteCommandLCD(INT8U WCLCD);
void WriteDataLCD(INT8U WDLCD);
void LCD_Init(void);
void DisplayOneChar(INT8U X,INT8U Y,INT8U DData);
void DisplayListChar(INT8U X,INT8U Y,INT8U code *DData);
void Timer_Init(void);
void DisplayTimer(void);
void SpkDly(void);
void Beep(INT8U x);
void DisplayWeek(INT8U W);
/*******************************************************************************
* 函数原型: void main(void) 主函数
* 功能:
* 说明:所有任务都采用定时器查询
* 参数:
*******************************************************************************/
void main(void)
{
Config();
while(1)
{
if(Cnt.Flag)
{
Cnt.Flag = 0;
TimeVal.Sec++;
if(TimeVal.Sec>=60)
{
TimeVal.Sec = 0;
TimeVal.Min++;
if(TimeVal.Min>=60)
{
TimeVal.Min = 0;
TimeVal.Hour++;
if(TimeVal.Hour>=24)
{
TimeVal.Hour = 0;
TimeVal.Week++;
if(TimeVal.Week>=6)
{
TimeVal.Week= 0;
}
}
}
}
}
if(Cnt.LcdFlag)
{
Cnt.LcdFlag = 0;
DisplayTimer();
}
}
}
/*******************************************************************************
* 函数原型:void Config(void)
* 功能:单片机的配置文件
* 说明:各个寄存器的配置,清内存,配置串口,初始化全局变量
* 参数:
* 使用的临时变量:INT16U itemp
*******************************************************************************/
void Config(void)
{
INT16U itemp;
DelayMs(400);
EA = 0;
DelayMs(100);
WDT_CONTR = 0x3d; //初始化内部看门狗
P0 = 0xff;
P1 = 0xff;
P2 = 0xff;
P3 = 0xff;
OpenLcdBL();
AUXR = 0x01; //使用片内RAM,禁止ALE输出
ClearWatchdog;
//清空片内RAM
for(itemp=0;itemp<1024;itemp++)
{
XBYTE[itemp] = 0x00;
}
ClearWatchdog;
IE = 0x70;
TCON = 0;
TMOD = 0x25;
T2CON = 0x00;
TH2 = TH2_;
TL2 = TL2_;
RCAP2H = TH2_;
RCAP2L = TL2_;
T2MOD = 0;
SCON = 0x50;
IP = 0x40;
TH1 = 0xfd;
TL1 = 0xfd;
TH0 = 0xb8;
TL0 = 0x63;
InitVal();
#ifdef LCD1602
DelayMs(20);
LCD_Init();
DelayMs(20);
#endif
TR0 = 1;
TR1 = 1;
TR2 = 1;
DelayMs(10);
EA = 1;
OpenLcdBL();
Beep(0);
}
/*******************************************************************************
* 函数原型:void DelayMs(INT16U k)
* 功能:不精确的延时函数
* 说明:11.0592MHz晶体下,实现1毫秒延时
* 参数:入口参数 INT16U k毫秒
* 局部变量:INT8U i
*******************************************************************************/
void DelayMs(INT16U k)
{
INT8U i;
while(k--)
{
for(i=0;i<250;i++)
{
AnyNop();
}
}
}
/*******************************************************************************
* 函数原型:void Timer2(void) interrupt 5
* 功能: 系统查询使用定时器
* 说明: 定时时长20ms,TF2=0,清溢出标志
* 参数:
*******************************************************************************/
void Timer2(void) interrupt 5
{
TF2 = 0;
LED1 = ~LED1; //监测定时器T2
ClearWatchdog;
SpkDly(); //蜂鸣器
Cnt.TimeWork++; //定时走时
if(Cnt.TimeWork%50==0)
{
Cnt.TimeWork = 0;
Cnt.Flag = 1;
}
Cnt.LcdWork++; //刷屏
if(Cnt.LcdWork%25==0)
{
Cnt.LcdWork = 0;
Cnt.LcdFlag = 1;
}
Cnt.LedWork++; //1S定时闪烁
if(Cnt.LedWork%50==0)
{
Cnt.LedWork = 0;
LED2 = 0;
}
else{LED2 = 1;}
Cnt.LcdWorkTimes++;
if(Cnt.LcdWorkTimes>=750)
CloseLcdBL();
}
/*******************************************************************************
* 函数原型:void InitVal(void)
* 功能: 初始化全局变量
* 说明:
* 参数:
*******************************************************************************/
void InitVal(void)
{
Cnt.LcdWorkTimes = 0;
Cnt.LedWork = 0;
Timer_Init(); //初始化时间数组
Cnt.Flag = 0;
Cnt.TimeWork = 0;
Cnt.LcdWork = 0;
Cnt.LcdFlag = 0;
}
/*******************************************************************************
* 函数原型:void Uart(void) interrupt 4
* 功能: 串行口的接收与发送
* 说明: 波特率9600X2,用定时器1产生波特率
* 参数:
*******************************************************************************/
void Uart(void) interrupt 4
{
if(RI)
{
RI = 0;
}
else{
TI = 0;
}
}
/*******************************************************************************
* 函数原型:bool LCD_BZ(void)
* 功能: 检测液晶忙标志
* 说明: bool=1表示忙,0为不忙
* 参数: 临时变量result
*******************************************************************************/
bool LCD_BZ(void)
{
bool result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
AnyNop();
result = (bool)(LCDDataBus & 0x80);
LCD_EN = 0;
return result;
}
/*******************************************************************************
* 函数原型:void WriteCommandLCD(INT8U WCLCD)
* 功能: 写指令到LCD
* 说明: 带忙标志检测
* 参数: 入口参数WCLCD为要写入的指令
*******************************************************************************/
void WriteCommandLCD(INT8U WCLCD)
{
while(LCD_BZ());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
LCDDataBus = WCLCD;
AnyNop();
LCD_EN = 1;
AnyNop();
LCD_EN = 0;
}
/*******************************************************************************
* 函数原型:void WriteDataLCD(INT8U WDLCD)
* 功能: 写数据到LCD
* 说明: 带忙标志检测
* 参数: 入口参数WDLCD为要写入的数据
*******************************************************************************/
void WriteDataLCD(INT8U WDLCD)
{
while(LCD_BZ());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
LCDDataBus = WDLCD;
AnyNop();
LCD_EN = 1;
AnyNop();
LCD_EN = 0;
}
/*******************************************************************************
* 函数原型:void LCD_Init(void)
* 功能: 初始化液晶
* 说明: 连续3次写入显示模式,不检测忙信号
* 参数:
*******************************************************************************/
void LCD_Init(void)
{
LCDDataBus = 0x00;
DelayMs(15);
WriteCommandLCD(0x38);
DelayMs(5);
WriteCommandLCD(0x38);
DelayMs(5);
WriteCommandLCD(0x38);
DelayMs(5);
WriteCommandLCD(0x38); //8位数据 2行显示 5×7字型 检测忙信号
WriteCommandLCD(0x08); //关闭显示 检测忙信号
WriteCommandLCD(0x01); //清屏 检测忙信号
WriteCommandLCD(0x06); //显示光标右移设置 检测忙信号
WriteCommandLCD(0x0c); //显示屏打开 光标不显示 不闪烁 检测忙信号
DelayMs(100);
WriteCommandLCD(0x0c);
WriteCommandLCD(0x01);
DelayMs(100);
}
/*******************************************************************************
* 函数原型:void DisplayOneChar(INT8U X,INT8U Y,INT8U DData)
* 功能: 在指定的坐标上显示一个字符
* 说明:
* 参数: 入口参数X Y 为显示的坐标 DData是显示的字符
*******************************************************************************/
void DisplayOneChar(INT8U X,INT8U Y,INT8U DData)
{
Y &= 1;
X &= 15;
if(Y) //Y=1;显示第二行
{
X |= 0x40;
}
X |= 0x80; //指令码为地址码+0x80
WriteCommandLCD(X);
WriteDataLCD(DData);
AnyNop();
}
/*******************************************************************************
* 函数原型:void DisplayListChar(INT8U X,INT8U Y,INT8U code *DData)
* 功能: 在指定的坐标上显示一串字符串
* 说明: X Y 为显示的坐标 code *DData 为字符串的长度
* 参数: 入口参数INT8U X INT8U Y INT8U code *DData
*******************************************************************************/
void DisplayListChar(INT8U X,INT8U Y,INT8U code *DData)
{
INT8U ListLength = 0;
Y &= 0x01;
X &= 0x0f;
while(X<16)
{
DisplayOneChar(X,Y,DData[ListLength]);
ListLength++;
X++;
}
AnyNop();
}
/*******************************************************************************
* 函数原型: void Timer_Init(void)
* 功能: 初始化要显示的时间
* 说明: 对时间数组赋初值2008-05-27-10:25:41
* 参数:
*******************************************************************************/
void Timer_Init(void)
{
TimeVal.Sec = 0x29;
TimeVal.Min = 0x19;
TimeVal.Hour = 0x0a;
TimeVal.Day = 0x1b;
TimeVal.Week = 0x02;
TimeVal.Month = 0x05;
TimeVal.Year = 0x08;
}
/*******************************************************************************
* 函数原型: void DisplayTimer(void)
* 功能: 刷屏
* 说明: 0.5S一次
* 参数: 无
*******************************************************************************/
void DisplayTimer(void)
{
#ifdef LCD1602
DisplayOneChar(0,0,(TimeVal.Year/10)+0x30);
DisplayOneChar(1,0,(TimeVal.Year%10)+0x30);
DisplayOneChar(2,0,'-');
DisplayOneChar(3,0,(TimeVal.Month/10)+0x30);
DisplayOneChar(4,0,(TimeVal.Month%10)+0x30);
DisplayOneChar(5,0,'-');
DisplayOneChar(6,0,(TimeVal.Day/10)+0x30);
DisplayOneChar(7,0,(TimeVal.Day%10)+0x30);
DisplayOneChar(0,1,(TimeVal.Hour/10)+0x30);
DisplayOneChar(1,1,(TimeVal.Hour%10)+0x30);
DisplayOneChar(2,1,':');
DisplayOneChar(3,1,(TimeVal.Min/10)+0x30);
DisplayOneChar(4,1,(TimeVal.Min%10)+0x30);
DisplayOneChar(5,1,':');
DisplayOneChar(6,1,(TimeVal.Sec/10)+0x30);
DisplayOneChar(7,1,(TimeVal.Sec%10)+0x30);
DisplayWeek(TimeVal.Week);
#endif
}
/*******************************************************************************
* 函数原型: void DisplayWeek(INT8U W)
* 功能: 显示星期
* 说明:入口参数w为选择的星期
* 参数:INT8U W
* 星期一 Mon.
* 星期二 Tues.
* 星期三 Wed.
* 星期四 Thurs.
* 星期五 Friday
* 星期六 Sat.
* 星期天 Sun.
* 局部变量: INT8U temp 用来转换入口参数W
*******************************************************************************/
void DisplayWeek(INT8U W)
{
INT8U temp;
temp = W;
#ifdef LCD1602
switch(temp)
{
case 01:
DisplayListChar(9,0,Dis1);
break;
case 02:
DisplayListChar(9,0,Dis2);
break;
case 03:
DisplayListChar(9,0,Dis3);
break;
case 04:
DisplayListChar(9,0,Dis4);
break;
case 05:
DisplayListChar(9,0,Dis5);
break;
case 06:
DisplayListChar(9,0,Dis6);
break;
case 00:
DisplayListChar(9,0,Dis7);
break;
default:
break;
}
#endif
}
/*******************************************************************************
* 函数原型: void Beep(INT8U x)
* 功能: 蜂鸣器控制提示音
* 说明: 入口参数x=0 1长 x=1 1短 x=2 2短 x=3 3短 x=4 1长3短
* 入口参数: INT8U x
*******************************************************************************/
void Beep(INT8U x)
{
if(x==0)
{
BeepCtr.BeepCnt = 30; //30*20ms=600ms
BeepCtr.BeepCntBak = 30;
BeepCtr.BeepTims = 1;
}
else if(x==1)
{
BeepCtr.BeepCnt = 5; //5*20ms=100ms
BeepCtr.BeepCntBak = 5;
BeepCtr.BeepTims = 1;
}
else if(x==2)
{
BeepCtr.BeepCnt = 5; //5*20ms=100ms
BeepCtr.BeepCntBak = 5;
BeepCtr.BeepTims = 3;
}
else if(x==3)
{
BeepCtr.BeepCnt = 5; //5*20ms=100ms
BeepCtr.BeepCntBak = 5;
BeepCtr.BeepTims = 5;
}
else if(x==4)
{
BeepCtr.BeepCnt = 30; //30*20ms=600ms
BeepCtr.BeepCntBak = 5; //5*20ms=100ms
BeepCtr.BeepTims = 7;
}
BEE = 0;
BeepCtr.SpkFlag = 1;
}
/*******************************************************************************
* 函数原型: void SpkDly(void)
* 功能: 蜂鸣器控制
* 说明: T2定时器20ms查询一次
* 参数:
* 全局变量:BeepCnt,BeepCntBak,BeepTims,Spk_id包含在蜂鸣器的结构体变量中
*******************************************************************************/
void SpkDly(void)
{
if(BeepCtr.SpkFlag)
{
if(--BeepCtr.BeepCnt==0)
{
if(--BeepCtr.BeepTims==0)
{
BEE = 1;
BeepCtr.SpkFlag = 0;
}
else
{
BeepCtr.BeepCnt = BeepCtr.BeepCntBak;
if(BeepCtr.BeepTims%2) BEE = 0;
else BEE = 1;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -