- 积分
- 3553
- 下载分
- 分
- 威望
- 点
- 原创币
- 点
- 下载
- 次
- 上传
- 次
- 注册时间
- 2014-11-13
- 精华
|
马上注册,获取阅读精华内容及下载权限
您需要 登录 才可以下载或查看,没有帐号?注册
x
#include <STC15F104E.H>
#include <intrins.h>
sbit SDA=P0^2;
sbit SCL=P0^1;
bit ack,blk; //I2C 应答位 LCD背光开关
#define uchar unsigned char
uchar num[]={"0123456789"},sec,min,hou;
unsigned int us,ms;
#define WriteAdd 0x7e //写PCF8574A地址 0111 A2 A2 A0 W
#define ReadAdd 0x7f //读PCF8574A地址 0111 A2 A2 A0 R
// 背光 CS/EN R/W RS
//P7 P6 P5 P4 P3 P2 P1 P0 PCF8574A引脚
//#define WriteCom 8 //DB7 DB6 DB5 DB4 1 0 0 0 RW=0写 RS=0指令 BLK背光
//#define WriteData 9 //DB7 DB6 DB5 DB4 1 0 0 1 RW=0写 RS=1数据
//#define WriteComEn 0x0c //DB7 DB6 DB5 DB4 1 1 0 0 RW=0写 RS=0
//#define WriteDataEn 0x0d //DB7 DB6 DB5 DB4 1 1 0 1 RW=0写 RS=1数据
/*======================== PCF8574A P3 = 0 关背光 ====================================*/
//#define WriteCom 0 //DB7 DB6 DB5 DB4 0 0 0 0 RW=0写 RS=0指令 BLK背光
//#define WriteData 1 //DB7 DB6 DB5 DB4 0 0 0 1 RW=0写 RS=1数据
//#define WriteComEn 4 //DB7 DB6 DB5 DB4 0 1 0 0 RW=0写 RS=0
//#define WriteDataEn 5 //DB7 DB6 DB5 DB4 0 1 0 1 RW=0写 RS=1数据
uchar WriteCom=8,WriteData=9,WriteComEn=0x0c,WriteDataEn=0x0d;
void LcdBlk() //LCD背光控制 blk=1亮,blk=0灭
{
if (blk) {WriteCom=8,WriteData=9,WriteComEn=0x0c,WriteDataEn=0x0d;}
else {WriteCom=0,WriteData=1,WriteComEn=4,WriteDataEn=5;}
}
void Delayms() //@22.1184MHz 1MS
{
unsigned char i, j;
i = 22;
j = 128;
do
{
while (--j);
} while (--i);
}
void Timer0Init(void) //10微秒@22.1184MHz 定时器做时钟
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x02; //设置定时器模式
TL0 = 0x23; //设置定时初值
TH0 = 0x23; //设置定时重载值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;EA=1;
}
void Delay5us() //@22.1184MHz
{
unsigned char i;
_nop_();
_nop_();
_nop_();
i = 24;
while (--i);
}
void i2cStart() //I2C 起始信号
{
SDA=1; _nop_(); SCL=1; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); SDA=0; _nop_(); _nop_(); _nop_();_nop_(); _nop_();SCL=0;Delay5us();
}
void i2cStop() //I2C 停止信号
{
SDA=0; _nop_(); SCL=1; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); SDA=1; _nop_(); _nop_(); _nop_(); _nop_();
}
void i2cAck(bit a) //I2C应答信号
{
if(a==0)SDA=0; //在此发出应答或非应答信号
else SDA=1;
_nop_();
_nop_();
_nop_();
SCL=1;
Delay5us();
SCL=0; //清时钟线,钳住I2C 总线以便继续接收
Delay5us();
}
void i2cWriteByte(uchar temp) //I2C写一字节
{
uchar i;
for(i=0;i<8;i++)
{
SDA=(bit)(temp & 0x80) ;
temp <<=1; Delay5us();
SCL=1; Delay5us(); Delay5us();
SCL=0;//Delay5us();
}
_nop_();
SDA=1; _nop_();Delay5us();
SCL=1;Delay5us();_nop_();_nop_();
if(SDA==1)ack=0;
else ack=1; //判断是否接收到应答信号
SCL=0;
}
void LcdCom(uchar com) //LCD1602写指令
{
i2cStart(); //I2C起始信号
i2cWriteByte(WriteAdd); //PCF8574A写地址
i2cWriteByte((com&0xf0)|WriteCom); //先写LCD1602高4位指令+控制位
i2cWriteByte((com&0xf0)|WriteComEn); //LCD1602 CS/EN拉高送入
i2cWriteByte((com&0xf0)|WriteCom); //LCD1602 CS/EN拉低准备写入
com<<=4; //指令低4位左移到高4位
i2cWriteByte((com&0xf0)|WriteCom); //写入剩下的4位指令+控制位
i2cWriteByte((com&0xf0)|WriteComEn);
i2cWriteByte((com&0xf0)|WriteCom);
i2cStop();Delay5us(); //写完成,I2C停止信号
}
void LcdIni() //1602初始化
{
LcdCom(0x33);
LcdCom(0x32);
LcdCom(0x28);
LcdCom(0x0c);
LcdCom(0x01);
LcdCom(0x80);
}
void LcdData(uchar com) //LCD1602写数据
{
i2cStart(); //I2C起始信号
i2cWriteByte(WriteAdd); //PCF8574A写地址
i2cWriteByte((com&0xf0)|WriteData); //Delay5us();//先写LCD1602高4位指令+控制位
i2cWriteByte((com&0xf0)|WriteDataEn); //Delayms();//LCD1602 CS/EN接高送入
i2cWriteByte((com&0xf0)|WriteData); //LCD1602 CS/EN拉低准备写入
com<<=4; //Delay5us();//数据低4位左移到高4位
i2cWriteByte((com&0xf0)|WriteDataEn); //Delayms();//写入剩下的4位数据+控制位
i2cWriteByte((com&0xf0)|WriteData); //写完成,I2C停止信号
i2cStop();Delay5us();
}
void LcdDisplay(uchar x,uchar *s) //1602显示字符串 //x=1显示在第一行,x=2显示在第二行
{
if(x==1) //第一行
{
LcdCom(0x80); //第一行起始位置地址
while(*s)
{
LcdData(*s);s++;
}
}
if(x==2) //第二行
{
LcdCom(0xc0); //第二行起始位置地址
while(*s)
{
LcdData(*s);s++;
}
}
}
void main()
{
Timer0Init();
LcdIni();
// LcdDisplay(1," I LOVE YOU!");LcdDisplay(2," Do U Love Me?");
while(1)
{
LcdCom(0x80);
if(hou>=24) {hou=0;}
if(sec>=60) {sec=0;min++;blk=~blk;}
LcdBlk();
if(min>=60) {min=0;hou++;}
LcdData(num[hou/10]);LcdData(num[hou%10]); LcdData(':');
LcdData(num[min/10]);LcdData(num[min%10]);LcdData(':');
LcdData(num[sec/10]);LcdData(num[sec%10]);
}
}
void InterruptT0 () interrupt 1
{
us++;
if (us>=100)
{
us=0;
ms++;
}
if(ms>=1000)
{
ms=0;
sec++;
}
}
|
|