📄 main.c
字号:
//*****************************************************//
//*********工程名称:pcf8563.spj************************//
//*******编译器软件:u'nSP IDE,凌阳公司*****************//
//**功能:使用pcf8563实现时钟,并通过LCD显示出来********//
//**硬件连接:IOA口的高八位接液晶显示器,IOB口接pcf8563*//
//****2006年8月3号调试成功,愿与大家共勉***************//
//*****************************************************//
#include "SPCE061V004.H"
unsigned int data_out;
int g8563_Store[7]; /*时间交换区,全局变量声明*/
int c8563_Store[7]={0x00,0x18,0x10,0x21,0x01,0x08,0x06}; /*写入时间初值*/
char r1[16]={" 年 月 日 "};
char r2[16]={" 星期 "};
char r3[16]={" 时 分 秒 "};
char week[7][2]={"日","一","二","三","四","五","六"};
//******IOB初始化******* 以B0口为数据位 B1为时钟位
int IOB_Ini()
{
*P_IOB_Dir=0x0003; //B0 SDA B1 SCL
*P_IOB_Attrib=0x0003;
*P_IOB_Data=0x0000;
}
/********************************************
内部函数,延时1
********************************************/
void Delay(int i)
{ /*根据晶振频率制定延时时间*/
while(i--)
*P_Watchdog_Clear = 1;
}
/********************************************
内部函数,I2C开始
********************************************/
void Start()
{
*P_IOB_Dir=0x0003; //B0 SDA B1 SCL
*P_IOB_Attrib=0x0003;
*P_IOB_Data=0x03;
Delay(2);
*P_IOB_Data=0x02;
Delay(2);
*P_IOB_Data=0x00;
}
/********************************************
内部函数,I2C结束
********************************************/
void Stop()
{ *P_IOB_Dir=0x0003; //B0 SDA B1 SCL
*P_IOB_Attrib=0x0003;
*P_IOB_Data=0x00;
Delay(2);
*P_IOB_Data=0x02;
Delay(2);
*P_IOB_Data=0x03;
Delay(31);
}
/********************************************
内部函数,输出ACK ,每个字节传输完成,输出ack=0,结束读书据,ack=1;
********************************************/
void WriteACK(int ack)
{*P_IOB_Dir=0x0003; //B0 SDA B1 SCL
*P_IOB_Attrib=0x0003;
*P_IOB_Data|=ack;
Delay(2);
*P_IOB_Data|=0x02;
Delay(2);
*P_IOB_Data&=0xfffd;
}
/********************************************
内部函数,等待ACK
********************************************/
void WaitACK()
{ int errtime=20;
*P_IOB_Dir=0x0002; //B0 SDA B1 SCL
*P_IOB_Attrib=0x0003;
*P_IOB_Data|=0x01;
Delay(2); /*读ACK*/
*P_IOB_Data=0x03;
Delay(2);
while(*P_IOB_Data&0x0001)
{ errtime--;
if(!errtime)
Stop();
}
*P_IOB_Data&=0xfffd;
Delay(5);
}
/********************************************
内部函数.输出数据字节
入口:B=数据
********************************************/
void writebyte(int wdata)
{ int i;
*P_IOB_Dir=0x0003;
*P_IOB_Attrib=0x0003;
for(i=0;i<8;i++)
{
if(wdata&0x80) *P_IOB_Data=0x01;
else *P_IOB_Data=0x00;
wdata<<=1;
*P_IOB_Data|=0x02;
Delay(2);
*P_IOB_Data&=0xfd;
}
WaitACK(); //I2C器件或通讯出错,将会退出I2C通讯
}
/********************************************
内部函数.输入数据
出口:B
********************************************/
int Readbyte()
{
int i,bytedata;
*P_IOB_Dir=0x0002; //输入
*P_IOB_Attrib=0x0002;
*P_IOB_Data=0x01;
for(i=0;i<8;i++)
{
*P_IOB_Data|=0x0002;
bytedata<<=1;
bytedata|=(*P_IOB_Data&0x0001);
*P_IOB_Data&=0xfffd;
Delay(2);
}
return(bytedata);
}
/********************************************
输出数据->pcf8563
********************************************/
void writeData(int address,int mdata)
{
Start();
writebyte(0xa2); /*写命令*/
writebyte(address); /*写地址*/
writebyte(mdata); /*写数据*/
Stop();
}
/********************************************
输入数据<-pcf8563
********************************************/
int ReadData(int address) /*单字节*/
{ int rdata;
Start();
writebyte(0xa2); /*写命令*/
writebyte(address); /*写地址*/
Start();
writebyte(0xa3); /*读命令*/
rdata=Readbyte();
WriteACK(1);
Stop();
return(rdata);
}
void ReadData1(int address,int count,int * buff) /*多字节*/
{ int i;
Start();
writebyte(0xa2); /*写命令*/
writebyte(address); /*写地址*/
Start();
writebyte(0xa3); /*读命令*/
for(i=0;i<count;i++)
{
buff[i]=Readbyte();
if(i<count-1) WriteACK(0);
}
WriteACK(1);
Stop();
}
/********************************************
内部函数,读入时间到内部缓冲区
********************************************/
void P8563_Read()
{int time[7];
time[0]=ReadData(0x02);
time[1]=ReadData(0x03);
time[2]=ReadData(0x04);
time[3]=ReadData(0x05);
time[4]=ReadData(0x06);
time[5]=ReadData(0x07);
time[6]=ReadData(0x08);
g8563_Store[0]=time[0]&0x7f; //秒
g8563_Store[1]=time[1]&0x7f; //分
g8563_Store[2]=time[2]&0x3f; //小时
g8563_Store[3]=time[3]&0x3f; //日
g8563_Store[4]=time[4]&0x07; //星期
g8563_Store[5]=time[5]&0x1f; //月
g8563_Store[6]=time[6]&0xff; //年
}
/********************************************
读入时间到内部缓冲区----外部调用
********************************************/
void P8563_gettime()
{
P8563_Read();
if(g8563_Store[0]==0)
P8563_Read(); /*如果为秒=0,为防止时间变化,再读一次*/
}
/********************************************
写时间修改值
********************************************/
void P8563_settime()
{
int i;
for(i=2;i<=8;i++) { writeData(i,g8563_Store[i-2]); }
// writeData(6,g8563_Store[3]);
}
/*****************************************
P8563的初始化-----外部调用
******************************************/
void P8563_init()
{
int i;
if((ReadData(0xa)&0x3f)!=0x8) /*检查是否第一次启动,是则初始化时间*/
{
for(i=0;i<=6;i++) g8563_Store[i]=c8563_Store[i]; /*初始化时间*/
P8563_settime();
writeData(0x0,0x00);
// writeData(0xa,0x8); /*8:00报警*/
// writeData(0x1,0x12); /*报警有效*/
writeData(0xd,0x00);
}
}
//***************换算*********************//
int transform()
{ int w;
r3[11]=(g8563_Store[0]&0x000f)+'0';
r3[10]=((g8563_Store[0]&0x0070)>>4)+'0';
r3[7]=(g8563_Store[1]&0x000f)+'0';
r3[6]=((g8563_Store[1]&0x0070)>>4)+'0';
r3[3]=(g8563_Store[2]&0x000f)+'0';
r3[2]=((g8563_Store[2]&0x0030)>>4)+'0';
w=g8563_Store[4]&0x0007;
r2[10]=week[w][0];r2[11]=week[w][1];
r1[11]=(g8563_Store[3]&0x000f)+'0';
r1[10]=((g8563_Store[3]&0x0030)>>4)+'0';
r1[7]=(g8563_Store[5]&0x000f)+'0';
r1[6]=((g8563_Store[5]&0x0010)>>4)+'0';
r1[3]=(g8563_Store[6]&0x000f)+'0';
r1[2]=((g8563_Store[6]&0x00f0)>>4)+'0';
}
///********************************************
//*****************液晶显示********************
void send_data(unsigned int data) //高8位为待送数据
{ int i=8,j,data1;
data=data>>6; //IO9为数据输入端,右移4位与IO11对齐
while (i--)
{
data1=data&0x0200;
if (data1)
{data_out|=data1;
*P_IOA_Data=data_out;}
else
{data_out&=0xfdff;
*P_IOA_Data=data_out;}
data_out|=0x0400; //set sclk to high IO10
*P_IOA_Data=data_out;
data_out&=0xfbff; //set sclk to low IO10
*P_IOA_Data=data_out;
data=data<<1;
}
}
void write_data(data) //低八位是待写入数据
unsigned int data;
{ unsigned int data1=0xfa00,data2,data3; //data2中存放高4位数据,data3中存放低4位数据
data_out=data_out|0x0100; //cs set to high
*P_IOA_Data=data_out;
data2=data&0x00f0; //取高4位数据
data2=data2<<8;
data3=data&0x000f; //取低4位数据
data3=data3<<12;
send_data(data1);
send_data(data2);
send_data(data3);
data_out=data_out&0xfeff;
*P_IOA_Data=data_out; //cs set to low
}
void write_comm(data) //低八位是待写入数据
unsigned int data;
{ unsigned int data1=0xf800,data2,data3;
data_out=data_out|0x0100; //cs set to high
*P_IOA_Data=data_out;
data2=data&0x00f0; //取高4位数据
data2=data2<<8;
data3=data&0x000f; //取低4位数据
data3=data3<<12;
send_data(data1);
send_data(data2);
send_data(data3);
data_out=data_out&0xfeff;
*P_IOA_Data=data_out; //cs set to low
}
void init_io(void)
{
*P_IOA_Data=0x00ff;
*P_IOA_Dir=0xef00;
*P_IOA_Attrib=0xffff;
data_out=0x0000; //初始化A口数据
}
void screen(data)
char data[65];
{ unsigned int i,j;
for (i=0;i<64;i++)
{write_data(data[i]);
if (i==15)
write_comm(0x0090); //设定DDRAM第二行,第一列
if (i==31)
write_comm(0x0088); //设定DDRAM第三行,第一列
if (i==47)
write_comm(0x0098); //设定DDRAM第四行,第一列
if (i==63)
write_comm(0x0080); //设定DDRAM第四行,第一列
}
}
unsigned int addr=0x0800;
void steprow(int r,char *p)
{
int i=0;
switch(r)
{
case 1:addr=0x0080; write_comm(addr);
for(i=0;i<16;i++)
write_data(p[i]); break;
case 2:addr=0x0090; write_comm(addr);
for(i=0;i<16;i++)
write_data(p[i]); break;
case 3:addr=0x0088; write_comm(addr);
for(i=0;i<16;i++)
write_data(p[i]); break;
case 4:addr=0x0098; write_comm(addr);
for(i=0;i<16;i++)
write_data(p[i]); break;
}
}
main()
{ init_io();
IOB_Ini();
write_comm(0x0030); //基本指令集
write_comm(0x0001); //清除显示屏幕,把DDRAM位址计数器调整为"00H"
write_comm(0x0003); //把DDRAM位址计数器调整为"00H",游标回原点,该功能不影响显示DDRAM
write_comm(0x0006); //光标右移
write_comm(0x000e);
P8563_init();
while(1)
{ steprow(1,r1);
steprow(2,r2);
steprow(3,r3);
P8563_gettime();
transform();
*P_Watchdog_Clear = 1;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -