51單片機(jī)AT24C02數(shù)據(jù)儲(chǔ)存

此為B站up:江科大自動(dòng)協(xié)課程的12-2程序,學(xué)習(xí)用
跟著老師敲出來(lái)

main.c

unsigned char i;
   for(i=0;i<8;i++)
   {    
       I2C_SDA=Byte&(0x80>>i);
       I2C_SCL=1;
       I2C_SCL=0;
   }
}

/**
 * @brief  I2C接收一個(gè)字節(jié)
 * @param  無(wú)
 * @retval 接收到的一個(gè)字節(jié)數(shù)據(jù)
 */
unsigned char I2C_ReceiveByte(void)
{
   unsigned char i,Byte=0x00;
   I2C_SDA=1;
   for(i=0;i<8;i++)
   {
       I2C_SCL=1;
       if(I2C_SDA){Byte|=(0x80>>i);}
       I2C_SCL=0;
   }
   return Byte;
}


unsigned char KeyNum;
unsigned int Num;

void main()
{
   LCD_Init();
   LCD_ShowNum(1,1,Num,5);
   while(1)
   {
       KeyNum=Key();
       if(KeyNum==1)   //K1按鍵,Num自增
       {
           Num++;
           LCD_ShowNum(1,1,Num,5);
       }
       if(KeyNum==2)   //K2按鍵,Num自減
       {
           Num--;
           LCD_ShowNum(1,1,Num,5);
       }
       if(KeyNum==3)   //K3按鍵,向AT24C02寫入數(shù)據(jù)
       {
           AT24C02_WriteByte(0,Num%256);
           Delay(5);
           AT24C02_WriteByte(1,Num/256);
           Delay(5);
           LCD_ShowString(2,1,"Write OK");
           Delay(1000);
           LCD_ShowString(2,1,"        ");
       }
       if(KeyNum==4)   //K4按鍵,從AT24C02讀取數(shù)據(jù)
       {
           Num=AT24C02_ReadByte(0);
           Num|=AT24C02_ReadByte(1)<<8;
           LCD_ShowNum(1,1,Num,5);
           LCD_ShowString(2,1,"Read OK ");
           Delay(1000);
           LCD_ShowString(2,1,"        ");
       }
   }
}


Delay.c


void Delay(unsigned int xms)
{
    unsigned char i, j;
    while(xms--)
    {
        i = 2;
        j = 239;
        do
        {
            while (--j);
        } while (--i);
    }
}

Delay.h

#ifndef __LCD1602_H__
#define __LCD1602_H__

//用戶調(diào)用函數(shù):
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif
  

LCD1602.c

#include <REGX52.H>

//引腳配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

//函數(shù)定義:
/**
  * @brief  LCD1602延時(shí)函數(shù),12MHz調(diào)用可延時(shí)1ms
  * @param  無(wú)
  * @retval 無(wú)
  */
void LCD_Delay()
{
    unsigned char i, j;

    i = 2;
    j = 239;
    do
    {
        while (--j);
    } while (--i);
}

/**
  * @brief  LCD1602寫命令
  * @param  Command 要寫入的命令
  * @retval 無(wú)
  */
void LCD_WriteCommand(unsigned char Command)
{
    LCD_RS=0;
    LCD_RW=0;
    LCD_DataPort=Command;
    LCD_EN=1;
    LCD_Delay();
    LCD_EN=0;
    LCD_Delay();
}

/**
  * @brief  LCD1602寫數(shù)據(jù)
  * @param  Data 要寫入的數(shù)據(jù)
  * @retval 無(wú)
  */
void LCD_WriteData(unsigned char Data)
{
    LCD_RS=1;
    LCD_RW=0;
    LCD_DataPort=Data;
    LCD_EN=1;
    LCD_Delay();
    LCD_EN=0;
    LCD_Delay();
}

/**
  * @brief  LCD1602設(shè)置光標(biāo)位置
  * @param  Line 行位置,范圍:1~2
  * @param  Column 列位置,范圍:1~16
  * @retval 無(wú)
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
    if(Line==1)
    {
        LCD_WriteCommand(0x80|(Column-1));
    }
    else if(Line==2)
    {
        LCD_WriteCommand(0x80|(Column-1+0x40));
    }
}

/**
  * @brief  LCD1602初始化函數(shù)
  * @param  無(wú)
  * @retval 無(wú)
  */
void LCD_Init()
{
    LCD_WriteCommand(0x38);//八位數(shù)據(jù)接口,兩行顯示,5*7點(diǎn)陣
    LCD_WriteCommand(0x0c);//顯示開(kāi),光標(biāo)關(guān),閃爍關(guān)
    LCD_WriteCommand(0x06);//數(shù)據(jù)讀寫操作后,光標(biāo)自動(dòng)加一,畫面不動(dòng)
    LCD_WriteCommand(0x01);//光標(biāo)復(fù)位,清屏
}

/**
  * @brief  在LCD1602指定位置上顯示一個(gè)字符
  * @param  Line 行位置,范圍:1~2
  * @param  Column 列位置,范圍:1~16
  * @param  Char 要顯示的字符
  * @retval 無(wú)
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
    LCD_SetCursor(Line,Column);
    LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置開(kāi)始顯示所給字符串
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  String 要顯示的字符串
  * @retval 無(wú)
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=0;String[i]!='\0';i++)
    {
        LCD_WriteData(String[i]);
    }
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
    unsigned char i;
    int Result=1;
    for(i=0;i<Y;i++)
    {
        Result*=X;
    }
    return Result;
}

/**
  * @brief  在LCD1602指定位置開(kāi)始顯示所給數(shù)字
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  Number 要顯示的數(shù)字,范圍:0~65535
  * @param  Length 要顯示數(shù)字的長(zhǎng)度,范圍:1~5
  * @retval 無(wú)
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
    }
}

/**
  * @brief  在LCD1602指定位置開(kāi)始以有符號(hào)十進(jìn)制顯示所給數(shù)字
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  Number 要顯示的數(shù)字,范圍:-32768~32767
  * @param  Length 要顯示數(shù)字的長(zhǎng)度,范圍:1~5
  * @retval 無(wú)
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
    unsigned char i;
    unsigned int Number1;
    LCD_SetCursor(Line,Column);
    if(Number>=0)
    {
        LCD_WriteData('+');
        Number1=Number;
    }
    else
    {
        LCD_WriteData('-');
        Number1=-Number;
    }
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
    }
}

/**
  * @brief  在LCD1602指定位置開(kāi)始以十六進(jìn)制顯示所給數(shù)字
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  Number 要顯示的數(shù)字,范圍:0~0xFFFF
  * @param  Length 要顯示數(shù)字的長(zhǎng)度,范圍:1~4
  * @retval 無(wú)
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i,SingleNumber;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        SingleNumber=Number/LCD_Pow(16,i-1)%16;
        if(SingleNumber<10)
        {
            LCD_WriteData(SingleNumber+'0');
        }
        else
        {
            LCD_WriteData(SingleNumber-10+'A');
        }
    }
}

/**
  * @brief  在LCD1602指定位置開(kāi)始以二進(jìn)制顯示所給數(shù)字
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  Number 要顯示的數(shù)字,范圍:0~1111 1111 1111 1111
  * @param  Length 要顯示數(shù)字的長(zhǎng)度,范圍:1~16
  * @retval 無(wú)
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
    }
}

LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__

//用戶調(diào)用函數(shù):
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

Key.c

#include <REGX52.H>
#include "Delay.h"

/**
  * @brief  獲取獨(dú)立按鍵鍵碼
  * @param  無(wú)
  * @retval 按下按鍵的鍵碼,范圍:0~4,無(wú)按鍵按下時(shí)返回值為0
  */
unsigned char Key()
{
    unsigned char KeyNumber=0;
    
    if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
    if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
    if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
    if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
    
    return KeyNumber;
}

Key.h

#ifndef __KEY_H__
#define __KEY_H__

unsigned char Key();

#endif

AT89C52.c

#include <REGX52.H>
#include "I2C.h"

#define AT24C02_ADDRESS     0xA0

/**
  * @brief  AT24C02寫入一個(gè)字節(jié)
  * @param  WordAddress 要寫入字節(jié)的地址
  * @param  Data 要寫入的數(shù)據(jù)
  * @retval 無(wú)
  */
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
    I2C_Start();
    I2C_SendByte(AT24C02_ADDRESS);
    I2C_ReceiveAck();
    I2C_SendByte(WordAddress);
    I2C_ReceiveAck();
    I2C_SendByte(Data);
    I2C_ReceiveAck();
    I2C_Stop();
}

/**
  * @brief  AT24C02讀取一個(gè)字節(jié)
  * @param  WordAddress 要讀出字節(jié)的地址
  * @retval 讀出的數(shù)據(jù)
  */
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
    unsigned char Data;
    I2C_Start();
    I2C_SendByte(AT24C02_ADDRESS);
    I2C_ReceiveAck();
    I2C_SendByte(WordAddress);
    I2C_ReceiveAck();
    I2C_Start();
    I2C_SendByte(AT24C02_ADDRESS|0x01);
    I2C_ReceiveAck();
    Data=I2C_ReceiveByte();
    I2C_SendAck(1);
    I2C_Stop();
    return Data;
}

AT89C52.h

 #ifndef __AT24C02_H__
#define __AT24C02_H__

void AT24C02_WriteByte(unsigned char WordAddress,Data);
unsigned char AT24C02_ReadByte(unsigned char WordAddress);


#endif

I2C.c

#include <REGX52.H>

sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;

/**
  * @brief  I2C開(kāi)始
  * @param  無(wú)
  * @retval 無(wú)
  */
void I2C_Start(void)
{
    I2C_SDA=1;
    I2C_SCL=1;
    I2C_SDA=0;
    I2C_SCL=0;
}

/**
  * @brief  I2C停止
  * @param  無(wú)
  * @retval 無(wú)
  */
void I2C_Stop(void)
{
    I2C_SDA=0;
    I2C_SCL=1;
    I2C_SDA=1;
}

/**
  * @brief  I2C發(fā)送一個(gè)字節(jié)
  * @param  Byte 要發(fā)送的字節(jié)
  * @retval 無(wú)
  */
void I2C_SendByte(unsigned char Byte)
{
    unsigned char i;
    for(i=0;i<8;i++)
    {
        I2C_SDA=Byte&(0x80>>i);
        I2C_SCL=1;
        I2C_SCL=0;
    }
}

/**
  * @brief  I2C接收一個(gè)字節(jié)
  * @param  無(wú)
  * @retval 接收到的一個(gè)字節(jié)數(shù)據(jù)
  */
unsigned char I2C_ReceiveByte(void)
{
    unsigned char i,Byte=0x00;
    I2C_SDA=1;
    for(i=0;i<8;i++)
    {
        I2C_SCL=1;
        if(I2C_SDA){Byte|=(0x80>>i);}
        I2C_SCL=0;
    }
    return Byte;
}

/**
  * @brief  I2C發(fā)送應(yīng)答
  * @param  AckBit 應(yīng)答位,0為應(yīng)答,1為非應(yīng)答
  * @retval 無(wú)
  */
void I2C_SendAck(unsigned char AckBit)
{
    I2C_SDA=AckBit;
    I2C_SCL=1;
    I2C_SCL=0;
}

/**
  * @brief  I2C接收應(yīng)答位
  * @param  無(wú)
  * @retval 接收到的應(yīng)答位,0為應(yīng)答,1為非應(yīng)答
  */
unsigned char I2C_ReceiveAck(void)
{
    unsigned char AckBit;
    I2C_SDA=1;
    I2C_SCL=1;
    AckBit=I2C_SDA;
    I2C_SCL=0;
    return AckBit;
}

I2C.h

#ifndef __I2C_H__
#define __I2C_H__

void I2C_Start(void);
void I2C_Stop(void);
void I2C_SendByte(unsigned char Byte);
unsigned char I2C_ReceiveByte(void);
void I2C_SendAck(unsigned char AckBit);
unsigned char I2C_ReceiveAck(void);


#endif

總結(jié)
可能是我比較憨,跟著課程走到現(xiàn)在(零基礎(chǔ)自學(xué)),才對(duì)單片機(jī)有了一點(diǎn)點(diǎn)感覺(jué)
現(xiàn)在對(duì)單片機(jī)編程的片面認(rèn)識(shí):根據(jù)說(shuō)明書芯片時(shí)序配置對(duì)配置管腳狀態(tài),即可讓單片機(jī)工作

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容