[求助] 各位大神,麻烦帮我看下我这个程序为何读写失败

奔跑滴流年   2014-4-28 16:45 楼主

//24C04读写程序
#include

#define CPU_F ((double)2000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))

#define SDA_OUT P1DIR|=BIT2//数据端输出
#define SDA_IN  P1DIR&=~BIT2//数据段输入
#define SDA_1   P1OUT|=BIT2//数据端置1
#define SDA_0   P1OUT&=~BIT2//数据端置0
#define SDA_VAL P1IN&BIT2
#define SCL_1   P1OUT|=BIT1
#define SCL_0   P1OUT&=~BIT1
//#define SCL_IN  P1DIR&=~BIT1
#define SCL_OUT P1DIR|=BIT1

unsigned char ack=0;
void Start_24C04()       //启动24C04,在SCL为高电平期间,SDA由高电平跳向低电平
{
    SDA_OUT;
    SCL_OUT;
    SDA_1;
    SCL_0;
    delay_us(5);
    SCL_1;
    delay_us(5);
    SDA_0;
    delay_us(5);
    SCL_0;
    delay_us(2);
}
void Stop_24C04()//停止24C02,在SCL为高电平期间,SDA由低电平跳向高电平
{
    SDA_OUT;
    SDA_0;
    SCL_0;
    delay_us(5);
    SCL_1;
    delay_us(5);
    SDA_1;
    delay_us(5);
}
void Ack(void) //IIC总线应答,SCL为高电平时,SDA为低电平
{
    SDA_OUT;
    SDA_0;
    SCL_0;
    delay_us(5);
//    SCL_OUT;
    SCL_1;
    delay_us(5);
    SCL_0;
    delay_us(5);
    SDA_1;
}

void NoAck(void) //IIC总线无应答,SDA维持高电平,SCL产生一个脉冲
{
    SDA_OUT;
    SDA_1;
    SCL_0;
    delay_us(5);
//    SCL_OUT;
    SCL_1;
    delay_us(5);
    SCL_0;
    delay_us(5);
}

/*从器件地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。如果返回1表示操作成功,否则操作有误。*/

unsigned char RcvByte()               //用来接收从器件传来的数据,并判断总线错误
{
    unsigned char retc=0;
    unsigned char i;

    //SDA_1;
    SDA_IN;             //置数据线为输入方式

    for(i=0;i<8;i++)
    {
        delay_us(2);           
        SCL_0;       //置时钟线为低,准备接收数据位
        delay_us(5);      //时钟低电平周期大于4.7us
        SCL_1;       //置时钟线为高使数据线上数据有效
        delay_us(2);
        retc=retc<<1;
        if(SDA_VAL==BIT2)
            retc=retc+1; //读数据位,接收的数据位放入retc中
        delay_us(2);
      }
      SCL_0;   
      delay_us(2);
      return(retc);
}
/*将数据c发送出去,发送数据正常,ack=1; ack=0表示被控器无应答或损坏。*/
void  SendByte(unsigned char c)
{
    unsigned char i;
    SDA_OUT;
    SCL_0;
    for(i=0;i<8;i++)  //要传送的数据长度为8位
    {
        if((c<         else  SDA_0;               
        delay_us(5);
        SCL_1;               //置时钟线为高,通知被控器开始接收数据位
        delay_us(5);            //保证时钟高电平周期大于4μ         
        SCL_0;
        delay_us(2);
    }

    delay_us(2);
    //SDA_1;               //8位发送完后释放数据线,准备接收应答位
    //delay_us(2);
    SDA_IN;
    delay_us(5);
    SCL_1;
    delay_us(5);
    if(SDA_VAL==BIT2)
        ack=0;     
    else
        ack=1;        //判断是否接收到应答信号
    SCL_0;
    delay_us(2);
}

unsigned char Read_data(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
    unsigned char i;

    Start_24C04();               //启动总线
    SendByte(sla);             //发送器件地址
    if(ack==0)return(0);
    SendByte(suba);            //发送器件子地址
    if(ack==0)return(0);

    Start_24C04();
    SendByte(sla+1);
    if(ack==0)return(0);

    for(i=0;i     {   
        *s=RcvByte();              //发送数据
        Ack();                //发送就答位
        s++;
    }
    *s=RcvByte();
    NoAck();                 //发送非应位
    Stop_24C04();                    //结束总线
    return(1);
}
unsigned char Save_data_c(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
    unsigned char i;

    Start_24C04();               //启动总线
    SendByte(sla);             //发送器件地址
    if(ack==0)return(0);
    SendByte(suba);            //发送器件子地址
    if(ack==0)return(0);

    for(i=0;i     {   
        SendByte(*s);            //发送数据
        if(ack==0)return(0);
        s++;
    }
    Stop_24C04();                  //结束总线
    return(1);
}

#include
#define uchar unsigned char

extern unsigned char Save_data_c(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);
extern unsigned char Read_data(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);

uchar e=3,f=0;
int main()
{
    WDTCTL = WDTPW + WDTHOLD;

    Save_data_c(0xa8,0,&e,1);//引脚A2接Vcc,A1和A0接地,故器件地址为a8
    Read_data(0xa8,0,&f,1);   
    while(1);
}
我也不知道些没写进去,反正读是读不出来的,请各位大神给指点下,万分感谢   




回复评论 (5)

sda和scl有没有使能上拉电阻,使能一下试试,或外加5.1k的上拉电阻
点赞  2014-4-29 12:06
写数据完成后再延时一段时间再去读芯片,否则写入没有成功
点赞  2014-4-29 17:19
能不能先移植到430F1系列上然后去PROTEUS里仿真一下。。PROTEUS里应该有24C04的
点赞  2014-5-3 22:25
  1. void Start_24C04()       //启动24C04,在SCL为高电平期间,SDA由高电平跳向低电平
  2. {
  3.     SDA_OUT;
  4.     SCL_OUT;
  5.     SDA_1;
  6.     delay_us(5);
  7.     SCL_1;
  8.     delay_us(5);
  9.     SDA_0;
  10.     delay_us(5);
  11. }<div class="blockcode"><blockquote>
  1. void Ack(void)//ACK要有一个等待的过程
  2. {
  3.     SDA_OUT;
  4.     unsigned char i = 0;
  5.     SCL_1;
  6.     delay_us(5);
  7.     while ((SDA_1 == 1) && (i<250))
  8.       i ++;
  9.     SCL_0;
  10.     delay_us(5);
  11. }





  1.   if (e == f){//当写入数据和读出数据一致时点亮发光二极管
  2.         
  3.         P3OUT ^= BIT1;
  4.     }




点赞  2014-5-5 15:27
在数据变换参数的时候出了错,如果能仿真,可以尝试下
点赞  2014-5-6 23:24
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复