📄 iictimelcd.c
字号:
//************************************************************************
//文件名:IICtimelcd.c
//
//创建人:章玉刚
//
//时间 :2003.6.21
//
//描述 :本程序是通过IIC口设置时钟芯片PCF8563和从时钟芯片读取时间;
// 设置只设置一次,读取时不要设置,不要运行void SetPCF8563(uchar timetype,uchar value)
//
//修改 :考虑到设置以后的每次读取都要把etPCF8563函数注释掉,为了避免这种麻烦,
// 所以用while语句来循环读取,但同时请注意,在C-SPY调试的时候就不能每次
// 让程序复位后运行,这样运行读取的时间就依然是第一次设定的时间,比系统时间慢了
// 后面一直用"Go"即可。
//修改时间:2003.6.21
//
//修改 :把时间的设定和读取做成函数,以便外部程序调用,传递的是全局变量
// 同时把液晶的显示函数做好了。
//
//修改时间:2003.6.24
//
//修改 :时间设定和读取做成用指针做形参的函数,以便外部调用;6.25
//修改 :加入一个不清屏的显示函数,主要是给设定时间用的;
//时间 :2003.7.1
//
//修改 :把清除屏幕和显示数据做成一个最底层的函数Cls()和Dispdata(char *data),供各显示函数调用
// 把flash()改成Dispdata();
//时间 :2003.7.2
//修改 :把显示9033OFF的函数放在底层,供9033.c调用
//时间 :2003.7.5
//************************************************************************//
#include "msp430x14x.h"
#define uint unsigned int
#define uchar unsigned char
#define SCL1 P4OUT |= BIT1;
#define SCL0 P4OUT &= ~BIT1;
#define SDA1 P4OUT |= BIT0;
#define SDA0 P4OUT &= ~BIT0;
#define I2COut P4DIR |=BIT0;P4DIR |=BIT1;
//#define I2CIn P4DIR &= ~BIT1;
#define I2CIn P4DIR &= ~BIT0;//我觉得应该为BIT0;是用SDA作为147输入的,而不是时钟SCL
#define I2CBit 0x01
unsigned char ack;
//启动总线函数:启动I2C总线,即发送I2C起始条件
void Start_I2c(void);
//结束I2C总线,发送结束条件?
void Stop_I2c(void);
//字节数据传送函数
void SendByte(uchar c);
//字节数据接收函数
uchar RcvByte(void);
//应答函数:主控器进行应答信号,(可以是应答或非应答信号)
void Ack_I2c(uchar a);
//应答信号函数
void SendAck(void);
//向有子地址器件发送多字节数据函数
uchar ISendStr256(uchar sla,uint suba, uchar *s,uchar no);
//向有子地址器件读取多字节数据
uchar IRcvStr256(uchar sla,uint suba, uchar *s,uchar no);
//时间设置函数
void Settime8563(uchar *time);
//时间读取函数
void Read8563(uchar *time);
uchar GetPCF8563(uchar firsttype);//只接收一个时间的函数
void SetPCF8563(uchar timetype,uchar value);
uchar BCD(uchar time1); //BCD到十进制转换
uchar countBCD(uchar time2); //十进制到BCD
//液晶显示函数,先清屏,再显示
void Display(uchar *data);
//液晶显示函数,不清除屏幕
void Dispdata(uchar *data);
//液晶清除屏幕函数
void Cls(void);
//显示E9033OFF函数
void DispOff(uchar);
//void delay(uchar delaytime); //这里面没有使用延时函数,注释掉
//注释掉的语句调试的时候用
/*unsigned char data_bak[7]; //时间读取后暂存数组
unsigned char data_time[7];
//这些变量应该是专门用来存放读取时间的,最后应该做成全局变量;用来设定时间的变量要另外定义
unsigned char Sec,Min,Hour,Day,Week,Mon,Year;
void main(void)
{
unsigned char disp_time[20]={0xd8,0x70,0xed,0x00,0xff,0xff,0xff,0x31,0xff,0x32,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
uchar nowtime[7]={00,50,3,26,4,6,03};//当前时间
uchar d_time[7]={0,0,0,0,0,0,0};
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
Settime8563(nowtime);
Read8563(d_time);
Display(disp_time);
while(1);
}*/
//启动总线函数:启动I2C总线,即发送I2C起始条件
void Start_I2c(void)
{
SDA1; SCL1; _NOP(); SDA0;_NOP(); SCL0;_NOP();
}
//结束I2C总线,发送结束条件?
void Stop_I2c(void)
{
SCL0; _NOP(); SDA0; _NOP(); SCL1; _NOP(); SDA1; _NOP();
}
//字节数据传送函数
void SendByte(uchar c)
{
uchar BitCnt;
uchar errtime=255;
for(BitCnt=0;BitCnt<8;BitCnt++)
{
SCL0; _NOP();
if((c<<BitCnt)&0x80)
{
SDA1;
}
else
{
SDA0;
}
_NOP();
SCL1;_NOP();
}
SCL0; _NOP();
I2CIn;
SCL1; _NOP();
aaa:
if (P4IN&I2CBit) ack=0;else ack=1;
if(ack==0) {
errtime--;
if (errtime==0){
Stop_I2c();
goto bbb;
}
goto aaa;
}
bbb:
SCL0;
_NOP();
I2COut;
}
//字节数据接收函数
uchar RcvByte(void)
{
uchar retc;
uchar BitCnt;
retc=0;
I2COut;
SDA1;
for(BitCnt=0;BitCnt<8;BitCnt++)
{
SCL0;SCL1;
retc=retc<<1;
I2CIn;
if (P4IN&I2CBit) retc=retc+1;
}
SCL0;;
return(retc);
}
//应答函数:主控器进行应答信号,(可以是应答或非应答信号)
void Ack_I2c(uchar a)
{
I2COut;
if(a==0) {
SDA0;
_NOP();
}
else
{
SDA1;
_NOP();
}
SCL1;
_NOP();
SCL0;
_NOP();
}
//向有子地址器件发送多字节数据函数
uchar ISendStr256(uchar sla,uint suba, uchar *s,uchar no)
{
uchar i,temp;
Start_I2c(); //启动总线
SendByte(sla);//发送器件地址
if (ack==0){ return(0);}
temp=(suba&0xff00)>>8;
SendByte(temp);//发送器件子地址高地址
if (ack==0) return(0);
temp=suba&0xff;
SendByte(temp); //发送器件子地址低地址
if (ack==0) return(0);
for(i=0;i<no;i++)
{
SendByte(*s); //发送数据
if (ack==0) return(0);
s++;
}
Stop_I2c();//结束总线
return(1);
}
//向有子地址器件读取多字节数据函数
uchar IRcvStr256(uchar sla,uint suba, uchar *s,uchar no)
{
uchar i,temp;
Start_I2c(); //启动总线
SendByte(sla);//发送器件地址
if (ack==0){ return(0); }
temp=(suba&0xff00)>>8;
SendByte(temp);//发送器件子地址高地址
if (ack==0) return(0);
temp=suba&0xff;
SendByte(temp); //发送器件子地址低地址
if (ack==0) return(0);
Start_I2c();
SendByte(sla+1);
if (ack==0) return(0);
for(i=0;i<no-1;i++)
{
*s=RcvByte(); //接收数据
Ack_I2c(0); //发送就答位
s++;
}
*s=RcvByte();
Ack_I2c(1); //发送非应位
Stop_I2c();//结束总线
return(1);
}
//**************************************************************************
//调用方式:void GetPCF8563(uchar firsttype)
//函数说明:读取时间。设置要读的时间类型firsttype,firsttype为地址
//0x02:秒/0x03:分/0x04:小时/0x05:日/0x06:星期/0x07:月(世纪)/0x08:年
//**************************************************************************//
uchar GetPCF8563(uchar firsttype)
{
uchar time;
Start_I2c();
SendByte(0xA2);
SendByte(firsttype);
Start_I2c();
SendByte(0xA3);
time=RcvByte();
SendAck(); //除最后一个字节外,其他都要从MASTER发应答。
Stop_I2c();
return(time);
}
/**--------------------------------------------------------------------------------
调用方式:void SetPCF8563(uchar timetype,uchar value)
函数说明:调整时钟。timetype是要改的时间类型,value是新设置的时间值(BCD格式)。
0x02:秒/0x03:分/0x04:小时/0x05:日/0x06:星期/0x07:月(世纪)/0x08:年
---------------------------------------------------------------------------------*/
void SetPCF8563(uchar timetype,uchar value)
{
Start_I2c();
SendByte(0xA2);
SendByte(timetype);
SendByte(value);
Stop_I2c();
}
/**--------------------------------------------------------------------------------
调用方式:void Settime(uchar *time)
函数说明:时间的一次性设置,年月日星期时分秒全设
---------------------------------------------------------------------------------*/
void Settime8563(uchar *time)
{
//配置的时间可为当前计算机系统的时间,也可使用全局变量配置,必须用BCD码进行设置
SetPCF8563(0x00,0x00); //启动PCF8563
SetPCF8563(0x01,0x00);
SetPCF8563(0x02,countBCD(*time)); //秒
SetPCF8563(0x03,countBCD(*(time+1))); //分
SetPCF8563(0x04,countBCD(*(time+2))); //时
SetPCF8563(0x05,countBCD(*(time+3))); //日
SetPCF8563(0x06,countBCD(*(time+4))); //星期,必须设置,可以不读取,否则年月不对
SetPCF8563(0x07,countBCD(*(time+5))); //月
SetPCF8563(0x08,countBCD(*(time+6))); //年
}
/**--------------------------------------------------------------------------------
调用方式:void SendAck(void)
函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。
---------------------------------------------------------------------------------*/
void SendAck(void)
{
SDA0; _NOP();
SCL1; _NOP();
SCL0;
}
//*********************************************************************************
//调用方式:uchar BCD(unsigned char time1)
//函数说明:是把BCD码变成十进制码
//********************************************************************************//
uchar BCD(uchar time1)
{
uchar D0,D1;
D0=time1&0x0f;
D1=(time1>>4)&0x0f;
return(D1*10+D0);
}
//*********************************************************************************
//调用方式:uchar countBCD(unsigned char time2)
//函数说明:是把十进制码变成BCD码,十进制不能超过100*/
//********************************************************************************//
uchar countBCD(unsigned char time2)
{
unsigned char D0,D1,D;
D1=time2/10; //十位
D0=time2%10; //个位
D=D1<<4; //注:不能用D=D1<<4+D0;为什么不清楚
D=D+D0;
return(D);
}
//-------------------------------------------------------------------------------------
//调用方式:void Read8563(uchar *time)
//函数说明:把从8563读取的时间放到time数组里面,返回给实参
//时间 :2003.6.25
//-------------------------------------------------------------------------------------
void Read8563(uchar *time)
{
uchar data_bak1[7];
SetPCF8563(0x00,0x00);
data_bak1[0]=GetPCF8563(0x02); //秒
data_bak1[0]=data_bak1[0]&0x7f;
*time=BCD(data_bak1[0]);
data_bak1[1]=GetPCF8563(0x03); //分
data_bak1[1]=data_bak1[1]&0x7f;
*(time+1)=BCD(data_bak1[1]);
data_bak1[2]=GetPCF8563(0x04); //时
data_bak1[2]=data_bak1[2]&0x3f;
*(time+2)=BCD(data_bak1[2]);
data_bak1[3]=GetPCF8563(0x05); //日
data_bak1[3]=data_bak1[3]&0x3f;
*(time+3)=BCD(data_bak1[3]);
data_bak1[4]=GetPCF8563(0x06); //星期,可以先不读取
data_bak1[4]=data_bak1[4]&0x07;
//if(data_bak1[4]==0) data_bak1[4]=7; //可以不变
*(time+4)=data_bak1[4];
data_bak1[5]=GetPCF8563(0x07); //月
data_bak1[5] =data_bak1[5]&0x1f;
*(time+5)=BCD(data_bak1[5]);
data_bak1[6]=GetPCF8563(0x08); //年
data_bak1[6]=*(data_bak1+6);
*(time+6)=BCD(data_bak1[6]);
}
//-------------------------------------------------------------------------------------
//调用方式:void Display(uchar *data)
//函数说明:把data数组中的数据发到8576进行显示
//时间 :2003.6.25
//-------------------------------------------------------------------------------------
void Display(uchar *data)
{
uint SubAdd=0xe080;
uchar i;
//液晶清屏命令
unsigned char cls[2]={0xd0,0x70};
//清除液晶屏幕
ISendStr256(0x70,SubAdd,cls,2);
for(i=0;i<0x5f;i++)
{
ISendStr256(0x70,SubAdd,cls,2);
_NOP();
}
//液晶显示
ISendStr256(0x70,SubAdd,data,20);
for(i=0;i<0x5f;i++)
{
ISendStr256(0x70,SubAdd,data,20);
_NOP();
}
}
//-------------------------------------------------------------------------------------
//调用方式:void Dispdata(uchar *data)
//函数说明:把data数组中的数据发到8576进行显示,不清除屏幕
//时间 :2003.7.2
//-------------------------------------------------------------------------------------
void Dispdata(uchar *data)
{
uint SubAdd=0xe080;
uchar i;
//液晶显示
ISendStr256(0x70,SubAdd,data,20);
for(i=0;i<0x10;i++)
{
ISendStr256(0x70,SubAdd,data,20);
_NOP();
}
}
//-------------------------------------------------------------------------------------
//调用方式:void Cls(void)
//函数说明:清除屏幕
//时间 :2003.7.2
//-------------------------------------------------------------------------------------
void Cls(void)
{
uint SubAdd=0xe080;
uchar i;
//液晶清屏命令
unsigned char cls[2]={0xd0,0x70};
//清除液晶屏幕
ISendStr256(0x70,SubAdd,cls,2);
for(i=0;i<0x5f;i++)
{
ISendStr256(0x70,SubAdd,cls,2);
_NOP();
}
}
//-------------------------------------------------------------------------------------
//调用方式:void DispOff(ucahr flag)
//函数说明:显示E9033OFF函数清除屏幕
//时间 :2003.7.5
//-------------------------------------------------------------------------------------
void DispOff(uchar flag)
{
uchar i;
uchar dispdata[20]={0xd8,0x70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//显示的数据
uchar lcd[19]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
switch(flag)
{
case 1:
/*lcd[13]=0xf8; //E
lcd[14]=0xbe; //9
lcd[15]=0xde; //0
lcd[16]=0x3e; //3
lcd[4]=0xe3; //3
lcd[13]=0xf8; */ //E
lcd[13]=0xbe; //9 101111110
lcd[14]=0xde; //0
lcd[15]=0x3e; //3
lcd[16]=0x3e; //3
lcd[4]=0x00;
break;
case 2:
lcd[13]=0xbc; //10111100 S
lcd[14]=0xd0; //11010000 L
lcd[15]=0xea; //11101010 P
lcd[16]=0xed; //11101101 O
//这里是用来显示电台关闭的lcd[]
break;
}
lcd[3]=0xed; //O
lcd[1]=0x8e; //F
lcd[18]=0xe8; //F
for(i=1;i<=18;i++)
dispdata[i+1]=lcd[i];
Dispdata(dispdata);
for(i=0;i<0xff;i++); for(i=0;i<0xff;i++); for(i=0;i<0xff;i++);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -