森侃 2024-03-09 22:13 采纳率: 60%
浏览 17
已结题

蓝桥杯单片机eeprom问题

iic.c文件
为什么我实现下面的代码,会出现先这个结果呀,数字在数码管上的显示这些函数是没有问题的。

img

/*    #   I2C代码片段说明
    1.     本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
    2.     参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
        中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "iic.h"
#define DELAY_TIME    5

//
static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();        
    }
    while(n--);          
}

//
void I2CStart(void)
{
    sda = 1;
    scl = 1;
    I2C_Delay(DELAY_TIME);
    sda = 0;
    I2C_Delay(DELAY_TIME);
    scl = 0;    
}

//
void I2CStop(void)
{
    sda = 0;
    scl = 1;
    I2C_Delay(DELAY_TIME);
    sda = 1;
    I2C_Delay(DELAY_TIME);
}

//
void I2CSendByte(unsigned char byt)
{
    unsigned char i;
    
    for(i=0; i<8; i++){
        scl = 0;
        I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
        I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
        I2C_Delay(DELAY_TIME);
    }
    
    scl = 0;  
}

//
unsigned char I2CReceiveByte(void)
{
    unsigned char da;
    unsigned char i;
    for(i=0;i<8;i++){   
        scl = 1;
        I2C_Delay(DELAY_TIME);
        da <<= 1;
        if(sda) 
            da |= 0x01;
        scl = 0;
        I2C_Delay(DELAY_TIME);
    }
    return da;    
}

//
unsigned char I2CWaitAck(void)
{
    unsigned char ackbit;
    
    scl = 1;
    I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
    I2C_Delay(DELAY_TIME);
    
    return ackbit;
}

//
void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
    I2C_Delay(DELAY_TIME);
    scl = 1;
    I2C_Delay(DELAY_TIME);
    scl = 0; 
    sda = 1;
    I2C_Delay(DELAY_TIME);
}

void eeprom_write_string(unsigned char* eeprom_string,unsigned char num,unsigned char addr)
{
    I2CStart();
    I2CSendByte(0xa0);
    I2CWaitAck();
    I2CSendByte(addr);
    I2CWaitAck();
    while(num--)
    {
        I2CSendByte(*eeprom_string++);
        I2CWaitAck();
        I2C_Delay(200);
    }
    I2CStop();
}
void eeprom_read_string(unsigned char* eeprom_string,unsigned char num,unsigned char addr)
{
    I2CStart();
    I2CSendByte(0xa0);
    I2CWaitAck();
    I2CSendByte(addr);
    I2CWaitAck();
    
    I2CStart();
    I2CSendByte(0xa1);
    I2CWaitAck();
    while(num--)
    {
        *eeprom_string++=I2CReceiveByte();
        I2C_Delay(200);
        if (num)
            I2CSendAck(0);
        else
            I2CSendAck(1);
    }
    I2CStop();
}
void eeprom_write_byte(unsigned char dat,unsigned char addr)
{
    I2CStart();
    I2CSendByte(0xa0);
    I2CWaitAck();
    I2CSendByte(addr);
    I2CWaitAck();
    I2CSendByte(dat);
    I2CWaitAck();
    I2CStop();
}
unsigned char eeprom_Read_byte(unsigned char addr)
{
    unsigned char dat;
    I2CStart();
    I2CSendByte(0xa0);
    I2CWaitAck();
    I2CSendByte(addr);
    I2CWaitAck();
    
    I2CStart();
    I2CSendByte(0xa1);
    I2CWaitAck();
    dat=I2CReceiveByte();
    I2CSendAck(1);
    I2CStop();
    return dat;
}
void Write()
{
    unsigned char i;
    for (i=0;i<6;i++)
    {
        eeprom_write_byte(input[i],i);
        
    }
}

void Read()
{
    unsigned char i;
    for (i=0;i<6;i++)
    {
        mima[i]=eeprom_Read_byte(i);
    }
}


iic.h

#ifndef __iic_H__
#define __iic_H__

#include <STC15F2K60S2.H>
#include "System.h"
#include "Display.h"
#include "Key.h"
#include "intrins.h"
sbit sda=P2^1;
sbit scl=P2^0;

static void I2C_Delay(unsigned char n);
void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);

void eeprom_write_string(unsigned char* eeprom_string,unsigned char num,unsigned char addr);
void eeprom_read_string(unsigned char* eeprom_string,unsigned char num,unsigned char addr);

void eeprom_write_byte(unsigned char dat,unsigned char addr);
unsigned char eeprom_Read_byte(unsigned char addr);

void Write();
void Read();
#endif

main.c

#include <STC15F2K60S2.H>
#include "System.h"
#include "Display.h"
#include "Key.h"
#include "iic.h"
unsigned char x;
unsigned char num=8;
unsigned char daxx[2]={30,60};
unsigned char dax[2]={20,70};
void display()
{
    unsigned char i=0;
    P0=0xff;SelectHC573(7);SelectHC573(0);
    SMG_Bit(SMG[daxx[0]/10],3);
    SMG_Delay(300);
    SMG_Bit(SMG[daxx[0]%10],4);
    SMG_Delay(300);
    SMG_Bit(SMG[daxx[1]/10],6);
    SMG_Delay(300);
    SMG_Bit(SMG[daxx[1]%10],7);
    SMG_Delay(300);
    SMG_Bit(0xff,8);
    SMG_Delay(300);
}

int main()
{
    Close();
    eeprom_write_string(dax,2,0);
    eeprom_read_string(daxx,2,0);
    while(1)
    {
        display();
    }
}


  • 写回答

5条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-03-09 22:14
    关注

    引自免费微信小程序:皆我百晓生

    你提供的代码片段是关于基于STC15F2K60S2单片机的I2C通信接口实现,用于与EEPROM进行数据读写。在你的问题中,并没有明确指出具体的问题现象,但从你给出的描述来看,似乎是在使用I2C协议与EEPROM交互时出现了意料之外的结果。

    首先,确认一下代码逻辑:

    1. eeprom_write_string 函数用来向EEPROM以字节流形式写入字符串。
    2. eeprom_read_string 函数则负责从EEPROM按照指定地址读取字符串。
    3. eeprom_write_byteeeprom_Read_byte 分别实现了单个字节的写入和读取操作。

    main.c 的主函数中,先调用 eeprom_write_string 将数组 dax 中的内容写入EEPROM地址0开始的位置,然后调用 eeprom_read_string 从EEPROM地址0开始读取内容到数组 daxx 中。

    针对可能的问题点:

    • 时序问题:确保I2C总线上的延时时间(DELAY_TIME)设置得当,特别是对于不同EEPROM芯片,其内部时钟频率要求可能会有差异。如果延时过短或过长,可能导致通信失败或数据错误。

    • EEPROM地址及数据范围:检查 num 参数是否正确反映了待写入或读取的数据长度,以及EEPROM的实际容量是否足够存储这些数据。

    • 硬件连接:确认I2C的SDA和SCL信号线连接无误,且上拉电阻已正确配置。

    • EEPROM初始化:虽然在提供的代码片段中未展示EEPROM的具体初始化过程,但在实际应用中,可能需要在初次使用前对EEPROM进行必要的写入保护解除或其他初始化操作。

    • 数据校验:在读取数据后,可以增加数据校验步骤,如计算写入和读取数据的CRC校验值并对比,以判断数据传输过程中是否有错误发生。

    为解决这类问题,你可以按照以下步骤调试:

    1. 逐步调试:通过逐行运行或者使用断点调试的方式观察每个函数执行后的结果,重点关注I2C的起始、停止条件和ACK应答状态。

    2. 硬件信号检测:使用示波器或逻辑分析仪捕捉I2C总线上的SDA和SCL信号,直观查看通信时序是否符合预期。

    3. 简化测试:尝试只写入和读取一个字节,确保基本功能正常后再扩展到字符串或多个字节。

    4. 查阅EEPROM数据手册:核对EEPROM型号的I2C时序要求、地址格式、写保护等特性,确保程序设计符合规定。

    如果你能提供更多有关问题现象的细节,我将能够更精确地指导你如何排查和解决问题。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月15日
  • 创建了问题 3月9日

悬赏问题

  • ¥15 求高通平台Softsim调试经验
  • ¥15 canal如何实现将mysql多张表(月表)采集入库到目标表中(一张表)?
  • ¥15 wpf ScrollViewer实现冻结左侧宽度w范围内的视图
  • ¥15 栅极驱动低侧烧毁MOSFET
  • ¥30 写segy数据时出错3
  • ¥100 linux下qt运行QCefView demo报错
  • ¥50 F1C100S下的红外解码IR_RX驱动问题
  • ¥20 基于matlab的航迹融合 航迹关联 航迹插补
  • ¥15 用Matlab实现图中的光线追迹
  • ¥15 联想笔记本开机出现系统更新界面