📄 8563写读.c
字号:
#include<iom16v.h>
#include<macros.h>
#include<stdio.h>
#define uint unsigned int
#define uchar unsigned char
//1602
#define SetRS PORTD|=(1<<PD7)
#define ClrRS PORTD&=~(1<<PD7)
#define SetRW PORTD|=(1<<PD6)
#define ClrRW PORTD&=~(1<<PD6)
#define SetE PORTD|=(1<<PD5)
#define ClrE PORTD&=~(1<<PD5)
//8563
#define rd_device_add 0xa3 //定义器件读地址
#define wr_device_add 0xa2 //定义器件写地址
#define START 0x08
#define RE_START 0x10
#define MT_SLA_ACK 0x18 //主机发送模式标志
#define MT_SLA_NOACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NOACK 0x30
#define MR_SLA_ACK 0x40 //主机接受模式标志
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NOACK 0x58
// {秒 ,分 ,时 ,日,星期,月 ,年}
uchar read_shijian[7]={0x02,0x21,0x16,0x24,0x00,0x12,0x27};
uchar write_shijian[7]={0x50,0x59,0x23,0x31,0x07,0x12,0x99};
uchar s[4]; //把数字转换成字符串
uchar ReadStatusLCM(void);//读状态
void WriteDataLCM(uchar WDLCM);//写数据
void WriteCommandLCM(uchar WCLCM,uchar c);//写指令
//uchar ReadDataLCM(void);//读数据
void LCMInit(void);//初始化
void DisplayOneChar(uchar X,uchar Y,uchar DData);//在指定位置显示单个字符
void DisplayListChar(uchar X,uchar Y,uchar *DData);//在指定位置显示字符串
void Delay5ms(void);//延时5ms
void Delay400ms(void); //延时
//读状态,忙则循环,不忙则返回Data
uchar ReadStatusLCM(void)
{
uchar Data;
DDRA=0xff; //设置指令
PORTA=0xff;
DDRD=0xff;//1,输出,置数 0,输入,读数
ClrRS;
SetRW;
SetE; //执行指令
SetE;
DDRA=0x00; //读忙标志,忙则循环
Data=PINA;
while(Data&0x80)
Data=PINA;
return(Data);
}
//写指令
void WriteCommandLCM(uchar WCLCM,uchar c)
{
if(c==1) //标志为0不忙检测,标志为1检测
ReadStatusLCM();
DDRA=0xff; //设置指令
PORTA=WCLCM;
DDRD=0xff;//1,输出,置数 0,输入,读数
ClrRS;
ClrRW;
SetE;
SetE;
ClrE;
}
//读数据
/*uchar ReadDataLCM(void)
{
ReadStatusLCM(); //忙检测
ClrRS; //指令设置
ClrRW;
ClrE; //执行指令
ClrE;
SetE;
return(Data);
}*/
//初始化
void LCMInit(void)
{
DDRA=0xff;
PORTA=0x00;
WriteCommandLCM(0x38,0);//三次显示设置 ,不需忙检
Delay5ms(); //四位总线,双行显示,5*7点阵
WriteCommandLCM(0x38,0);
Delay5ms();
WriteCommandLCM(0x38,0);
Delay5ms();
WriteCommandLCM(0x38,1);//显示模式设置,以后都须忙检
WriteCommandLCM(0x08,1);//关闭显示
WriteCommandLCM(0x01,1);//清屏
WriteCommandLCM(0x06,1);//光标右移,字符不移
WriteCommandLCM(0x0c,1);//显示开,有光标,有闪烁
}
//写数据
void WriteDataLCM(uchar WDLCM)
{
ReadStatusLCM(); //忙检测
DDRA=0xff; //设置指令
PORTA=WDLCM;
DDRD=0xff;//1,输出,置数 0,输入,读数
SetRS;
ClrRW;
SetE;
SetE;
ClrE;
}
//按指定位置显示一个字符
void DisplayOneChar(uchar X,uchar Y,uchar DData)
{
Y&=0x01;//Y不能>1
X&=0x0f;//X不能>15
if(Y)
X+=0x40;//显示第二行时地址码+0x40
X+=0x80;//计算指令码
WriteCommandLCM(X,0);//发送地址码不需忙检
WriteDataLCM(DData);
}
//在指定位置显示字符串
void DisplayListChar(uchar X,uchar Y,uchar *DData)
{
uchar pose=0;
Y&=0x01;//Y不能>1
X&=0x0f;//X不能>15
while(DData[pose]>0x20)
{
DisplayOneChar(X,Y,DData[pose]);//显示单个字符
pose++;
X++;
if(X>=0xF)
{X=0x00;
Y=0x01;
}
}
}
void Delay1ms(void)
{
uint time,i;
time=5552;
while(time--);
}
//延时5ms,已验证
void Delay5ms(void)
{
uint time,i;
for(i=0;i<5;i++)
{time=5552;
while(time--);
}
}
//延时400ms
void Delay400ms(void)
{
uchar j;
for(j=0;j<8;j++)//延时400ms
{
Delay5ms();
}
}
//////////TWI总线操作函数 ////////////
void Start(void) //TWSTA置位,产生START状态
{TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);}
void Wait(void) //应用程序等待硬件操作完成
{while((TWCR&0x80)!=0x80);} //一直循环,直至硬件已置位TWINT
unsigned char TestAck(void) //读并返回状态寄存器TWSR的状态位,屏蔽低三位
{unsigned char twsr;
twsr=TWSR&0xf8;
return twsr;
}
void Write8Bit(unsigned char data)//应用程序写数据到数据寄存器TWDR,清TWINT启动发送
{TWDR=data;
TWCR=(1<<TWINT)|(1<<TWEN);
}
void Stop(void) //TWSTO置位,产生STOP状态
{TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);}
void Ack(void) //使能EA,如果接受到数据发送ACK脉冲
{TWCR=(1<<TWINT)|(1<<TWEA)|(1<<TWEN);}
void Twi(void) //使能TWI操作激活TWI接口
{TWCR=(1<<TWINT)|(1<<TWEN);}
// 向I2C总线写数据 ,正确写入数据返回0,否则分别返回2,3,4
unsigned char i2c_Write(unsigned char command,unsigned char RomAddress)
{
Start(); //发总线起始命令
Wait(); //等待应答
if(TestAck()!=START) return 1; //测试应答
Write8Bit(wr_device_add); //装入写器件地址
Wait(); //等待应答
if(TestAck()!=MT_SLA_ACK) return 2; //测试应答
Write8Bit(RomAddress); //装入写器件内的寄存器地址
Wait(); //等待应答
if(TestAck()!=MT_DATA_ACK) return 3; //测试应答
Write8Bit(command); //写命令
Wait(); //等待应答
if(TestAck()!=MT_DATA_ACK) return 4; //测试应答
Stop(); //停止总线
Delay5ms(); //延时
Delay5ms();
return 0;
}
//向I2C总线连续写入7个数据
unsigned char i2c_WriteData(unsigned char RomAddress)
{
unsigned char i;
Start(); //发总线起始命令
Wait(); //等待应答
if(TestAck()!=START) return 1; //测试应答
Write8Bit(wr_device_add); //写器件地址
Wait(); //等待应答
if(TestAck()!=MT_SLA_ACK) return 2; //测试应答
Write8Bit(RomAddress); //写器件内的寄存器首地址
Wait(); //等待应答
if(TestAck()!=MT_DATA_ACK)return 3; //测试应答
for(i=0;i<7;i++) //循环7次
{
Write8Bit(write_shijian[i]); //写数据
Wait(); //等待应答
if(TestAck()!=MT_DATA_ACK)return 4; //测试应答
}
Stop(); //停止总线
Delay5ms(); //延时
Delay5ms(); //延时
return 0;
}
//连续读取I2C总线
unsigned char i2c_Read(unsigned char RomAddress)
{
unsigned char i;
Start(); //发总线起始命令
Wait(); //等待应答
if(TestAck()!=START) return 1; //测试应答
Write8Bit(rd_device_add); //装入读器件地址
Wait(); //等待应答
if(TestAck()!=MR_SLA_ACK) return 5; //测试应答
for(i=0;i<7;i++)
{
Ack(); //使能EA,如果接受到数据发送ACK脉冲
Wait(); //等待应答
if(TestAck()!=MR_DATA_ACK)return 6; //测试应答
read_shijian[i]=TWDR; //将读取的数据放入数组中
}
Stop(); //停止总线
return 0;
}
//INT0中断函数,刷新显示时间
#pragma interrupt_handler Int0_isr:3 //中断向量2是INT0,3是INT1
void Int0_isr(void)
{
uchar result,result1,result2,result3,result4,result5;
i2c_Write(0x19,0x01); //向8563的01H控制状态寄存器2写入0x19
i2c_Read(0x02); //读取8563的02H-08H装入read_shijian[]
result1=read_shijian[0]&0x7f;
sprintf(s,"%x",result1);//转换成字符串 秒
if(result1<0x10)
{DisplayOneChar(6,1,'0');
DisplayListChar(7,1,s);
}
else DisplayListChar(6,1,s); //刷新时间
result2=read_shijian[1]&0x7f;
sprintf(s,"%x",result2);//转换成字符串 分
if(result2<0x10)
{
DisplayOneChar(3,1,'0');
DisplayListChar(4,1,s);
}
else DisplayListChar(3,1,s); //刷新时间
result3=read_shijian[2]&0x3f;
sprintf(s,"%x",result3);//转换成字符串 小时
if(result3<0x10)
{
DisplayOneChar(0,1,'0');
DisplayListChar(1,1,s);
}
else DisplayListChar(0,1,s); //刷新时间
result4=read_shijian[3]&0x3f;
sprintf(s,"%x",result4);//转换成字符串 日
if(result4<0x10)
{
DisplayOneChar(8,0,'0');
DisplayListChar(9,0,s);
}
else DisplayListChar(8,0,s); //刷新时间
Delay1ms();
sprintf(s,"%x",read_shijian[4]&0x07);//转换成字符串 星期
DisplayListChar(11,0,s); //刷新时间
result5=read_shijian[5]&0x1f;
sprintf(s,"%x",result5);//转换成字符串 月
if(result5<0x10)
{
DisplayOneChar(5,0,'0');
DisplayListChar(6,0,s);
}
else DisplayListChar(5,0,s); //刷新时间
result=read_shijian[6];
sprintf(s,"%x",read_shijian[6]); //转换成字符串 年
if(result<0x10)
{
DisplayOneChar(2,0,'0');
DisplayListChar(3,0,s);
}
else DisplayListChar(2,0,s); //刷新时间
if((result5==0x01)&&(result4==0x01)&&(result3==0x00)&&(result2==0x00)&&(result1==0x00))
{sprintf(s,"%d",20);
DisplayListChar(0,0,s);
}
}
//初始化TWI总线
void Twi_Init(void)
{
TWBR=32; //设置波特率
TWSR=0; //复位TWI总线
i2c_Write(0,0); //设置时钟状态
i2c_Write(0x81,0x0d);
i2c_Write(0x82,0x0e);
i2c_Write(1,0x0f);
i2c_Write(0x81,0x01);
i2c_WriteData(0x02);
i2c_Write(0x19,0x01); //向8563的01H控制状态寄存器2写入0x19
i2c_Read(0x02); //读取8563的02H-08H装入read_shijian[]
}
void main(void)
{
uint k=19;//年
DDRD=0xfb;
DDRC=0xff;
CLI(); //关中断
Delay400ms();//延时,启动
//MCUCR=(1<<ISC01); //设置INT0下降沿触发中断
GICR=(1<<INT1); //使能INT1中断
DDRB=0xff; //启动后灯亮
PORTB&=~(1<<PB0);
Twi_Init(); //初始化TWI总线
LCMInit(); //初始化
PORTB|=(1<<PB0);//初始化后灯灭
Delay5ms(); //年
sprintf(s,"%d",k);
DisplayListChar(0,0,s);
Delay5ms();
DisplayOneChar(4,0,'.');
Delay5ms();
DisplayOneChar(7,0,'.');
Delay5ms();
DisplayOneChar(10,0,'.');
Delay5ms();
DisplayOneChar(2,1,':');
Delay5ms();
DisplayOneChar(5,1,':');
//DisplayOneChar(10,0,'.');
//sprintf(s,"%d",k);
//DisplayListChar(0,0,s);
// DisplayListChar(5,0,net);
SEI(); //开中断
while(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -