吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1050|回复: 6
收起左侧

[学习记录] 51单片机在AT24C02读取数据的时候读不到

[复制链接]
djdgf4 发表于 2023-3-19 15:05
本帖最后由 djdgf4 于 2023-3-20 22:12 编辑

写了一个按键控制led移位、存储和读取的程序,反复测试,读取P2的时候总是0x00,。AT24C02器件本身没问题,配置代码也没问题,因为开另一个使用24C02的工程的时候一切正常,可以存储读取
工程如下:

main.c:

[C] 纯文本查看 复制代码
#include <REGX52.H>
#include "Delay.h"
#include "AT24C02.h"
#include "key.h"
//#include "MatrixKey.h"

#define uchar unsigned char
#define StorageAddress 0xF1 //数据存储地址

#if 1
void main()
{
        uchar KeyNum;
        uchar LED_shift = 0;
        
        P2 = ~0X01;
        
        while (1)
        {
                KeyNum = key();
                if(KeyNum == 1)//左移
                {        
                        Delay(5);
                        if (LED_shift >= 8)
                        {
                                LED_shift = 0;
                        }
                        P2 = ~(0x01 << ++LED_shift);
                        Delay(5);
                }
                if(KeyNum == 2)//右移
                {
                        Delay(5);
                        if (LED_shift == 0)
                        {
                                LED_shift = 8;
                        }
                        P2 = ~(0x01 << --LED_shift);
                        Delay(5);
                }
                if (KeyNum == 3)
                {
                        AT24C02_SendData(StorageAddress, P2);//把P2存入AT24C02
                        Delay(5);
                }
                if(KeyNum == 4)
                {
                        P2 = AT24C02_ReceiveData(StorageAddress);//从AT24C02读取P2

                }
        }
}
#endif


AT24C02.C:

[C] 纯文本查看 复制代码
#include "I2C.h"

#define uchar unsigned char
#define SLAVE_ADDRESS 0XA0
/**
  *  [url=home.php?mod=space&uid=190858]@brief[/url]   AT24C02写入一个字节
  *  [url=home.php?mod=space&uid=952169]@Param[/url]   WordAddress 要写入字节的地址
        *  @param   Data 要写入的数据
  *  @retva   无
  */
void AT24C02_SendData(uchar WordAddress, uchar Data)
{
    I2C_Start();
    I2C_SendByte(SLAVE_ADDRESS);
    I2C_ReceiveACK();
    I2C_SendByte(WordAddress);
    I2C_ReceiveACK();
    I2C_SendByte(Data);
    I2C_ReceiveACK();
    I2C_Stop();
}
/**
  *  @brief   AT24C02读取一个字节
  *  @param   WordAddress 要读出字节的地址
  *  @retva   Data 读出的数据
  */
uchar AT24C02_ReceiveData(uchar WordAddress)
{
    uchar Data;
    I2C_Start();
    I2C_SendByte(SLAVE_ADDRESS);
    I2C_ReceiveACK();
    I2C_SendByte(WordAddress);
    I2C_ReceiveACK();

    I2C_Start();
    I2C_SendByte(SLAVE_ADDRESS | 0x01);
    I2C_ReceiveACK();
    Data = I2C_ReceiveByte();
    I2C_SendACK(1);
    I2C_Stop();
    return Data;
}


I2C.c:

[C] 纯文本查看 复制代码
#include <REGX52.H>

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

#define uchar unsigned char

/*
 *  @brief   I2C开始
 *  @param
 *  @retva
 */
void I2C_Start()
{
    I2C_SCL = 0;
    I2C_SDA = 1;

    I2C_SCL = 1;
    I2C_SDA = 0;
}

/*
 *  @brief   I2C停止
 *  @param
 *  @retva
 */
void I2C_Stop()
{
    I2C_SDA = 0;
    I2C_SCL = 1;

    I2C_SDA = 1;
}

/*
 *  @brief   I2C发送一个字节
 *  @param   Byte 要发送的字节
 *  @retva
 */
void I2C_SendByte(uchar Data)
{
    uchar i;
    I2C_SDA = 0; // 在接收前释放SDA
    for (i = 0; i < 8; i++)
    {
        I2C_SCL = 0;
        I2C_SDA = Data;
        I2C_SCL = 1;
    }
}

/*
 *  @brief   I2C接受一个字节
 *  @param   无
 *  @retva   Byte 接收到的字节数据
 */
uchar I2C_ReceiveByte()
{
    uchar Data;
    uchar i;
    I2C_SDA = 0;
    for (i = 0; i < 8; i++)
    {
        I2C_SCL = 0;
        Data = I2C_SDA;
        I2C_SCL = 1;
    }
    return Data;
}

/*
 *  @brief   I2C发送应答
 *  @param   ACKBit 应答位,0为应答,1为非应答
 *  @retva
 */
void I2C_SendACK(bit ACK_Sending)
{
    I2C_SCL = 0;
    I2C_SDA = ACK_Sending;
    I2C_SCL = 1;
}

/*
 *  @brief   I2C接受应答位
 *  @param   无
 *  @retva   ACKBit 接收到的应答位
 */
uchar I2C_ReceiveACK()
{
    bit ACK_Receiving;
    I2C_SCL = 0;
    ACK_Receiving = I2C_SDA;
    I2C_SCL = 1;
    return ACK_Receiving;
}


经过调试,发现在写入AT24C02函数 AT24C02_SendData 出来的时候数据就错了,再仔细调试发现,在I2C_ReceiveByte函数结束的时候,data变成了0x00。
经过比对,发现整个I2C的具体实现都有~瑕疵~,重新改写I2c如下,烧录,完美解决。
[C] 纯文本查看 复制代码
#include <REGX52.H>

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

#define uchar unsigned char

/*
 *  @brief   I2C开始
 *  @param
 *  @retva
 */
void I2C_Start()
{
    I2C_SDA = 1;

    I2C_SCL = 1;
    I2C_SDA = 0;
    I2C_SCL = 0;
}

/*
 *  @brief   I2C停止
 *  @param
 *  @retva
 */
void I2C_Stop()
{
    I2C_SDA = 0;
    I2C_SCL = 1;

    I2C_SDA = 1;
}

/*
 *  @brief   I2C发送一个字节
 *  @param   Byte 要发送的字节
 *  @retva
 */
void I2C_SendByte(uchar Data)
{
    uchar i;
    //I2C_SDA = 0; // 在接收前释放SDA,释放SDA,就是将IO置1
    /*这句没有必要*/
    for (i = 0; i < 8; i++)
    {
        I2C_SDA = Data & (0x80 >> i);
        I2C_SCL = 1;
        I2C_SCL = 0;
    }
}

/*
 *  @brief   I2C接受一个字节
 *  @param   无
 *  @retva   Byte 接收到的字节数据
 */
uchar I2C_ReceiveByte()
{
    uchar Data = 0;
    uchar i;
    I2C_SDA = 1;// 在接收前释放SDA
    for (i = 0; i < 8; i++)
    { 
        //Data = I2C_SDA;傻逼,写错了
        I2C_SCL = 1;
        if (I2C_SDA)
        {
            Data |= (0x80 >> i);
        }
        I2C_SCL = 0;
    }
    return Data;
}

/*
 *  @brief   I2C发送应答
 *  @param   ACKBit 应答位,0为应答,1为非应答
 *  @retva
 */
void I2C_SendACK(bit ACK_Sending)
{
    //I2C_SCL = 0;这句没必要
    I2C_SDA = ACK_Sending;
    I2C_SCL = 1;
    I2C_SCL = 0;
}

/*
 *  @brief   I2C接受应答位
 *  @param   无
 *  @retva   ACKBit 接收到的应答位
 */
uchar I2C_ReceiveACK()
{
    bit ACK_Receiving;
    I2C_SDA= 1;// 在接收前释放SDA
    I2C_SCL = 1;
    ACK_Receiving = I2C_SDA;
    I2C_SCL = 0;
    
    return ACK_Receiving;
}


I2C总线释放SDA是将IO口置1的原因是:

I2C总线的IO口是开漏或开集电极模式,即只能输出低电平或高阻态。
当IO口为高阻态时,SDA可以被其他设备拉高或拉低,即释放了对总线的控制权。
SDA和SCL都为高电平时,表示总线空闲或结束信号。

工程文件

工程文件

I2C前后对比图

I2C前后对比图

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

dongge666 发表于 2023-3-19 16:15
换用其他io口试试呢
ciker_li 发表于 2023-3-19 16:36
shicoco 发表于 2023-3-19 20:05
nbacba456456 发表于 2023-3-19 20:09
很厉害的样子还行吧
 楼主| djdgf4 发表于 2023-3-20 22:13
zhujue 发表于 2023-3-19 17:08
大佬这么牛,不顶不行啊,代码也很详尽。可以抄作业啦

代码已经改过来了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 23:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表