钻石会员
主题
回帖0
积分36261
阅读权限50
注册时间2011-4-27
最后登录1970-1-1
在线时间 小时
|
#include <at89x52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define OP_WRITE 0xD0 // DS32C35器件地址以及写入操作
#define OP_READ 0xD1 // DS32C35器件地址以及读取操作
uchar TAB[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xbf,0x8e,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
uchar flag;
uchar Min,Max,Change_Num,Change,Set_Flag=0;
uchar *DS_Data;
float Tem;
/*--------------------------------------------------------------*/
//定义时间类型
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
uchar Tem_H;
uchar Tem_L;
// 数码管驱动相关接口
sbit SDATA_595 = P1^3 ; // /串行数据输入14DS*/
sbit SCLK_595 = P1^2; // /*移位时钟脉冲11SCH*/
sbit RCK_595 = P1^1; // /*输出锁存器控制脉冲12STCP*/
sbit EN_595 = P1^0; // /*使能*/
//* 定义设置时钟键
sbit Key_Set=P2^4;
sbit Key_Add=P2^5;
sbit Key_Dec=P2^6;
sbit Key_Ok=P2^7;
//* 定义设置时钟键
sbit INT = P3^6;
sbit scl = P3^5;
sbit sda = P3^4;
delay(uint count)
{
uint x,y;
for(x=0;x<count;x++)
for(y=0;y<12;y++);
}
//--------------------------------------------//
// 数据转换函数
//--------------------------------------------//
BCD_D(uchar num)
{
uchar L;
L=(num/16)*10+(num%16);
return L;
}
//十进制转BCD
D_BCD(uchar num)
{
uchar L;
L=(num/10)*16+(num%10);
return L;
}
//--------------------------------------------//
// 模拟IIC读写32C35驱动 //
//--------------------------------------------//
void delay1()
{ ; ;}
void start() //开始信号
{
sda=1;
delay1();
scl=1;
delay1();
sda=0;
delay1();
}
void stop() //停止
{
sda=0;
delay1();
scl=1;
delay1();
sda=1;
delay1();
}
void ack() //应答
{
uchar i;
scl=1;
delay1();
delay1();
while((sda==1)&&(i<250))i++;
scl=0;
delay1();
}
//--------------------------------------------
// 写字节
//--------------------------------------------
void write_byte(uchar date)
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
delay1();
sda=CY;
delay1();
scl=1;
delay1();
}
scl=0;
delay1();
sda=1;
delay1();
}
//--------------------------------------------
// 读字节
//--------------------------------------------
uchar read_byte()
{
uchar i,k;
scl=0;
delay1();
sda=1;
delay1();
for(i=0;i<8;i++)
{
scl=1;
delay1();
k=(k<<1)|sda;
scl=0;
delay1();
}
return k;
}
//--------------------------------------------
// 给DS32C35写数据
//--------------------------------------------
void write_add(uchar address,uchar date)
{
start();
write_byte(OP_WRITE);
ack();
write_byte(address);
ack();
write_byte(date);
ack();
stop();
}
//--------------------------------------------
// 读DS32C35的数据
//--------------------------------------------
uchar read_add(uchar address)
{
uchar date;
start();
write_byte(OP_WRITE);
ack();
write_byte(address);
ack();
start();
write_byte(OP_READ);
ack();
date=read_byte();
stop();
return date;
}
//--------------------------------------------//
// 写入DS32C35数据 //
//--------------------------------------------//
write32c35()
{
write_add(0x00,Second); //设定秒钟初值
write_add(0x01,Minute); //设定分钟初值
write_add(0x02,Hour); //设定时钟初值
write_add(0x04,Day); //设定日初值
write_add(0x05,Month); //设定月初值
write_add(0x06,Year); //设定年初值
}
//--------------------------------------------//
// 读取DS32C35并且处理数据 //
//--------------------------------------------//
void read32c35()
{
Year = read_add(0x06);
Month = read_add(0x05);
Day = read_add(0x04);
// Week = read_add(0x03);
Hour= read_add(0x02);
Minute = read_add(0x01);
Second = read_add(0x00);
}
//--------------------------------------------//
// DS32C35读温度并处理数据 //
//--------------------------------------------//
void readtemp()
{
uint Tem_suf;//缓冲数据变量
write_add(0x0e,0x20); //采集温度
Tem_H=read_add(0x11);//读取温度高位
Tem_L=read_add(0x12);//读取温度低位
if(!(Tem_H&0x80))//正温度
{
Tem_suf=Tem_H;//高位赋给Tem_suf
Tem_suf<<=2;//Tem_suf右移两位
Tem_suf|=(Tem_L>>6);//Tem_L右移6位并放于Tem_suf的低两位
Tem=Tem_suf;
Tem*=0.25;//温度实际值
Tem+=0.5;//温度四舍五入
Tem*=10;//温度放大10倍
if(Tem>=100)
{
Tem_H=Tem/100;//温度十位
Tem_L=(uint)Tem/10%10;//温度个位
}
if(Tem<100)
{
Tem_H=(uint)Tem/10%10;//温度个位
Tem_H+=0x0c;//显示小数点的数字表位置
Tem_L=(uint)Tem%10;//温度十分位
}
}
else//负温度
{
Tem_suf=(Tem_H&0x7f);//Tem_H高位标志位置0并赋给Tem_suf
Tem_suf<<=2;//Tem_suf右移两位
Tem_suf|=(Tem_L>>6);//Tem_L右移6位并放于Tem_suf的低两位
Tem_suf=(~Tem_suf)+1;//取反加一,将补码转换为原码
Tem=Tem_suf;
Tem*=0.25;//温度实际值
Tem+=0.5;//温度四舍五入
Tem*=10;//温度放大10倍
Tem_H=Tem/100;//温度十位
Tem_L=(uint)Tem/10 %10;//温度各位
// Tem_D=Tem%10;//温度十分位
if(Tem_H)//温度超过零下9度时
{
Tem_H=0x00;//显示"O"符号 overflow溢出
Tem_L=0x0b;//显示"F"符号
}
else
{
Tem_H=0x0a;//显示"-"符号
Tem_L=(uint)Tem/10%10;//显示温度
}
}
}
void WR_595(unsigned char data num2 )//写
{
unsigned char data count1;
for(count1=0;count1<=7;count1++)
{
if((num2&0x80)==0x80) //*最高位为1,则向SDATA_595发送1*/
SDATA_595=1; //*发出数据的最高位*/
else
SDATA_595=0;
num2<<=1; //*右移位*/
SCLK_595=0; //*产生上生沿*/
SCLK_595=1;
}
}
/*-------------------------------------------------------------------------------
打开锁存,更新74595输出子程序
---------------------------------------------------------------------------------*/
void Out_595(void)
{
RCK_595=0;
_nop_();
_nop_();
RCK_595=1; /*上升沿锁存数据*/
}
/*-------------------------------------------------------------------------------
74HC138移位子程序
---------------------------------------------------------------------------------*/
WR_138(unsigned char count)
{
switch(count)
{
case 0x00:{P1_4=0;P1_5=0;P1_6=0;}break;
case 0x01:{P1_4=0;P1_5=0;P1_6=1;}break;
case 0x02:{P1_4=0;P1_5=1;P1_6=0;}break;
case 0x03:{P1_4=0;P1_5=1;P1_6=1;}break;
case 0x04:{P1_4=1;P1_5=0;P1_6=0;}break;
case 0x05:{P1_4=1;P1_5=0;P1_6=1;}break;
default:{P1_4=1;P1_5=1;P1_6=1;}
}
}
// 显示 //
/*--------------------------------------------------------------------*/
void disp(void)
{
WR_595(TAB[0]); //
WR_595(TAB[Hour/16]); //写数码管的段 小时(十位)
WR_595(TAB[2]); //写数码管的段 年(千位)
WR_138(0x07); //关闭138译码器
Out_595(); //打开锁存,更新74595输出
WR_138(0x00); //138译码器 00010000
delay(20);
WR_595(TAB[0]); //
WR_595(TAB[Hour%16]); //写数码管的段 小时(个位)
WR_595(TAB[0]); //写数码管的段年(百位)
WR_138(0x07); //关闭138译码器
Out_595(); //打开锁存,更新74595输出
WR_138(0x01); //138译码器 00100000
delay(20);
WR_595(TAB[Tem_H]); //写数码管的段 温度(十位)
WR_595(TAB[Minute/16]); //写数码管的段 分钟(十位)
WR_595(TAB[Year/16]); //写数码管的段年 (十位)
WR_138(0x07); //关闭138译码器
Out_595(); //打开锁存,更新74595输出
WR_138(0x02); //138译码器 00110000
delay(20);
WR_595(TAB[Tem_L]); //写数码管的段温度(个位)
WR_595(TAB[Minute%16]); //写数码管的段 分钟(个位)
WR_595(TAB[Year%16]); //写数码管的段 年(个位)
WR_138(0x07); //关闭138译码器
Out_595(); //打开锁存,更新74595输出
WR_138(0x03); //138译码器 01000000
delay(20);
WR_595(TAB[Day/16]); // 写数码管的段日 (十位)
WR_595(TAB[Second/16]); //写数码管的段秒 (十位)
WR_595(TAB[Month/16]); //写数码管的段 月(十位)
WR_138(0x07); //关闭138译码器
Out_595(); //打开锁存,更新74595输出
WR_138(0x04); //138译码器 01010000
delay(20);
WR_595(TAB[Day%16]); //写数码管的段日(个位)
WR_595(TAB[Second%16]); //写数码管的段秒 (个位)
WR_595(TAB[Month%16]); //写数码管的段 月(个位)
WR_138(0x07); //关闭138译码器
Out_595(); //打开锁存,更新74595输出
WR_138(0x05); //138译码器 01100000
}
void init_ds32C35()
{
write_add(0x00,D_BCD(50)); //设定秒钟初值
write_add(0x01,D_BCD(59)); //设定分钟初值
write_add(0x02,D_BCD(23)); //设定时钟初值
write_add(0x03,D_BCD(7)); //设定星期初值
write_add(0x04,D_BCD(31)); //设定日初值
write_add(0x05,D_BCD(1)); //设定月初值
write_add(0x06,D_BCD(10)); //设定年初值
// write_add(0x0E,D_BCD(0x20)); //设置DS32C35温度闹钟等参数
// write_add(0x0F,D_BCD(0x0f)); //设置DS32C35输出32KHZ
}
Set()//时间设置
{
uchar Buffer;
*DS_Data=BCD_D(*DS_Data);//BCD码转十进制
if(!Key_Add) //加
{
delay(30);
while(!Key_Add);
if((*DS_Data)<Max)
(*DS_Data)++;
else
(*DS_Data)=Min;
}
if(!Key_Dec) //减
{
delay(30);
while(!Key_Dec);
if((*DS_Data)>Min)
(*DS_Data)--;
else
(*DS_Data)=Max;
}
if(Change) //显示“——”
{
Buffer=*DS_Data;
*DS_Data=0xaa;
disp();
*DS_Data=Buffer;
*DS_Data=D_BCD(*DS_Data);
}
if(!Change)
{
*DS_Data=D_BCD(*DS_Data);
disp();
}
if(!Key_Set)
{
delay(30);
while(!Key_Set);
if(Set_Flag==6)
{
Set_Flag=0;
write32c35();
}
else
{
Set_Flag++;
}
}
if(!Key_Ok)
{
delay(30);
while(!Key_Ok);
Set_Flag=0;
write32c35();
}
}
/*--------------------------------------------------------------*/
//主函数
void main(void)
{
// init_ds32C35();
EN_595=0;
while(1)
{
if(Set_Flag==0)//设置键未按下时候
{
read32c35();//时钟更新
if(!Second)//60秒更新一次温度(0秒时更新)
readtemp();//温度更新
disp();
}
if(!Key_Set)
{
delay(50);
while(!Key_Set);
Set_Flag++;
}
if(Set_Flag==1)//设置"年"
{
Min=10;
Max=20;
DS_Data=&Year;
Set();
}
if(Set_Flag==2)//设置"月"
{
Min=1;
Max=12;
DS_Data=&Month;
Set();
}
if(Set_Flag==3)//设置"日"
{
Min=1;
if((Month==1)|(Month==3)|(Month==5)|(Month==7)|(Month==8)|(Month==10)|(Month==12))// 1、3、5、7、9、10、12月为31天
Max=31;
if((Month==4)|(Month==6)|(Month==9)|(Month==11))//4// 4、6、9、11月为30天
Max=30;
if((BCD_D(Year)%4!=0)&&(Month==2))//非闰年的2月为28天
Max=28;
if((BCD_D(Year)%4==0)&&(Month==2))//闰年的2月为29天
Max=29;
DS_Data=&Day;
Set();
}
if(Set_Flag==4)//设置"小时"
{
Min=0;
Max=23;
DS_Data=&Hour;
Set();
}
if(Set_Flag==5)//设置"分"
{
Min=0;
Max=59;
DS_Data=&Minute;
Set();
}
if(Set_Flag==6)//设置"秒"
{
Min=0;
Max=59;
DS_Data=&Second;
Set();
}
if(Set_Flag)//显示切换条件
{
Change_Num++;
if(Change_Num==20)
Change=0;
if(Change_Num==40)
{
Change=1;
Change_Num=0;
}
}
}
}
自己提取 驱动吧 |
|