找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2000|回复: 5
收起左侧

求助:msp430f149+24c02,IIC总线已通,但是24c02调不通。

[复制链接]
ID:601868 发表于 2019-9-4 21:18 | 显示全部楼层 |阅读模式
最近做了个项目,要用到MSP430f149+24c02,还有一个数码管显示模块,用的tm1650,用的也是iic总线。
同样的配置,tm1650可以通,但是24c02,死活回不来数据。
用示波器看了sda和scl和的波形也是正常的。
已经调了好几天了,还是通不了。

麻烦大家帮帮忙。看看问题出在哪里了。
0.png
这个电路调不通。



main函数



#include <msp430f249.h>
#include "msp430type.h"
#include "system.h"
#include "delay.h"
#include "led.h"
#include "key.h"

#include "iic.h"
#include "eeprom.h"



//要写入到24c02的字符串数组
u8 String[]={"452aASz*67895"};//一个字符占用一个字节,再加个结束符\n
#define SIZE sizeof(String)//自动计算字符个数
u8 24c02_data ;
//主函数
void main(void)
{
    u8 temp[SIZE];
   
    Wdt_Off();//关闭看门狗
    Clock_Init();//系统时钟初始化
    Led_Init();//led灯初始化
    Key_Init();//按键初始化
    Uart0_Init();//串口0初始化 波特率9600
    TFT_Init();//TFT初始化
    IIC_Init();//IIC总线初始化



    //检查24C02是否存在   
    if(EEPROM_24C02_Check())  {LED_H;Delay_ms(200);}
   
   Write_Eeprom_OneData(0,150);//写单个数字
     24c02_data  = Read_Eeprom_OneData(0);
  if(24c02_data == 150)
    {
     LED_H;Delay_ms(200);
    LED_L;Delay_(200);
    }   

   
    while(1)
    {
     ;
    }
}



iic.h
//模拟IIC总线底层驱动文件

#include <msp430f149.h>
#include "delay.h"
#include "iic.h"


//IIC_SDA方向输出
void IIC_SDAOut(void)
{
    P5DIR |= (1<<1);//设置为输出
}

//IIC_SDA方向输入
void IIC_SDAIn(void)
{
    P5DIR &= ~(1<<1);//设置为输入
}

//IIC初始化
void IIC_Init(void)
{
    P5SEL &= 0xf9;//设置P5.1,P5.2IO口为普通I/O模式
    P5DIR |= 0x06;//设置P5.1,P5.2IO口方向为输出
    P5OUT |= 0x06;//初始设置P5.1,P5.2IO为高电平
    IIC_SDA_H;
    IIC_SCL_H;
    Delay_us(5);
}

//起始信号函数
void IIC_Start(void)
{
    IIC_SDAOut();
    IIC_SDA_H;
    IIC_SCL_H;
    Delay_us(5);
    IIC_SDA_L;
    Delay_us(5);
}

//停止信号函数
void IIC_Stop(void)                       
{
    IIC_SDAOut();
    IIC_SDA_L;
    Delay_us(5);
    IIC_SCL_H;
    Delay_us(5);
    IIC_SDA_H;
    Delay_us(5);
}

//应答函数
void IIC_Ack(void)
{
    u8 time = 220;

    IIC_SDAIn();
    IIC_SCL_H;
    Delay_us(5);
    while(IIC_SDA_D && time --);//等待从机返回低电平应答信号
    IIC_SCL_L;
    Delay_us(5);
}

//非应答函数
void IIC_NoAck(void)
{
    IIC_SDAOut();
    IIC_SDA_H;
    Delay_us(5);
    IIC_SCL_H;
    Delay_us(5);
    IIC_SCL_L;
    Delay_us(5);
}

//写字节函数
void Write_IIC_byte(u8 Data)
{
    u8 i;

    IIC_SDAOut();
    IIC_SCL_L;
    for(i=0; i<8; i++)
    {
        if(Data & 0x80)
        {
            IIC_SDA_H;
        }
        else
        {
            IIC_SDA_L;
        }
        Data <<= 1;
        Delay_us(5);
        IIC_SCL_H;
        Delay_us(5);
        IIC_SCL_L;
        Delay_us(5);
    }
    IIC_SDA_H;
    Delay_us(5);   
}

//读字节函数
u8 Read_IIC_byte(void)
{
    u8 i, byte=0;

    IIC_SDAIn();
    IIC_SCL_L;
    Delay_us(5);
    for(i=0; i<8; i++)
    {
        IIC_SCL_H;
        Delay_us(5);
        byte <<= 1;
        if(IIC_SDA_D) byte ++;
        Delay_us(5);
        IIC_SCL_L;
        Delay_us(5);
    }
    return byte;
}
回复

使用道具 举报

ID:601868 发表于 2019-9-4 21:18 | 显示全部楼层
由于长度不足。
iic.c


//模拟IIC总线底层驱动文件

#include <msp430f249.h>
#include "delay.h"
#include "iic.h"


//IIC_SDA方向输出
void IIC_SDAOut(void)
{
    P5DIR |= (1<<1);//设置为输出
}

//IIC_SDA方向输入
void IIC_SDAIn(void)
{
    P5DIR &= ~(1<<1);//设置为输入
}

//IIC初始化
void IIC_Init(void)
{
        P5SEL &= 0xf9;//设置P5.1,P5.2IO口为普通I/O模式
        P5DIR |= 0x06;//设置P5.1,P5.2IO口方向为输出
        P5OUT |= 0x06;//初始设置P5.1,P5.2IO为高电平
        IIC_SDA_H;
        IIC_SCL_H;
        Delay_us(5);
}

//起始信号函数
void IIC_Start(void)
{
    IIC_SDAOut();
        IIC_SDA_H;
        IIC_SCL_H;
        Delay_us(5);
        IIC_SDA_L;
        Delay_us(5);
}

//停止信号函数
void IIC_Stop(void)                                          
{
    IIC_SDAOut();
        IIC_SDA_L;
        Delay_us(5);
        IIC_SCL_H;
        Delay_us(5);
        IIC_SDA_H;
        Delay_us(5);
}

//应答函数
void IIC_Ack(void)
{
        u8 time = 220;

    IIC_SDAIn();
        IIC_SCL_H;
        Delay_us(5);
        while(IIC_SDA_D && time --);//等待从机返回低电平应答信号
        IIC_SCL_L;
        Delay_us(5);
}

//非应答函数
void IIC_NoAck(void)
{
    IIC_SDAOut();
        IIC_SDA_H;
        Delay_us(5);
        IIC_SCL_H;
        Delay_us(5);
        IIC_SCL_L;
        Delay_us(5);
}

//写字节函数
void Write_IIC_byte(u8 Data)
{
        u8 i;

    IIC_SDAOut();
        IIC_SCL_L;
        for(i=0; i<8; i++)
        {
                if(Data & 0x80)
                {
                        IIC_SDA_H;
                }
                else
                {
                        IIC_SDA_L;
                }
                Data <<= 1;
                Delay_us(5);
                IIC_SCL_H;
                Delay_us(5);
                IIC_SCL_L;
                Delay_us(5);
        }
        IIC_SDA_H;
        Delay_us(5);       
}

//读字节函数
u8 Read_IIC_byte(void)
{
        u8 i, byte=0;

    IIC_SDAIn();
        IIC_SCL_L;
        Delay_us(5);
        for(i=0; i<8; i++)
        {
                IIC_SCL_H;
                Delay_us(5);
                byte <<= 1;
                if(IIC_SDA_D) byte ++;
                Delay_us(5);
                IIC_SCL_L;
                Delay_us(5);
        }
        return byte;
}
回复

使用道具 举报

ID:601868 发表于 2019-9-4 21:20 | 显示全部楼层
eeprom.c

//EEPROM-24c02底层驱动文件

#include <msp430f249.h>
#include "delay.h"
#include "iic.h"
#include "eeprom.h"


//EEPROM容量
//- 24C02, 256 X 8 (2K bits)
//- 24C04, 512 X 8 (4K bits)
//- 24C08, 1024 X 8 (8K bits)
//- 24C16, 2048 X 8 (16K bits)
//- 24C32, 4096 X 8 (32K bits)
//- 24C64, 8192 X 8 (64K bits)

//在EEPROM-24c02指定地址写入一个数据
//Addr:写入数据的目的地址 0~255 for AT24C02
//Data:要写入的数据
void Write_Eeprom_OneData(u8 Addr,u8 Data)
{
        IIC_Start();
        Write_IIC_byte(WriteCom);        //写命令
        IIC_Ack();
        Write_IIC_byte(Addr);
        IIC_Ack();
        Write_IIC_byte(Data);
        IIC_Ack();
        IIC_Stop();       
        Delay_ms(10);//等待EEPROM写入数据完成
}

//在EEPROM-24c02指定地址读出一个数据
//Addr:开始读数的目的地址 0~255 for AT24C02
//Data:读到的数据
u8 Read_Eeprom_OneData(u8 Addr)
{
        u8 Data;

        IIC_Start();
        Write_IIC_byte(WriteCom);        //写命令
        IIC_Ack();
        Write_IIC_byte(Addr);
        IIC_Ack();

        IIC_Start();
        Write_IIC_byte(ReadCom);        //读命令
        IIC_Ack();
        Data = Read_IIC_byte();
        IIC_NoAck();
        IIC_Stop();
       
        return Data;               
}

//检查EEPROM-24c02是否正常
//返回1:检测成功,返回0:检测失败
//EEPROM-24c02的最后一个地址(255)来存储标志字
u8 EEPROM_24C02_Check(void)
{
        u8 temp;
       
        IIC_Init();//初始化IIC总线
        temp = Read_Eeprom_OneData(255);//先读取数据          
        if(temp == 8) return 1;                  
        else
        {
                Write_Eeprom_OneData(255,8);//24C02的255位置第一次写入数据
            temp = Read_Eeprom_OneData(255);          
                if(temp == 8) return 1;//读取数据成功
        }
       
        return 0;                                                                                          
}

//在EEPROM-24c02里面的指定地址开始写入0~4294967295的数据
//Addr:开始写入的地址;Data:数据
//一个数据占用EEPROM-24c02四个地址
void Write_Eeprom_LenData(u16 Addr,u32 Data)
{         
        u8 t;

        for(t=0; t<4; t++)
        {
                Write_Eeprom_OneData(Addr+t,(Data>>(8*t))&0xFF);
        }                                                                                                    
}

//在EEPROM-24c02里面的指定地址开始读出0~4294967295的数据
//Addr:开始读出的地址 Data:数据
//该函数用于读出32bit的数据
u32 Read_Eeprom_LenData(u16 Addr)
{         
        u8 t;
        u32 Data;
        for(t=0; t<4; t++)
        {
                Data <<= 8;
                Data += Read_Eeprom_OneData(Addr+4-t-1);                                            
        }
        return Data;                                                                                                    
}

//在EEPROM-24c02里面的指定地址开始写入指定个数的字符串
//Addr:开始写入的地址 对24c02为0~255;Buf:数据数组首地址;Num:要写入数据的个数
void Write_Eeprom_NubStr(u16 Addr,u8 *Buf,u16 Num)
{
        while(Num --)
        {
                Write_Eeprom_OneData(Addr,*Buf);
                Addr ++;
                Buf ++;
        }
}

//在EEPROM-24c02里面的指定地址开始读出指定个数的字符串
//Addr:开始读出的地址 对24c02为0~255;Buf:数据数组首地址;Num:要读出数据的个数
void Read_Eeprom_NubStr(u16 Addr,u8 *Buf,u16 Num)
{
        while(Num)
        {
                *Buf ++= Read_Eeprom_OneData(Addr ++);       
                Num --;
        }
}
回复

使用道具 举报

ID:601868 发表于 2019-9-4 22:41 | 显示全部楼层
问题解决了,在网上重新找了个图。给电源个接了一个104电容,给SDA和SCL接了两个10k的上拉电阻。搞定了。
回复

使用道具 举报

ID:138097 发表于 2019-9-5 08:02 | 显示全部楼层
24c02_data  = Read_Eeprom_OneData(0);
这个是上电读EE吧,试试在读数据的前后各加20ms的延时
回复

使用道具 举报

ID:601868 发表于 2019-9-6 16:20 | 显示全部楼层
whx.000 发表于 2019-9-5 08:02
24c02_data  = Read_Eeprom_OneData(0);
这个是上电读EE吧,试试在读数据的前后各加20ms的延时

谢谢了,问题已经解决了。给sda和sdl加上10k的上拉电阻,在电源和gnd之间加一个104.就好了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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