電子產業(yè)一站式賦能平臺

PCB聯(lián)盟網

搜索
查看: 2855|回復: 1
收起左側

單片機C語言實例-352-將按鍵次數(shù)寫入AT24C02,再讀出并用1602LCD顯示

[復制鏈接]
跳轉到指定樓層
樓主
發(fā)表于 2022-3-31 10:45:26 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
單片機C語言實例-352-將按鍵次數(shù)寫入AT24C02,再讀出并用1602LCD顯示

//實例86:將按鍵次數(shù)寫入AT24C02,再讀出并用1602LCD顯示
#include<reg51.h>       //包含單片機寄存器的頭文件
#include<intrins.h>     //包含_nop_()函數(shù)定義的頭文件
sbit RS=P2^0;           //寄存器選擇位,將RS位定義為P2.0引腳
sbit RW=P2^1;           //讀寫選擇位,將RW位定義為P2.1引腳
sbit E=P2^2;            //使能信號位,將E位定義為P2.2引腳
sbit BF=P0^7;           //忙碌標志位,,將BF位定義為P0.7引腳
sbit S=P1^4;            //將S位定義為P1.4引腳
#define        OP_READ        0xa1        // 器件地址以及讀取操作,0xa1即為1010 0001B
#define        OP_WRITE 0xa0        // 器件地址以及寫入操作,0xa1即為1010 0000B
sbit SDA=P3^4;          //將串行數(shù)據(jù)總線SDA位定義在為P3.4引腳
sbit SCL=P3^3;          //將串行時鐘總線SDA位定義在為P3.3引腳
unsigned char code digit[ ]={"0123456789"}; //定義字符數(shù)組顯示數(shù)字
/*****************************************************
函數(shù)功能:延時1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以認為是1毫秒
***************************************************/
void delay1ms()
{
   unsigned char i,j;       
         for(i=0;i<10;i++)
          for(j=0;j<33;j++)
           ;                 
}
/*****************************************************
函數(shù)功能:延時若干毫秒
入口參數(shù):n
***************************************************/
void delaynms(unsigned char n)
{
   unsigned char i;
        for(i=0;i<n;i++)
           delay1ms();
}
/*******************************************************************************
以下是對液晶模塊的操作程序
********************************************************************************/
/*****************************************************
函數(shù)功能:判斷液晶模塊的忙碌狀態(tài)
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
unsigned char BusyTest(void)
  {
    bit result;
        RS=0;       //根據(jù)規(guī)定,RS為低電平,RW為高電平時,可以讀狀態(tài)
    RW=1;
    E=1;        //E=1,才允許讀寫
    _nop_();   //空操作
    _nop_();
    _nop_();
    _nop_();   //空操作四個機器周期,給硬件反應時間       
    result=BF;  //將忙碌標志電平賦給result
   E=0;         //將E恢復低電平
   return result;
  }
/*****************************************************
函數(shù)功能:將模式設置指令或顯示地址寫入液晶模塊
入口參數(shù):dictate
***************************************************/
void WriteInstruction (unsigned char dictate)
{   
    while(BusyTest()==1);   //如果忙就等待
         RS=0;                  //根據(jù)規(guī)定,RS和R/W同時為低電平時,可以寫入指令
         RW=0;   
         E=0;                   //E置低電平(根據(jù)表8-6,寫指令時,E為高脈沖,
                            // 就是讓E從0到1發(fā)生正跳變,所以應先置"0"
         _nop_();
         _nop_();               //空操作兩個機器周期,給硬件反應時間
         P0=dictate;            //將數(shù)據(jù)送入P0口,即寫入指令或地址
         _nop_();
         _nop_();
         _nop_();
         _nop_();               //空操作四個機器周期,給硬件反應時間
         E=1;                   //E置高電平
         _nop_();
         _nop_();
         _nop_();
         _nop_();               //空操作四個機器周期,給硬件反應時間
          E=0;                  //當E由高電平跳變成低電平時,液晶模塊開始執(zhí)行命令
}
/*****************************************************
函數(shù)功能:指定字符顯示的實際地址
入口參數(shù):x
***************************************************/
void WriteAddress(unsigned char x)
{
     WriteInstruction(x|0x80); //顯示位置的確定方法規(guī)定為"80H+地址碼x"
}
/*****************************************************
函數(shù)功能:將數(shù)據(jù)(字符的標準ASCII碼)寫入液晶模塊
入口參數(shù):y(為字符常量)
***************************************************/
void WriteData(unsigned char y)
{
    while(BusyTest()==1);  
          RS=1;           //RS為高電平,RW為低電平時,可以寫入數(shù)據(jù)
          RW=0;
          E=0;            //E置低電平(根據(jù)表8-6,寫指令時,E為高脈沖,
                       // 就是讓E從0到1發(fā)生正跳變,所以應先置"0"
          P0=y;           //將數(shù)據(jù)送入P0口,即將數(shù)據(jù)寫入液晶模塊
          _nop_();
          _nop_();
          _nop_();
     _nop_();       //空操作四個機器周期,給硬件反應時間
          E=1;          //E置高電平
          _nop_();
          _nop_();
          _nop_();
         _nop_();        //空操作四個機器周期,給硬件反應時間
         E=0;            //當E由高電平跳變成低電平時,液晶模塊開始執(zhí)行命令
}
/*****************************************************
函數(shù)功能:對LCD的顯示模式進行初始化設置
***************************************************/
void LcdInitiate(void)
{
    delaynms(15);               //延時15ms,首次寫指令時應給LCD一段較長的反應時間
    WriteInstruction(0x38);     //顯示模式設置:16×2顯示,5×7點陣,8位數(shù)據(jù)接口
        delaynms(5);                //延時5ms ,給硬件一點反應時間
    WriteInstruction(0x38);
        delaynms(5);
        WriteInstruction(0x38);     //連續(xù)三次,確保初始化成功
        delaynms(5);
        WriteInstruction(0x0c);     //顯示模式設置:顯示開,無光標,光標不閃爍
        delaynms(5);
        WriteInstruction(0x06);     //顯示模式設置:光標右移,字符不移
        delaynms(5);
        WriteInstruction(0x01);     //清屏幕指令,將以前的顯示內容清除
        delaynms(5);

}
/***************************************************
函數(shù)功能:顯示小時                          
***************************************************/
void Display(unsigned char x)
{
   unsigned char i,j;
        i=x/10;                  //取整運算,求得十位數(shù)字
        j=x%10;                  //取余運算,求得各位數(shù)字
    WriteAddress(0x44);      //寫顯示地址,將十位數(shù)字顯示在第2行第5列
        WriteData(digit);     //將十位數(shù)字的字符常量寫入LCD
        WriteData(digit[j]);     //將個位數(shù)字的字符常量寫入LCD

}
/*******************************************************************************
以下是對AT24C02的讀寫操作程序
********************************************************************************/
/***************************************************
函數(shù)功能:開始數(shù)據(jù)傳送
***************************************************/
void start()
// 開始位
{
        SDA = 1;    //SDA初始化為高電平“1”
        SCL = 1;    //開始數(shù)據(jù)傳送時,要求SCL為高電平“1”
        _nop_();    //等待一個機器周期
        _nop_();    //等待一個機器周期
        SDA = 0;    //SDA的下降沿被認為是開始信號
        _nop_();    //等待一個機器周期
        _nop_();    //等待一個機器周期
        _nop_();    //等待一個機器周期
        _nop_();    //等待一個機器周期
        SCL = 0;    //SCL為低電平時,SDA上數(shù)據(jù)才允許變化(即允許以后的數(shù)據(jù)傳遞)
}
/***************************************************
函數(shù)功能:結束數(shù)據(jù)傳送
***************************************************/
void stop()
// 停止位
{
        SDA = 0;     //SDA初始化為低電平“0”
        _nop_();     //等待一個機器周期
        _nop_();     //等待一個機器周期
        SCL = 1;     //結束數(shù)據(jù)傳送時,要求SCL為高電平“1”
        _nop_();     //等待一個機器周期
        _nop_();     //等待一個機器周期
        _nop_();     //等待一個機器周期
        _nop_();     //等待一個機器周期
        SDA = 1;    //SDA的上升沿被認為是結束信號
}
/***************************************************
函數(shù)功能:從AT24Cxx讀取數(shù)據(jù)
出口參數(shù):x
***************************************************/
unsigned char ReadData()
// 從AT24Cxx移入數(shù)據(jù)到MCU
{
        unsigned char i;
        unsigned char x;   //儲存從AT24Cxx中讀出的數(shù)據(jù)
        for(i = 0; i < 8; i++)
        {
                SCL = 1;                //SCL置為高電平
                x<<=1;                  //將x中的各二進位向左移一位
                x|=(unsigned char)SDA;  //將SDA上的數(shù)據(jù)通過按位“或“運算存入x中
                SCL = 0;                        //在SCL的下降沿讀出數(shù)據(jù)
        }
        return(x);                //將讀取的數(shù)據(jù)返回
}
/***************************************************
函數(shù)功能:向AT24Cxx的當前地址寫入數(shù)據(jù)
入口參數(shù):y (儲存待寫入的數(shù)據(jù))
***************************************************/
//在調用此數(shù)據(jù)寫入函數(shù)前需首先調用開始函數(shù)start(),所以SCL=0
bit WriteCurrent(unsigned char y)
{
        unsigned char i;
        bit ack_bit;               //儲存應答位
        for(i = 0; i < 8; i++)                // 循環(huán)移入8個位
        {
            SDA = (bit)(y&0x80);   //通過按位“與”運算將最高位數(shù)據(jù)送到S
                                                  //因為傳送時高位在前,低位在后
                _nop_();            //等待一個機器周期   
           SCL = 1;            //在SCL的上升沿將數(shù)據(jù)寫入AT24Cxx      
           _nop_();            //等待一個機器周期
          _nop_();             //等待一個機器周期      
               
                  SCL = 0;            //將SCL重新置為低電平,以在SCL線形成傳送數(shù)據(jù)所需的8個脈沖
                y <<= 1;           //將y中的各二進位向左移一位
        }
        SDA = 1;                          // 發(fā)送設備(主機)應在時鐘脈沖的高電平期間(SCL=1)釋放SDA線,
                        //以讓SDA線轉由接收設備(AT24Cxx)控制
        _nop_();        //等待一個機器周期
        _nop_();        //等待一個機器周期
        SCL = 1;       //根據(jù)上述規(guī)定,SCL應為高電平
        _nop_();       //等待一個機器周期
        _nop_();       //等待一個機器周期
        _nop_();       //等待一個機器周期
        _nop_();       //等待一個機器周期
        ack_bit = SDA; //接受設備(AT24Cxx)向SDA送低電平,表示已經接收到一個字節(jié)
                       //若送高電平,表示沒有接收到,傳送異常
        SCL = 0;       //SCL為低電平時,SDA上數(shù)據(jù)才允許變化(即允許以后的數(shù)據(jù)傳遞)
        return  ack_bit;                        // 返回AT24Cxx應答位
}
/***************************************************
函數(shù)功能:向AT24Cxx中的指定地址寫入數(shù)據(jù)
入口參數(shù):add (儲存指定的地址);dat(儲存待寫入的數(shù)據(jù))
***************************************************/
void WriteSet(unsigned char add, unsigned char dat)
// 在指定地址addr處寫入數(shù)據(jù)WriteCurrent
{
        start();               //開始數(shù)據(jù)傳遞
        WriteCurrent(OP_WRITE);  //選擇要操作的AT24Cxx芯片,并告知要對其寫入數(shù)據(jù)
        WriteCurrent(add);       //寫入指定地址
        WriteCurrent(dat);       //向當前地址(上面指定的地址)寫入數(shù)據(jù)
        stop();                //停止數(shù)據(jù)傳遞
        delaynms(4);               //1個字節(jié)的寫入周期為1ms, 最好延時1ms以上
}
/***************************************************
函數(shù)功能:從AT24Cxx中的當前地址讀取數(shù)據(jù)
出口參數(shù):x (儲存讀出的數(shù)據(jù))
***************************************************/
unsigned char ReadCurrent()
{
        unsigned char x;
        start();               //開始數(shù)據(jù)傳遞
        WriteCurrent(OP_READ);   //選擇要操作的AT24Cxx芯片,并告知要讀其數(shù)據(jù)
        x=ReadData();         //將讀取的數(shù)據(jù)存入x
        stop();                //停止數(shù)據(jù)傳遞
        return x;              //返回讀取的數(shù)據(jù)
}
/***************************************************
函數(shù)功能:從AT24Cxx中的指定地址讀取數(shù)據(jù)
入口參數(shù):set_add
出口參數(shù):x
***************************************************/
unsigned char ReadSet(unsigned char set_add)
// 在指定地址讀取
{
        start();                      //開始數(shù)據(jù)傳遞
        WriteCurrent(OP_WRITE);       //選擇要操作的AT24Cxx芯片,并告知要對其寫入數(shù)據(jù)
        WriteCurrent(set_add);       //寫入指定地址
        return(ReadCurrent());        //從指定地址讀出數(shù)據(jù)并返回
}
/*********************************************************************
函數(shù)功能:主函數(shù)
***********************************************************************/
void main(void)
{
    unsigned char sum;    //儲存計數(shù)值
         unsigned char x;      //儲存從AT24C02讀出的值
    LcdInitiate();        //調用LCD初始化函數(shù)  
         sum=0;                //將計數(shù)值初始化為0
    while(1)             //無限循環(huán)
      {
                  if(S==0)          //如果該鍵被按下
                   {
                    delaynms(80);   //軟件消抖,延時80ms
                         if(S==0)        //確實該鍵被按下
                          sum++;         //計件值加1
                         if(sum==99)     //如果計滿99
                          sum=0;         //清0,重新開始計數(shù)
                        }
       WriteSet(0x01,sum); //將計件值寫入AT24C02中的指定地址"0x01"
                 x=ReadSet(0x01);    //從AT24C02中讀出計件值
                 Display(x);              //將計件值用1602LCD顯示
          }
}


更多詳情參考附件文檔

游客,如果您要查看本帖隱藏內容請回復

回復

使用道具 舉報

1

主題

8

帖子

42

積分

一級會員

Rank: 1

積分
42
沙發(fā)
發(fā)表于 2022-4-1 11:42:03 | 只看該作者
好開心,真的好開心,看到老師的指導!
回復 支持 反對

使用道具 舉報

發(fā)表回復

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則


聯(lián)系客服 關注微信 下載APP 返回頂部 返回列表