导航: 老古网老古论坛XMOS公共讨论区XMOS开源项目区单片机程序设计嵌入式系统广告区域
→C51编程:老古,我用你的下载区的2401的程序在51上,读[东海飘萍客]

 *第683篇: C51编程:老古,我用你的下载区的2401的程序在51上,读写都正确,但是我把刚写进的数再读出来,发现不相等,不知老古能否帮我解决??

  
楼 主:东海飘萍客 2001年10月13日16:46
 C51编程:老古,我用你的下载区的2401的程序在51上,读写都正确,但是我把刚写进的数再读出来,发现不相等,不知老古能否帮我解决??
  
2楼:老古 2001年10月13日18:34
 刚写进去,要等5ms才写完。你等5ms才可以读
  
3楼:东海飘萍客 2001年10月15日00:05
 我也延时了好长时间,超过5MS,但是还是不行啊
  
4楼:东海飘萍客 2001年10月15日09:52
 不知老古能否提更好的解决办法
  
5楼:东海飘萍客 2001年10月15日11:33
 有关2401的求助,老古及各位大虾进来看一下!!
void main(void)
{
uchar Key1[8];
uchar *p1,*p2;
bit  temp;
uchar temp1;
uchar Key[]={0x13,0x02,0x06,0xf4,0x00,0x00,0x00,0x00};
p2=Key1;
for(temp1=8;temp1>0;temp1--)
    {
   *p2++=0;
    }
temp=RW2401(Key,8,0x01,0xa0);
if(!temp) 
    {
    led_yellow=0;
    led_red=1;
    }
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
bellx(3);
p1=Key;
p2=Key1;

temp=RW2401(p2,8,0x01,0xa1);
if(!temp) 
    {
    led_yellow=1;
    led_red=0;
    }
temp1=strncmp(p1,p2,8);
if(temp1==0) 
    {
    led_yellow=0;
    led_red=0;
    }
    else
    {
    led_yellow=1;
    led_red=1;
    }
while(1);
}

  
6楼:东海飘萍客 2001年10月15日14:01
 老古不在吗,快帮帮我啊,我急死了,谢谢!!
  
7楼:东海飘萍客 2001年10月15日16:33
 老古及各位大虾,我用24c01读写程序,读出的是我定义的首地址,不知怎么解决,各位大虾快救我,不然我死定了,5555!!
  
8楼:东海飘萍客 2001年10月16日12:34
 老古,你怎么不说话啊,难道你也不会吗??
  
9楼:老古 2001年10月16日13:03
 请再贴出rw2401的子程序.
  
10楼:东海飘萍客 2001年10月16日15:45
 老古,我自己重新写了一个程序,我想在地址01处写入03,但是结果却是在地址50H开始处写了01,03,救救我吧,不然我死定了!
#include <reg51.h>
#include <string.h>
#include <intrins.h>
#define uint unsigned int
#define HIGH 1
#define LOW  0
#define FALSE 0
#define TRUE ~FALSE
#define uchar unsigned char
#define WRITE  0xa0
#define READ   0xa1
uchar    databuff;
uchar str;
sbit     SDA=P1^5;
sbit     SCL=P1^4;
sbit     bell=P2^5;
sbit     led_yellow=P2^2;
sbit     led_red=P2^1;
void delay(void);
void I_start(void);
void I_stop(void);
void I_init(void);
bit I_clock(void);
bit I_send(uchar I_data);
uchar I_receive(void);
void I_Ack(void);
bit E_address(uchar Address);
bit E_read_address(uchar Address);
void wait_5ms(void);
bit E_write_address(uchar Address);
void bellx(uchar bell_count);
void delay_us(uint delay_time);
void ddelay(uint delay_time);           //延时delay_timeMS

void main(void)
{
bit temp;
databuff=0x03;
str=0;
temp=E_write_address(0x01);
if(temp) bellx(2);
else led_yellow=0;
ddelay(100);
ddelay(100);
ddelay(100);
ddelay(100);
ddelay(100);
ddelay(100);
temp=E_read_address(0x01);
if(temp) bellx(3);
else led_red=0;
ddelay(100);
ddelay(100);
ddelay(100);
ddelay(100);
ddelay(100);
ddelay(100);
if(str==databuff) bellx(5);
else 
    {
    led_red=0;
    led_yellow=0;
    }
while(1);
}


/*功能:本函数实际上只有一条返回指令,在具体应用中
可视具体要求增加延时指令*/
void delay(void)
{
  _nop_();
  _nop_();
  _nop_();
}

/*功能:提供I2C总线工作时序的起始位。*/
void I_start(void)
{
SCL=HIGH;
delay();    
SDA=LOW;
delay();
SCL=LOW;
delay();
}

/*功能:提供I2C总线工作时序的停止位。*/
void I_stop(void)
{
SDA=LOW;
delay();
SCL=HIGH;
delay();
SDA=HIGH;
delay();
SCL=LOW;
delay();    
}

/*功能:I2C总线初始化。在MAIN()函数中应首先调用本函数,然后再调用其它函数。*/
void I_init(void)
{
SCL=LOW;
I_stop();    
}

/*功能:提供I2C总线的时钟信号,并返回在时钟电平位高期间SDA信号线
上状态。本函数可用于数据发送,也可用于数据接收*/
bit I_clock(void)
{
bit sample;
SCL=HIGH;
delay();
sample=SDA;
SCL=LOW;
delay();return(sample);    
}

/*功能:向I2C总线发送8位数据,并请求一个应答信号ACK。如果收到
ACK应答则返回1(TRUE),否则返回0(FALSE)。*/
bit I_send(uchar I_data)
{
register uchar i;
/*发送8位数据*/
for(i=0;i<8;i++)
    {
    SDA=(bit)(I_data&0x80);
    I_data=I_data<<1;
    I_clock();    
    }
SDA=HIGH;
return (~I_clock());
}

/*功能:从I2C总线上接收8位数据信号,并将接收到8位数据作为一个字节
返回,不回送应答信号ACK。主函数在调用本函数之前应保证SDA信号线处于
浮置状态,即使8051的P1.7脚置1。*/
uchar I_receive(void)
{
uchar I_data=0;
register uchar i;
for(i=0;i<8;i++)
    {
    I_data*=2;
    if(I_clock())
        I_data++;
    
    }
return(I_data);    
}

/*功能:向I2C总线发送一个应答信号ACK,一般用于连续数据读取时。*/
void I_Ack(void)
{
SDA=LOW;
I_clock();
SDA=HIGH;    
}


/*功能:向24c01写入器件地址和一个指定的字节地址。*/
bit E_address(uchar Address)
{
I_init();
I_start();
if(I_send(WRITE))
    return(I_send(Address));
else
    return(FALSE);
}

/*功能:从24c01中读取data_size个字节的数据并存放到databuff里,采用序列读操作方式
从片
内ADDRESS地址处连续读取数据。如果24c01不接收指定的地址在返回0*/ 
bit E_read_address(uchar Address)
{
I_init();                     //从地址0开始读取数据
if(E_address(Address))
    {
     I_start();
    if(I_send(READ))
        {
        str=(I_receive());
        I_clock();
        I_stop();
        return(TRUE);
        }
    else
        {
        I_stop();
        return(FALSE);
        }
    }
    else
        I_stop();
        return(FALSE);
}

/*功能:提供5ms延时(时钟频率12MHZ)*/
void wait_5ms(void)
{
register int i;
for(i=0;i<1000;i++)
    ;
}

/*功能:将数据缓冲区databuff中的数据写入到24c01的以Address地址开始的data_size个
字节。
采用字节写操作方式,每次写入时都需要指定片内地址。如果24c01不接受指定的地址或某
个传送
的字节未收到应答信号ACK,在返回0(FALSE).*/
bit E_write_address(uchar Address)
{
if(E_address(Address)&&I_send(0x03))
        {
        I_stop();
        wait_5ms();
        return(TRUE);
        }
    else
        return(FALSE);
}

void bellx(uchar bell_count)
{
uint count1;
do
    {
    for(count1=0x019b;count1>0;count1--)
          {
        bell=0;
        delay_us(55);
        _nop_();
        _nop_();
        _nop_();
        _nop_();
      _nop_();
       _nop_();
       _nop_();
       _nop_();
        _nop_();
        _nop_();
       _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
       _nop_();
        _nop_();
        _nop_();
         bell=1;
        delay_us(55);
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
           _nop_();
        _nop_();
        _nop_();
       _nop_();
        _nop_();
        _nop_();
        _nop_();
      _nop_();
       _nop_();
       _nop_();
       _nop_();
        _nop_();
      _nop_();
        _nop_();
        _nop_();
        _nop_();
        }
    ddelay(80);
    bell_count--;
    }
while(bell_count);
return ;
}


void delay_us(uint delay_time)
{
for(;delay_time>0;delay_time--)
      {
     _nop_();
     _nop_();
    }

  return;
}

void ddelay(uint delay_time)           //延时delay_timeMS

delay_time*=50;
for(;delay_time>0;delay_time--)
      {
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
    }

  return;
}
     

  
11楼:半夜开车 2001年10月16日16:56
 24c01与24C02不同,24C01(atmel)是简约型的.以下是读写程序. 多年以来,数据奔腾而过,从未错过
/*------------------------------------------------------------------------------
 为了安全起见,程序中很多NOP是冗余的,希望读者能进一步精简,但必须经过验证。
        Atmel 24C01 比较特殊,为简约型.
        51晶振为11.0592MHz
〖参考〗  <a href=http://www.c51bbs.com target=_blank>    </a>  
〖版本〗V1.00A Build 0918
-----------------------------------------------------------------------------*/


#include "reg51.h"
#include "intrins.h"

sbit SCL= P1^5;
sbit SDA= P1^4;

delay()
{
unsigned int i=1200;
while(i--);
}
/*----------------------------------------------------------------------------
调用方式:write_8bit(unsigned char ch)  ﹫2001/03/23
函数说明:内函数,私有,用户不直接调用。
-------------------------------------------------------------------------------
*/
void  write_8bit(unsigned char ch)
{
    unsigned char i=8;
    SCL=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();
    while (i--)
    {
        SDA=(bit)(ch&0x80);
        _nop_();_nop_();_nop_();_nop_();_nop_();
        ch<<=1;
        SCL=1;
        _nop_();_nop_();_nop_();_nop_();_nop_();
        SCL=0;
        _nop_();_nop_();_nop_();_nop_();_nop_();
    }
    _nop_();_nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();_nop_();
}

/*------------------------------------------------------------------------------
调用方式:void ACK(void)  ﹫2001/03/23
函数说明:内函数,私有,用户不直接调用。
-------------------------------------------------------------------------------
*/
void ACK(void)
{
   unsigned char time_1;
    SDA=1;
    SCL=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();
    SCL=1;
    time_1=5;
    while(SDA) {if (!time_1) break;} //ACK
    SCL=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();
}


unsigned char ReadIIC_24C01(unsigned char address)
{
      unsigned char ddata=0;
      unsigned char i=8;

    SCL=1;
    _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();   //Tsu:STA
    SDA=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //Thd:STA
    SCL=0;             //START

    write_8bit( (address<<1) | 0x01);   //写页地址和操作方式
    ACK();

    while (i--)
    {
        SDA=1;
        ddata<<=1;
        SCL=0;_nop_();_nop_();_nop_();_nop_();_nop_();SCL=1;
        if (SDA) ddata|=0x01;
    }

    SCL=0;_nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
    SDA=0;_nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
        SDA=1;   //STOP
    delay();
    return ddata;

}


void WriteIIC_24C01(unsigned char address,unsigned char ddata)
{

    SCL=1;
    _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();   //Tsu:STA
    SDA=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //Thd:STA
    SCL=0;             //START

    write_8bit( (address<<1) & 0xfe);   //写页地址和操作方式,对于24C32-
24C256,page不起作用
    ACK();
    write_8bit(ddata);      //发送数据
    ACK();
    SDA=0;
        _nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
        SDA=1;   //STOP
        delay();
}

  
12楼:东海飘萍客 2001年10月16日22:13
 谢谢,我明天去试一下,不知道24c01接法有没有什么特别的地方??
  
13楼:RobinHood 2001年10月16日22:25
 如对成本要求不高,可使用24LC01(24M以下标准51系统基本可零等待)。如非用24C01不可,则要注意字节帧尾的从器件握手信号等待(器件可靠时可用如JB P*.*,$实现),以及写入帧间隔等待,可
如对成本要求不高,可使用24LC01(24M以下标准51系统基本可零等待)。如非用24C01不
可,则要注意字节帧尾的从器件握手信号等待(器件可靠时可用如JB P*.*,$实现),以及写
入帧间隔等待,可用写入后的读循环可靠的判定写入是否结束。
  
14楼:RobinHood 2001年10月16日22:32
 24c01与24C02的驱动方法基本一样,只是24C01有一半的地址空间是无效的
  
15楼:东海飘萍客 2001年10月17日08:48
 我自己写了一个程序,但是只能读写64个字节的内存,为什么??
  
16楼:东海飘萍客 2001年10月17日15:31
 再讨论一下24c01
我现在已经可以往24C01里写东西,但是一次只能写4个数据。当我想向07h开始的内存单元
写4个字节的数据时,结果却写到07、04、05、06单元去了,就是不能到08h单元,如果我向
08h开始的内存单元写4个字节的数据,可以正常写入。不知为什么,不知大虾们是否可以帮
我解释一下,谢谢!!还有,读数据时是否有什么限制??

  
17楼:shengxh12 2006年1月15日14:34
 写入和读出地址不对
写入和读出地址不对
  
18楼:xiaop0423 2006年1月16日10:39
 如果还没高顶,给我写信把!
njzr@tom.com
  
19楼:tywood 2006年1月24日09:14
 我晕
/*------------------------------------------------------------------------------
调用方式:void ACK(void)  ﹫2001/03/23
函数说明:内函数,私有,用户不直接调用。
-------------------------------------------------------------------------------
*/
void ACK(void)
{
   unsigned char time_1;
    SDA=1;
    SCL=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();
    SCL=1;
    time_1=5;
    while(SDA) {if (!time_1) break;} //ACK
    SCL=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();
}

上面这个函数的
    while(SDA) {if (!time_1) break;} //ACK
语句好象是死循环啊?

我做了一块板子用P34做SCL,P35做SDA,WP接到P33。可是忘记加上拉电阻了,运行上面的程序,结果在上面提到的while语句卡死了。

我想问一个问题:P3口不是有内部上拉电阻了吗,24C01不接再接上拉电阻行不行啊?
哪位老大来回答一下啊,老板急着催我呢!
晕死了!

  
20楼:adaizhu 2006年4月27日15:57
 ack()??
time_1=5;
    while(SDA) {if (!time_1) break;} //ACK

这句啥意思啊,我的程序到这里就死循环了啊


>>>>>>对该主题发表你的看法

本主题贴数21,分页: [第1页] [第2页]


[上一篇主题]:初学者:请教古斑竹:我想学C51,在网上看到了您推荐的徐教授KEIL C51 学

[下一篇主题]:AVR单片机:老古,我从你的下载区下载了AVR教程,但是打不开,从你上面下载了PDF阅读软件后,还是