單片機源程序如下:
- #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)
2019-3-12 08:19 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|