打印
[应用相关]

写数据总是失败

[复制链接]
933|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
litengg|  楼主 | 2017-3-23 16:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
程序功能:将数据存入24c08,然后用led显示存入的数据
*/

#define uchar unsigned char
#define uint unsigned int

#define SCL_H P1OUT |= BIT2      //高低电平宏定义
#define SCL_L P1OUT &= ~BIT2
#define SDA_H P1OUT |= BIT3
#define SDA_L P1OUT &= ~BIT3

#define SCL_OUT P1DIR |= BIT2    //将P1.2口(SCL)设为输出状态
#define SDA_OUT P1DIR |= BIT3    //将P1.3口(SDA)设为输出状态
#define SDA_IN P1DIR &= ~BIT3    //将P1.3口设为输入状态,判断SDA高低电平
#define SDA_T (P1IN & BIT3)      //用于数据线(SDA)的检测

void delay(uchar n)           //短暂延时函数,用于电平延时
{
  uchar i,j;
  for(i=n;i>0;i--)            
    for(j=0;j<5;j++);      
}

void io_init()        //用于显示
{
  P2DIR = 0XFF;       //用于led显示
}

void iic_init()      //iic总线初始化  
{
  SCL_OUT;           //将P1.2口(SCL)设为输出状态
  SDA_OUT;
  delay(1);
  
  SCL_H;
  delay(1);
  SDA_H;
  delay(1);
}

void start()
{
  SDA_OUT;
  delay(1);
  
  SCL_H;
  delay(1);
  SDA_H;
  delay(1);
  SDA_L;
  delay(1);
}

void stop()
{
  SDA_OUT;
  delay(1);
  
  SCL_H;
  delay(1);
  SDA_L;
  delay(1);
  SDA_H;
  delay(1);
}

void respon()                 //可能有问题 ,简化了应答机制      
{
  uchar i=0;
  SDA_IN;                     //输入,用于读数据
  
  SCL_H;                      //高电平时
  delay(1);
  while((SDA_T==1)&&(i<252))   //等待应答,即SDA拉低0
  {
    i++;
  }
}

void writebyte(uchar data)     //从最高位开始传送
{
  uchar i;
  SDA_OUT;
  
  for(i=0; i<8; i++)
  {
    SCL_L;
    delay(1);
    if((data&0x80)==0x80)
      SDA_H;
    else
      SDA_L;
    delay(1);
   
    SCL_H;
    delay(1);
    data = data << 1;     //data左移7次即可,第8次没给sda
  }
}

uchar readbyte()              //从最高位开始读
{
  uchar i,temp=0;
  SDA_IN;                     //输入,用于读数据
  delay(1);
   
  for(i=0; i<8; i++)
  {
    SCL_L;                      //允许数据变化
    delay(1);
    SCL_H;                    //停止数据变化
    delay(1);
    temp = (temp<<1)|SDA_T;
    delay(1);
  }
  return temp;
}

void write_24c08(uchar add,uchar data)
{
  start();
  writebyte(0xa0);   //单字节写入
  respon();
  writebyte(add);
  respon();
  writebyte(data);
  respon();
  stop();
}

uchar read_24c08(uchar add)
{
  uchar data;
  start();
  writebyte(0xa0);   //单字节写入
  respon();
  writebyte(add);
  respon();
  
  start();
  writebyte(0xa1);   //单字节读
  respon();
  data = readbyte();
  stop();
  return data;
}

void main(void)
{
  uchar data;             //用于存放读出的数据
  WDTCTL = WDTPW + WDTHOLD;
  io_init();
  iic_init();
  
  write_24c08(8,0x55);    //随便写入一个数据      
  data = read_24c08(8);

  P2OUT = data;           //用led显示
  while(1);
}
沙发
feiqi1| | 2017-3-23 16:51 | 只看该作者
到底是写24C02操作失败,还是LED操作失败?

使用特权

评论回复
板凳
androidbus| | 2017-3-23 16:55 | 只看该作者

应该是操作24c02失败了吧。。

使用特权

评论回复
地板
qiangweii| | 2017-3-23 17:01 | 只看该作者
你最好看下这段应答函数产生的时序,和24c02手册对比一下

使用特权

评论回复
5
shashaa| | 2017-3-23 17:04 | 只看该作者
估计是读写速度有问题吧?

使用特权

评论回复
6
xia00| | 2017-3-23 17:07 | 只看该作者
可能是硬件问题,模拟I2C的两条输出线要加上拉电阻。

使用特权

评论回复
7
ericw0ng| | 2017-3-23 17:07 | 只看该作者
直接看看示波器,不就知道问题了吗?

使用特权

评论回复
8
hfdy01| | 2017-3-23 17:10 | 只看该作者
以后遇到这个问题就需要注意了。

使用特权

评论回复
9
CallReceiver| | 2017-3-23 17:14 | 只看该作者
写内置的eeprom没有这么多问题

使用特权

评论回复
10
boy1990| | 2017-3-23 17:19 | 只看该作者
这个需不需要内部刷新一下?

使用特权

评论回复
11
sourceInsight| | 2017-3-23 17:21 | 只看该作者
现在很多的芯片都有写保护了。

使用特权

评论回复
12
minzisc| | 2017-3-24 16:55 | 只看该作者
有写数据成功的时候吗

使用特权

评论回复
13
minzisc| | 2017-3-24 16:57 | 只看该作者
可能配置的不正确,存在问题。

使用特权

评论回复
14
feelhyq| | 2017-3-24 17:28 | 只看该作者
void writebyte(uchar data) 这个函数最后一行 将SCL拉低,即数据写完后将时钟线拉低。 I2C的时钟线不使用后应该拉低的,防止产生stop信号(时钟线在高电平的时候,此时数据线在低电平,不小心将数据线由低拉高导致产生stop信号)。

uchar readbyte()            这个函数   如果你的SCL和SDA 2个管脚配置的是开漏的话, 将这一行(SDA_IN;                     //输入,用于读数据) 删掉,将SDA拉高即可(释放SDA总线,让从机,即EEPRO接管SDA线,用于EEPROM传输数据)。

使用特权

评论回复
15
feelhyq| | 2017-3-24 17:31 | 只看该作者
建议楼主将I2C协议理解透彻, ”clk在不使用(读完一个字节或者写完一个字节数据)的时候拉低,  sda在读数据之前释放自己,即拉高自己”

使用特权

评论回复
16
lefeng| | 2017-3-29 21:00 | 只看该作者
时序问题??

使用特权

评论回复
17
Bjorn| | 2017-3-30 20:50 | 只看该作者
示波器查看一下时序

使用特权

评论回复
18
Prry| | 2017-3-31 00:17 | 只看该作者

单片机常用的总线如i2c、spi、uart等,将其硬件抽象层分离,相关外设在其抽象层上的应用函数接口调用。这样的好处是 :
1、外设的驱动方便移植到任何单片机;
2、外设总线方便移植到其他单片机,只需更改部分寄存器配置;
3、总线调试OK后,调试新的外设程序时,不用重重复复调试总线的程序。
比如,楼上的程序分层就不够好,i2c总线和eeprom交叉,假如我这个i2c总线要挂其他i2c设备(传感器、ADC等),那又得重新写一次总线程序?又重新配置?又调试时序对不对?做重复的工作就是浪费青春啊!假设换了一家公司,用了不同单片机,这个eeprom程序移植到其他单片机时又是重新写一遍,多吃力啊。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

51

主题

1597

帖子

4

粉丝