单片机源程序如下:
- #include <reg51.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define DS1302_SECOND 0x80 //秒寄存器
- #define DS1302_MINUTE 0x82 //分寄存器
- #define DS1302_HOUR 0x84 //小时寄存器
- #define DS1302_WEEK 0x8A //星期寄存器
- #define DS1302_DAY 0x86 //日寄存器
- #define DS1302_MONTH 0x88 //月寄存器
- #define DS1302_YEAR 0x8C //年寄存器
- #define right 1 //正确
- #define error 0 //错误
- typedef struct SYSTEMTIME
- {
- uchar Second;
- uchar Minute;
- uchar Hour;
- uchar Week;
- uchar Day;
- uchar Month;
- uchar Year;
- uchar DateString[9];
- uchar TimeString[9];
- }SYSTEMTIME; //定义的时间类型
- sbit ACC0=ACC^0;
- sbit ACC7=ACC^7;
- sbit DQ=P1^0; //DS1990A数据线引脚
- sbit SDA=P1^1; //2402数据线引脚
- sbit SCL=P1^2; //2402时钟线引脚
- sbit DS1302_RST=P1^3; //DS1302复位线引脚
- sbit DS1302_CLK=P1^4; //DS1302时钟线引脚
- sbit DS1302_IO=P1^5; //DS1302数据线引脚
- sbit din=P2^0; //MAX7221数据线引脚
- sbit load=P2^1; //MAX7221控制线引脚
- sbit clk=P2^2; //MAX7221时钟线引脚
- sbit Lock=P2^3; //电子锁控制线引脚
- uchar code CrcTable[256]={
- 0,94,188,226,97,63,221,131,194,156,126,32,163,253,31,65,
- 157,195,33,127,252,162,64,30,95,1,227,189,62,96,130,220,
- 35,125,159,193,66,28,254,160,225,191,93,3,128,222,60,98,
- 190,224,2,92,223,129,99,61,124,34,192,158,29,67,161,255,
- 70,24,250,164,39,121,155,197,132,218,56,102,229,187,89,7,
- 219,133,103,57,186,228,6,88,25,71,165,251,120,38,196,154,
- 101,59,217,135,4,90,184,230,167,249,27,69,198,152,122,36,
- 248,166,68,26,153,199,37,123,58,100,134,216,91,5,231,185,
- 140,210,48,110,237,179,81,15,78,16,242,172,47,113,147,205,
- 17,79,173,243,112,46,204,146,211,141,111,49,178,236,14,80,
- 175,241,19,77,206,144,114,44,109,51,209,143,12,82,176,238,
- 50,108,142,208,83,13,239,177,240,174,76,18,145,207,45,115,
- 202,148,118,40,171,245,23,73,8,86,180,234,105,55,213,139,
- 87,9,235,181,54,104,138,212,149,203,41,119,244,170,72,22,
- 233,183,85,11,136,214,52,106,43,117,151,201,74,20,246,168,
- 116,42,200,150,21,75,169,247,182,232,10,84,215,137,107,53
- }; //校验码查询表
- uchar code ID[]={
- 0x01,0x2c,0xc5,0xb8,
- 0x00,0x00,0x00,0x8b}; //默认访问者身份ID
- uchar code dispcode[]={
- 0x7e,0x30,0x6d,0x79,
- 0x33,0x5b,0x5f,0x70,
- 0x7f,0x7b,0x77,0x1f,
- 0x4e,0x3d,0x4f,0x47}; //共阴极显示代码
-
- bit flag=0;
- uchar CRCbyte,num=200,da_ad=0x00; //CRC校验码,2402存储地址
- uchar SN[8],time[6];
- uchar buf[]={0,0,0,0,0,0,0,0};
- SYSTEMTIME time1;
- /******************函数声明*******************/
- void Init_DS1302(void); //DS1302初始化
- void Init_DS1990(void); //DS1990初始化
- void Init_T0(void); //定时器T0初始化
- void DS1302InputByte(uchar d); //DS1302
- void Write_1302(uchar ucAddr, uchar ucDa);//DS1302写数据
- void DS1302_SetProtect(bit flag); //DS1302写保护设定
- void DS1302_SetTime(uchar Address, uchar Value);//DS1302设置时间函数
- void DS1302_GetTime(SYSTEMTIME *Time);//DS1302时间转换函数
- void DS1302_time(void); //DS1302时间显示函数
- void Init_MAX7221(void); //MAX7221初始化
- void Write_7221(uchar com,uchar da);//MAX7221写字节程序
- void Delay(uint i); //延时函数
- void Writebyte(uchar dat); //向DS1990A写一个字节函数
- void Record(void); //记录访问时间
- void Start_bit(void); //I2C起始函数
- void Stop_bit(void); //I2C停止函数
- bit Compare(void); //验证身份函数
- bit Read1990(void); //读身份信息函数
- bit Write_8bit(uchar ch); //I2C总线写8位数据函数
- uchar DS1302OutputByte(void); //DS1302读一个字节
- uchar Read1302(uchar ucAddr); //DS1302读数据
- uchar CRC(uchar j); //DS1990A校验位计算函数
- uchar Readbyte(void); //从DS1990A读一个字节函数
- uchar Page_wr(uchar firstw_ad,uchar counter,uchar *firstr_ad);//I2C总线页面写函数
- /******************主函数*******************/
- void main()
- {
- uchar i;
- Init_MAX7221();
- Init_DS1302();
- Init_T0();
- P2=0;
- while (1)
- {
- if(Compare()==1) //身份验证一致
- {
- Lock=1; //闭合继电器
- TR0=1; //定时器T0启动
- Record(); //记录访问时间
- for(i=1;i<9;i++)
- {
- Write_7221(i,0x01);
- }
- if(da_ad==248)
- da_ad=0; //判断存储内容是否已经满
- else
- da_ad+=8; //修改2402存储地址
- while(Compare());
- }
- else
- {
- DS1302_time(); //显示当前时间
- }
- }
- }
- /**************T0定时器初始化******************/
- void Init_T0(void)
- {
- TMOD=0x01; //工作方式1
- TH0=(65536-50000)/256; //定时时间为0.5ms
- TL0=(65536-50000)%256;
- EA=1; //开总中断
- ET0=1; //允许定时器T0中断
- }
- /**************T0定时器服务程序******************/
- void timer0(void) interrupt 1
- {
- TH0=(65536-50000)/256; //重载初值
- TL0=(65536-50000)%256;
- num--;
- if(num==0) //5秒定时到
- {
- TR0=0; //关定时器T0
- num=200; //重载时间计数器
- Lock=0; //断开继电器
- }
- }
- /**************DS1302一个写字节******************/
- void DS1302InputByte(uchar d) //实时时钟写入一字节(内部函数)
- {
- uchar i;
- ACC=d;
- for (i=8;i>0;i--)
- {
- DS1302_IO=ACC0; //相当于汇编中的 RRC
- DS1302_CLK=1;
- DS1302_CLK=0; //发一个高跳变到低的脉冲
- ACC=ACC>>1;
- }
- }
- /**************DS1302读一个字节******************/
- uchar DS1302OutputByte(void) //实时时钟读取一字节(内部函数)
- {
- uchar i;
- for (i=8;i>0;i--)
- {
- ACC=ACC>>1; //相当于汇编中的 RRC
- ACC7=DS1302_IO;
- DS1302_CLK=1;
- DS1302_CLK=0; //发一个高跳变到低的脉冲
- }
- return(ACC);
- }
- /****************DS1302写数据********************/
- void Write_1302(uchar ucAddr, uchar ucDa)
- {
- DS1302_RST=0;
- DS1302_CLK=0;
- DS1302_RST=1;
- DS1302InputByte(ucAddr); //地址,命令
- DS1302InputByte(ucDa); //写1Byte数据
- DS1302_CLK=1;
- DS1302_RST=0;
- }
- /****************DS1302读数据********************/
- uchar Read1302(uchar ucAddr) //读取DS1302某地址的数据
- {
- uchar ucData;
- DS1302_RST=0;
- DS1302_CLK=0;
- DS1302_RST=1; //enable
- DS1302InputByte(ucAddr|0x01); //地址,命令
- ucData=DS1302OutputByte(); //读1Byte数据
- DS1302_CLK=1;
- DS1302_RST=0;
- return(ucData);
- }
- /**************DS1302写保护设定******************/
- void DS1302_SetProtect(bit flag) //是否写保护
- {
- if (flag)
- Write_1302(0x8E,0x10); //WP=1,不能写入
- else
- Write_1302(0x8E,0x00); //WP=0,可以写入
- }
- /**************DS1302设置时间函数****************/
- void DS1302_SetTime(uchar Address, uchar Value)
- {
- DS1302_SetProtect(0);
- Write_1302(Address, ((Value/10)<<4|(Value%10)));//高4位为十位,低4位为个位
- }
- /*****************DS1302初始化******************/
- void Init_DS1302(void)
- {
- uchar Second=Read1302(DS1302_SECOND);
- if (Second&0x80) //如果第七为1(表明没有启动), 则启动时钟
- DS1302_SetTime(DS1302_SECOND,0);
- }
- /**************DS1302时间转换函数***************/
- void DS1302_GetTime(SYSTEMTIME *Time)
- {
- uchar ReadValue;
- ReadValue=Read1302(DS1302_SECOND);
- Time->Second=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); //转换秒
- ReadValue=Read1302(DS1302_MINUTE);
- Time->Minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); //转换分
- ReadValue=Read1302(DS1302_HOUR);
- Time->Hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); //转换时
- ReadValue=Read1302(DS1302_DAY);
- Time->Day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); //转换日
- ReadValue=Read1302(DS1302_WEEK);
- Time->Week=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); //转换星期
- ReadValue=Read1302(DS1302_MONTH);
- Time->Month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); //转换月
- ReadValue=Read1302(DS1302_YEAR);
- Time->Year=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); //转换年
- }
- /*****************MAX7221初始化***************/
- void Init_MAX7221(void)
- {
- Write_7221(0x0c,0x01); //正常工作状态,关断模式
- Write_7221(0x09,0x00); //译码选择,非BCD码
- Write_7221(0x0a,0x0f); //亮度调节
- Write_7221(0x0b,0x07); //显示位数
- }
- /**************MAX7221写字节程序*************/
- void Write_7221(uchar com,uchar da)
- {
- uchar temp,i,j;
- load=0;
- clk=0;
- for (i=0;i<8;i++) //发送命令
- {
- temp=com;
- if ((temp&(0x80>>i))!=0)
- din=1;
- else din=0;
- clk=1;
- for (j=0;j<5;j++);
- clk=0;
- }
- for (i=0;i<8;i++) //发送数据
- {
- temp=da;
- if ((temp&(0x80>>i))!=0)
- din=1;
- else din=0;
- clk=1;
- for (j=0;j<5;j++);
- clk=0;
- }
- load=1;
- }
- /**************时间显示函数*******************/
- void DS1302_time(void)
- {
- DS1302_GetTime(&time1); //获取当前时间
- buf[7]=(time1.Second)%10;
- buf[6]=(time1.Second)/10;
- buf[4]=(time1.Minute)%10;
- buf[3]=(time1.Minute)/10;
- buf[1]=(time1.Hour)%10;
- buf[0]=(time1.Hour)/10;
- Write_7221(0x08,dispcode[buf[7]]);
- Write_7221(0x07,dispcode[buf[6]]);
- Write_7221(0x06,0x01);
- Write_7221(0x05,dispcode[buf[4]]);
- Write_7221(0x04,dispcode[buf[3]]);
- Write_7221(0x03,0x01);
- Write_7221(0x02,dispcode[buf[1]]);
- Write_7221(0x01,dispcode[buf[0]]);
- }
- /**************I2C起始函数*******************/
- void Start_bit(void)
- {
- SCL=1;_nop_();
- SDA=1;_nop_();
- SDA=0;_nop_();
- SCL=0;_nop_();
- }
- /***************I2C停止函数******************/
- void Stop_bit(void)
- {
- SDA=0;_nop_();
- SCL=1;_nop_();
- SDA=1;_nop_();
- }
- /***********I2C总线写8位数据函数*************/
- bit Write_8bit(uchar ch)
- {
- uchar i=8;
- bit fan_w;
- SCL=0;_nop_();
- while (i--)
- {
- SDA=(bit)(ch&0x80);_nop_();
- ch<<=1;
- SCL=1;_nop_();
- SCL=0;_nop_();
- }
- SDA=1;_nop_();
- SCL=1;_nop_();
- fan_w=SDA;
- SCL=0;_nop_();
- return(fan_w);
- }
- /************I2C总线页面写函数**************/
- uchar Page_wr(uchar firstw_ad,uchar counter,uchar *firstr_ad)
- {
- uchar *ufirstr_ad;
- ufirstr_ad=firstr_ad;
- Start_bit(); //启动I2C
- if (Write_8bit(0xA0)!=0) //发送2402器件地址
- {
- Stop_bit(); //无应答,返回
- return(0);
- }
- if (Write_8bit(firstw_ad)!=0) //写入数据的存储地址
- {
- Stop_bit(); //无应答,返回
- return(0);
- }
- while (counter--) //写入数据
- {
- if (Write_8bit(*ufirstr_ad)!=0) //无应答,返回
- {
- Stop_bit();
- return(0);
- }
- ufirstr_ad++; //准备下一数据
- }
- Stop_bit();
- return(1); //写数据成功
- }
- /*****************延时函数******************/
- void Delay(uint i)
- {
- while (i--);
- }
- /***********DS1990A校验位计算函数***********/
- uchar CRC(uchar j)
- {
- uchar i,crc_data=0;
- for (i=0;i<j;i++) //查表校验
- crc_data=CrcTable[crc_data^SN[i]];
- return(crc_data);
- }
- /*************DS1990A初始化函数*************/
- void Init_DS1990(void)
- {
- uchar i,x=0;
- DQ=0; //置低
- Delay(60); //延时480us
- DQ=1; //释放
- Delay(10); //延时85us
- for (i=0;i<10;i++)
- {
- if (DQ==0) //如果拉低
- {
- flag=1;
- break;
- }
- }
- Delay(20);
- }
- /***********从DS1990A读一个字节函数*********/
- uchar Readbyte(void)
- {
- uchar i=0;
- uchar temp=0;
- for (i=0;i<8;i++)
- {
- DQ=0;
- temp>>=1;
- DQ=1;
- _nop_();
- if (DQ)temp|=0x80;
- Delay(8);
- }
- return(temp);
- }
- /**********向DS1990A写一个字节函数**********/
- void Writebyte(uchar dat)
- {
- uchar i=0,send;
- for (i=0;i<8;i++)
- {
- DQ=0;
- send=dat&0x01;
- if (send==0x01)
- {
- DQ=1;
- Delay(15);
- }
- else
- {
- Delay(15);
- DQ=1;
- }
- dat>>=1;
- }
- Delay(8);
- }
- /*************读身份信息函数****************/
- bit Read1990(void)
- {
- uchar i;
- Init_DS1990();
- if (flag==1)
- {
- while (DQ==0);
- flag=0;
- Writebyte(0x33);
- for (i=0;i<8;i++)
- SN[i]=Readbyte();
- CRCbyte=CRC(7);
- if (CRCbyte==SN[7])
- {
- return(right);
- }
- else
- return(error);
- }
- else
- return(error);
- }
- /****************验证身份函数***************/
- bit Compare(void)
- {
- uchar i;
- if (Read1990()==1) //若身份验证正确返回1,错误返回0
- {
- for (i=0;i<8;i++)
- {
- if (SN[i]!=ID[i])return(error);
- }
- return(right);
- }
- else
- return(error);
- }
- /****************记录访问时间***************/
- void Record(void)
- {
- DS1302_GetTime(&time1); //获取访问时间
- time[0]=time1.Second; //将访问时间信息存入缓冲区
- time[1]=time1.Minute;
- time[2]=time1.Hour;
- time[3]=time1.Day;
- time[4]=time1.Month;
- time[5]=time1.Year;
- while(Page_wr(da_ad,6,time)==0); //等待写入成功
- }
复制代码
所有资料51hei提供下载:
出入管理系统.zip
(62.01 KB, 下载次数: 8)
|