新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 門禁系統項目驅動程序

        門禁系統項目驅動程序

        作者: 時間:2016-11-30 來源:網絡 收藏
        /*****************************************************************************

        門禁系統項目驅動程序

        本文引用地址:http://www.104case.com/article/201611/323636.htm

        (1)晶振 11.0592MHZ
        (2)芯片 DS1302,AT24C64,HEF4053BP
        (3)ZIMO21.EXE縱向、字節倒序取字模
        (4)完整代碼下載(包含頭文件):http://www.51hei.com/f/12154f.rar
        *****************************************************************************/
        #include "reg51.h"
        #include "intrins.h"
        #include "7041_Door.h"http://字模

        #define LCD_DATA P1//液晶屏數據輸入
        #define EEAddr EAddr.All//AT24C64片內地址
        #define EAddrH EAddr.array[0]
        #define EAddrL EAddr.array[1]

        #define uchar unsigned char
        #define uint unsigned int

        union Add{ //定義EEPROM地址
        uint All;
        uchar array[2];
        }EAddr;

        uchar Sto = 1,Del = 0;
        uint DelCount;//定時器中斷中用于延時的變量DelCount
        uchar Function = 0;//按鍵功能變量Function
        uchar SCount = 0;//串行中斷中用于計數卡號信息的循環變量
        bit TimeDisFlag = 0,KEndFlag = 0,StoreFlag = 0,DeleteFlag = 0,SwitchFlag = 0,WXFlag = 0,NSK12Flag = 0;//控制時間顯示標志位TimeDisFlag,14位卡號接收完的標志KEndFlag
        uchar CardNo[14] = {0},GetTime[7],RD24C64[32] = 0,CardMax = 0,CardNum = 0;//存儲讀到的卡號CardNo[14],存儲從1302讀到的時間GetTime[7],存入卡的個數CardMax

        /*---------------------------------定義P口-----------------------------------*/

        sbit LCD_RS = P2^7; //LCD12864
        sbit LCD_RW = P2^6;
        sbit LCD_E = P2^5;
        sbit LCD_CS1 = P2^4;
        sbit LCD_CS2 = P2^3;
        sbit Busy = P1^7;
        sbit Motor2 = P3^7;
        sbit Motor1 = P3^6;
        sbit SDA_24C64 = P3^5;//AT24C64
        sbit SCL_24C64 = P3^4;
        sbit CLK_1302 = P2^2;//DS1302
        sbit IO_1302 = P2^1;
        sbit RST_1302 = P2^0;
        sbit RS_485 = P3^2;//485R/S,其為1時允許發送,為0時允許接收
        sbit CON_4053 = P3^3;//通信控制,其為1時讀卡,為0時485通信
        sbit KEY1 = P0^0;//定義按鍵
        sbit KEY2 = P0^1;
        sbit KEY3 = P0^2;
        sbit KEY4 = P0^3;

        /***************************液晶屏驅動程序*********************************/

        void LCD_BusyCheck(bit BCS){//檢測忙子程序
        LCD_DATA = 0xff;//LCD_RS = 0,LCD_RW = 1,LCD_E = 高電平。
        LCD_RS = 0;
        LCD_RW = 1;
        if(BCS){//檢測片1忙狀態
        LCD_CS1 = 1;
        LCD_E = 1;
        while(Busy);
        LCD_E = 0;
        LCD_CS1 = 0;
        }
        else{//檢測片2忙狀態
        LCD_CS2 = 1;
        LCD_E = 1;
        while(Busy);
        LCD_E = 0;
        LCD_CS2 = 0;
        }
        }
        void LCD_Write_Code(uchar WCode,bit CS){//寫指令子程序
        LCD_BusyCheck(CS);//調用忙檢測子程序:寫前檢測
        LCD_DATA = WCode;
        LCD_RS = 0;//LCD_RS = 0,LCD_RW = 0,LCD_E = 高脈沖。
        LCD_RW = 0;
        if(CS){//檢測片1忙狀態
        LCD_CS1 = 1;
        LCD_E = 1;
        _nop_();
        LCD_E = 0;
        LCD_CS1 = 0;
        }
        else{//檢測片2忙狀態
        LCD_CS2 = 1;
        LCD_E = 1;
        _nop_();
        LCD_E = 0;
        LCD_CS2 = 0;
        }
        }
        void LCD_Write_Data(uchar WData,uchar CS){//寫數據子程序
        LCD_BusyCheck(CS);//調用忙檢測子程序:寫前忙狀態檢測
        LCD_DATA = WData;
        LCD_RS = 1;//LCD_RS = 1,LCD_RW = 0,LCD_E = 高脈沖。
        LCD_RW = 0;
        if(CS){//檢測片1忙狀態
        LCD_CS1 = 1;
        LCD_E = 1;
        _nop_();
        LCD_E = 0;
        LCD_CS1 = 0;
        }
        else{//檢測片2忙狀態
        LCD_CS2 = 1;
        LCD_E = 1;
        _nop_();
        LCD_E = 0;
        LCD_CS2 = 0;
        }
        }
        void LCD_Write(uchar xpos,uchar ypos,uchar WData){//寫屏子(地址轉換)程序
        uchar WCS;
        if(xpos < 64)WCS = 1;//判斷將要操作片1或片2:WCS = 1操作LCD_CS1
        else WCS = 0;//WCS = 2 操作LCD_CS2
        ypos &= 0x07;//頁地址轉換
        ypos |= 0xb8;
        LCD_Write_Code(ypos,WCS);//寫入頁地址到對應片
        xpos &= 0x3f;//列地址轉換
        xpos |= 0x40;
        LCD_Write_Code(xpos,WCS);//寫入列地址到對應片
        LCD_Write_Data(WData,WCS);//寫入數據到對應片
        }
        void LCD_Data_DisWord(uchar xpos,uchar ypos,uchar array[]){//漢字顯示子程序:12*16
        uchar Cnt = 0,x = 0,y = 0;
        for(y = ypos;y < ypos + 2;y ++){
        for(x = xpos;x < xpos + 12;x ++,Cnt ++)
        LCD_Write(x,y,array[Cnt]);//調用寫屏子程序:在對應的地址上寫入要顯示的內容
        }
        }
        void LCD_Data_DisNum(uchar xpos,uchar ypos,uchar array[]){//數字及符號顯示子程序:6*16
        uchar Cnt = 0,x = 0,y = 0;
        for(y = ypos;y < ypos + 2;y ++){
        for(x = xpos;x < xpos + 6;x ++,Cnt ++)
        LCD_Write(x,y,array[Cnt]);//調用寫屏子程序:在對應的地址上寫入要顯示的內容
        }
        }
        void LCD_All_Clear(void){//清屏子程序:全屏清0
        uchar x,y;
        for(y = 0;y < 8;y ++)
        for(x = 0;x < 128;x ++)
        LCD_Write(x,y,0x00);//調用寫屏子程序:全屏寫0
        }
        void LCD_Page_Clear(uchar yPage){//清屏子程序:清除以所給頁坐標為起始的兩頁的內容
        uchar x,y;
        for(y = yPage;y < yPage + 2;y ++)
        for(x = 0;x < 128;x ++)
        LCD_Write(x,y,0x00);//調用寫屏子程序:以所給頁坐標為起始的兩頁寫0
        }
        void LCD_Reset(void){//液晶屏初始化設置
        LCD_E = 0;
        LCD_Write_Code(0x3f,1);//開片1顯示
        LCD_Write_Code(0x3f,0);//開片2顯示
        LCD_Write_Code(0xc0,1);//設片1起始行顯示
        LCD_Write_Code(0xc0,0);//設片2起始行顯示
        }

        /******************************DS1302時鐘程序*******************************/

        void DS1302_WriteByte(uchar WData){ //寫入一個字節
        uchar Cnt;
        for(Cnt=0;Cnt<8;Cnt++){
        WData >>= 1;//寫入數據時先寫低位再寫高位(D0---D7)
        CLK_1302 = 0;
        IO_1302 = CY;
        CLK_1302 = 1; //上升沿將數據寫入1302
        }
        }
        uchar DS1302_ReadByte(){ //讀出一個字節
        uchar Cnt,RData = 0;
        for(Cnt = 0;Cnt < 8;Cnt ++){
        RData >>= 1;//讀數據時先讀低位再讀高位(D0---D7)
        CLK_1302 = 1;
        CLK_1302 = 0; //下降沿將數據讀出來
        if(IO_1302)
        RData |= 0x80;
        elseRData &= 0x7f;
        }
        return RData;
        }
        void DS1302_WriteData(uchar Waddr,uchar Wdata){ //向某地址中寫入一個字節的數據
        RST_1302 = 0;
        CLK_1302 = 0;
        RST_1302 = 1;
        DS1302_WriteByte(Waddr);//寫入地址
        DS1302_WriteByte(Wdata);//寫入數據
        CLK_1302 = 0;
        RST_1302 = 0;
        }
        uchar DS1302_ReadData(uchar RAddr){ //讀取1302某地址中一個字節的數據
        uchar Rdata;
        RST_1302 = 0;
        CLK_1302 = 0;
        RST_1302 = 1;
        DS1302_WriteByte(RAddr);//寫入讀取數據的地址
        Rdata = DS1302_ReadByte();//讀取數據
        RST_1302 = 0;
        IO_1302 = 1;
        return(Rdata);
        }
        void DS1302_SetTime(){ //設置1302時間
        uchar Cnt,Add = 0x80;//秒 寄存器的寫地址0x80
        // 秒 分 時 日 月 星期 年
        uchar STime[7] = {0x00,0x19,0x14,0x18,0x07,5,0x08};

        DS1302_WriteData(0x8e,0x00);//禁止寫保護(可寫入數據)
        for(Cnt = 0;Cnt < 7;Cnt ++,Add += 2)//循環寫入秒,分,時,日,月,星期,年
        DS1302_WriteData(Add,STime[Cnt]);
        DS1302_WriteData(0x8e,0x80);//寫保護(不能寫入數據)
        }
        void DS1302_GetTime(){ //讀取1302中當前時間
        uchar Cnt,Addr = 0x81;//秒 寄存器的讀地址0x81
        for(Cnt = 0;Cnt < 7;Cnt ++,Addr += 2)//循環讀取秒,分,時,日,月,星期,年
        GetTime[Cnt] = DS1302_ReadData(Addr);
        }

        /**************************液晶屏顯示程序******************************/

        void LCD_DisTime(){//顯示從1302讀取的時間
        DS1302_GetTime();
        LCD_Data_DisNum(32,0,num[GetTime[6] >> 4]);//年(由1302循環讀出顯示)
        LCD_Data_DisNum(38,0,num[GetTime[6] & 0x0f]);
        LCD_Data_DisNum(50,0,num[GetTime[4] >> 4]);//月
        LCD_Data_DisNum(56,0,num[GetTime[4] & 0x0f]);
        LCD_Data_DisNum(68,0,num[GetTime[3] >> 4]);//日
        LCD_Data_DisNum(74,0,num[GetTime[3] & 0x0f]);
        LCD_Data_DisNum(122,0,num[GetTime[5]]);//星期
        LCD_Data_DisNum(32,2,num[GetTime[2] >> 4]);//時
        LCD_Data_DisNum(38,2,num[GetTime[2] & 0x0f]);
        LCD_Data_DisNum(50,2,num[GetTime[1] >> 4]);//分
        LCD_Data_DisNum(56,2,num[GetTime[1] & 0x0f]);
        LCD_Data_DisNum(68,2,num[GetTime[0] >> 4]);//秒
        LCD_Data_DisNum(74,2,num[GetTime[0] & 0x0f]);
        }
        void LCD_DisCell(){//顯示固定不變的內容(日期,時間等漢字及符號的顯示)(圖1~4)
        LCD_Data_DisWord(2,0,ri);
        LCD_Data_DisWord(14,0,qi);
        LCD_Data_DisNum(26,0,maohao);
        LCD_Data_DisNum(44,0,heng);
        LCD_Data_DisNum(62,0,heng);
        LCD_Data_DisWord(92,0,xing);
        LCD_Data_DisWord(104,0,qi);
        LCD_Data_DisNum(116,0,maohao);
        LCD_Data_DisWord(2,2,shi);
        LCD_Data_DisWord(14,2,jian);
        LCD_Data_DisNum(26,2,maohao);
        LCD_Data_DisNum(44,2,heng);
        LCD_Data_DisNum(62,2,heng);
        }
        void LCD_Display1(){//無操作狀態時顯示內容
        LCD_DisCell();
        LCD_Data_DisWord(34,4,wu);//無操作狀態
        LCD_Data_DisWord(46,4,cao);
        LCD_Data_DisWord(58,4,zuo);
        LCD_Data_DisWord(70,4,zhuang);
        LCD_Data_DisWord(82,4,tai);
        }
        void LCD_Display2(){//刷卡后顯示此卡有效或無效
        LCD_Data_DisWord(2,4,ka);//顯示刷卡后的卡號
        LCD_Data_DisWord(14,4,hao);
        LCD_Data_DisNum(26,4,maohao);
        }
        void LCD_Display3(){//顯示電機狀態:打開或關閉
        //LCD_DisCell();//顯示固定不變的內容
        LCD_Data_DisWord(2,4,dian);//電機狀態
        LCD_Data_DisWord(14,4,ji);
        LCD_Data_DisWord(26,4,zhuang);
        LCD_Data_DisWord(38,4,tai);
        LCD_Data_DisNum(50,4,maohao);
        }
        void LCD_Display4(){//顯示數據上傳過程:上傳成功或失敗
        LCD_Data_DisWord(2,4,shu);//數據上傳
        LCD_Data_DisWord(14,4,ju);
        LCD_Data_DisWord(26,4,shang);
        LCD_Data_DisWord(38,4,chuan);
        LCD_Data_DisNum(50,4,maohao);

        LCD_Data_DisWord(56,4,kuang1);
        LCD_Data_DisWord(68,4,kuang1);
        LCD_Data_DisWord(80,4,kuang1);
        LCD_Data_DisWord(92,4,kuang1);
        LCD_Data_DisWord(104,4,kuang1);
        LCD_Data_DisWord(116,4,kuang1);

        LCD_Data_DisWord(35,6,cheng);
        LCD_Data_DisWord(47,6,gong);

        LCD_Data_DisWord(75,6,shibai);
        LCD_Data_DisWord(87,6,bai);
        }
        void LCD_Display5(){//顯示存卡過程:存入或取消存儲
        LCD_Data_DisWord(2,0,cun);//存卡
        LCD_Data_DisWord(14,0,ka);
        LCD_Data_DisWord(2,2,ka);//卡號
        LCD_Data_DisWord(14,2,hao);
        LCD_Data_DisNum(26,2,maohao);
        }
        void LCD_Display6(){//顯示卡號刪除過程:確認刪除或取消刪除
        LCD_Data_DisWord(2,0,liu);//瀏覽卡號
        LCD_Data_DisWord(14,0,lan);
        LCD_Data_DisWord(26,0,ka);
        LCD_Data_DisWord(38,0,hao);
        LCD_Data_DisWord(2,2,ka);//卡號顯示
        LCD_Data_DisWord(14,2,hao);
        LCD_Data_DisNum(26,2,maohao);
        LCD_Data_DisWord(35,4,shan);
        LCD_Data_DisWord(47,4,chu);
        LCD_Data_DisWord(75,4,qu);
        LCD_Data_DisWord(87,4,quxiao);
        }

        /******************************AT24C64存儲程序*******************************/

        void I2C_Start(void){//I2C總線啟動
        SCL_24C64 = 1;
        _nop_();
        SDA_24C64 = 1;
        _nop_();
        SDA_24C64 = 0;
        }
        void I2C_Stop(void){//I2C總線通信結束
        SCL_24C64 = 0;
        SDA_24C64 = 0;
        _nop_();
        SCL_24C64 = 1;
        SDA_24C64 = 1;
        }
        void I2C_ACK_Send(bit ack){//發送返回幀
        SDA_24C64 = ack;
        SCL_24C64 = 1;
        _nop_();
        SCL_24C64 = 0;
        SDA_24C64 = 1;//釋放總線
        }
        bit I2C_ACK_Receive(){//接收返回幀
        bit ACKR;
        SDA_24C64 = 1;//釋放總線
        SCL_24C64 = 1;
        _nop_();
        ACKR = SDA_24C64;
        SCL_24C64 = 0;
        return ACKR;
        }
        void I2C_SendByte(uchar WData){//寫入一個字節的數據
        uchar Count;
        SCL_24C64 = 0;
        for(Count = 0;Count < 8;Count ++){
        WData <<= 1;
        SDA_24C64 = CY;
        SCL_24C64 = 1;//下降沿寫入數據
        _nop_();
        SCL_24C64 = 0;
        }
        }
        uchar I2C_ReceiveByte(){//讀出一個字節的數據
        uchar Count,RData;
        SCL_24C64 = 0;
        for(Count = 0;Count < 8;Count ++){
        RData <<= 1;
        SCL_24C64 = 1;//高電平讀出數據
        _nop_();
        if(SDA_24C64)
        RData |= 0x01;
        elseRData &= 0xfe;
        SCL_24C64 = 0;
        }
        return RData;
        }
        void I2C_Write_AT24C64(uchar WAddrH,uchar WAddrL,uchar *Point,uchar WNum){//向WAddrH,WAddrL為首地址的頁中寫入WNum個字節
        bit ACK;uchar Cnt;
        I2C_Start();//啟動通信
        do{
        I2C_SendByte(0xa0);//AT24C64的寫地址
        ACK = I2C_ACK_Receive();
        }while(ACK);
        do{
        I2C_SendByte(WAddrH); //寫字節高地址
        ACK = I2C_ACK_Receive();
        }while(ACK);
        do{
        I2C_SendByte(WAddrL); //寫字節低地址
        ACK = I2C_ACK_Receive();
        }while(ACK);
        for(Cnt = 0;Cnt < WNum;Cnt ++,Point ++){//循環寫入WNum個字節
        do{
        I2C_SendByte(*Point); //寫的內容
        ACK = I2C_ACK_Receive();
        }while(ACK);
        }
        I2C_Stop(); //通信結束
        }
        uchar I2C_Read_AT24C64(uchar WAddrH,uchar WAddrL,uchar RNum){//從WAddrH,WAddrL為首地址的頁中讀取RNum個字節
        uchar Cnt;//一頁最多32個字節
        bit ACK;
        I2C_Start();//啟動通信
        do{
        I2C_SendByte(0xa0);//AT24C64的寫地址
        ACK = I2C_ACK_Receive();
        }while(ACK);
        do{
        I2C_SendByte(WAddrH);//寫入地址的高5位
        ACK = I2C_ACK_Receive();
        }while(ACK);
        do{
        I2C_SendByte(WAddrL);//寫入地址的低8位
        ACK = I2C_ACK_Receive();
        }while(ACK);
        I2C_Start();//再次啟動通信
        do{
        I2C_SendByte(0xa1);//AT24C64的讀地址
        ACK = I2C_ACK_Receive();
        }while(ACK);
        for(Cnt = 0;Cnt < RNum;Cnt ++){//循環讀取RNum個字節
        RD24C64[Cnt] = I2C_ReceiveByte();
        if(Cnt != RNum - 1)
        I2C_ACK_Send(0);
        }
        I2C_ACK_Send(1);//讀取最后一個字節的數據后的返回幀
        I2C_Stop();//通信結束
        }
        void AT24C64Init(){//24C64初始化
        //I2C_Write_AT24C64(0x00,0x1f,&CardMax,1);//將存儲卡的最大數目初始化為0
        //I2C_Write_AT24C64(0x00,0x1e,&CardNum,1);//將存儲卡的數目初始化為0
        I2C_Read_AT24C64(0x00,0x1f,1);//讀取0x00,0x1f地址中的內容,其為存儲卡過程中曾存卡的最多個數
        CardMax = RD24C64[0];//將讀取的數據存入卡數目最大值變量CardMax中
        I2C_Read_AT24C64(0x00,0x1e,1);//讀取0x00,0x1e地址中的內容,其為存儲卡的數目
        CardNum = RD24C64[0];//將讀取的數據存入卡數目變量CardNum中
        EEAddr = 0x0000;//將24C64的地址初始化到首地址
        }


        上一頁 1 2 下一頁

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 治多县| 松阳县| 英超| 长岭县| 通江县| 永德县| 亳州市| 惠州市| 嘉峪关市| 晋江市| 乐山市| 滦平县| 迁西县| 安溪县| 曲阜市| 德庆县| 新野县| 南漳县| 会昌县| 木兰县| 达日县| 焦作市| 乌审旗| 崇文区| 凌海市| 景东| 大荔县| 庆安县| 南木林县| 嵊州市| 会泽县| 宿松县| 梁平县| 穆棱市| 澄城县| 大名县| 牡丹江市| 慈溪市| 云霄县| 沅江市| 洛宁县|