打印

IIC口线操作变慢之后读数统一被乘2,是为什么?

[复制链接]
4185|39
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
alphal|  楼主 | 2007-10-8 09:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我的程序中为了程序结构的清晰,IO口操作全部统一出口为GPIO操作,例如:
sbit eepromSDA = P1^2 ;
eepromSDA = 1;

对应GPIO实现为
#define setBit(x,b)             (x) |=  (1U<<(b))
#define clearBit(x,b)        (x) &= ~(1U<<(b))
#define eepromSDA_PORT P1
#define eepromSDA_PIN  2

#define SET_SDAEEPROM_HIGH   setBit(eepromSDA_PORT,eepromSDA_PIN) ;
#define SET_SDAEEPROM_LOW    clearBit(eepromSDA_PORT,eepromSDA_PIN) ;
......

这样原来一个指令周期能实现的端口操作现在需要大概6~8个周期实现,eeprom驱动程序使用这种方式之后发现写数据没有问题,但读数据的时候统一
被乘了2,即本该是1读出却是2,本是2读出为4,而IO口操作改回之前的方式就没有问题,并程序中已关掉了中断,程序时序、代码上没有问题,难道是IIC操作慢了就会造成这种问题吗???

相关帖子

沙发
qjy_dali| | 2007-10-8 10:30 | 只看该作者

IIC本身当然没有这个问题

其实说乘2不合适,而是左移了。也就是你的程序该读第7位时却读了EEPROM第6位,该读第6位时却读了EEPOM发出的第5位...

使用特权

评论回复
板凳
ayb_ice| | 2007-10-8 10:45 | 只看该作者

肯定是程序的问题。。。

使用特权

评论回复
地板
alphal|  楼主 | 2007-10-8 11:04 | 只看该作者

。。。。

to qjy_dali:
乘2是被左移了, 但是是出现你说的“也就是你的程序该读第7位时却读了EEPROM第6位,该读第6位时却读了EEPOM发出的第5位”还是“读完了后被多移了一次”或者别的原因?但程序逻辑上是看不出这样的操作的,并且只要把IO操作改回原来的方式就正常了。问题好像就在这个定义方式不不同上面,而这两种定义方式的不同在于操作时占用的指令周期不一样。而且写的时候就没有问题。

to ayb_ice :
我也觉得该是程序的问题,但只要把IO操作改回原来的方式就正常了如何解释?

使用特权

评论回复
5
qjy_dali| | 2007-10-8 11:13 | 只看该作者

请问你的SCL用的也是P1口的其它线吗?

使用特权

评论回复
6
ayb_ice| | 2007-10-8 11:22 | 只看该作者

是不是你的宏定义错了,或是指令执行时间不一样。。。

 (x) |=  (1U<<(b)) 8位机此处用1U不好,用1就行了。。。

使用特权

评论回复
7
alphal|  楼主 | 2007-10-8 11:36 | 只看该作者

、、、、

to qjy_dali :
sda和scl都是用的P2的口线,P2做io口用的,没有接地址总线,芯片内集成有3k的xdata空间,iic操作的时候把中断关闭了,(中断程序有有对xdata的操作,并测试发现如果不关中断确实对iic操作有较大影响,但是也只是对写操作会报失败,读没有问题,这一点也比较费解,难道是中断中P2口有对xdata寻址而混淆iic操作,但为什么只写有错,而读的数据不会出错?)。

to ayb_ice:
宏定义有错?但是同样的方式操作io口控制其它器件就没有问题。

使用特权

评论回复
8
qjy_dali| | 2007-10-8 12:54 | 只看该作者

我也有点模糊了

你上面不是写的P1吗?MCU是什么型号?EEPROM是什么型号?还有,I2C的上拉电阻是多少?

使用特权

评论回复
9
alphal|  楼主 | 2007-10-8 13:04 | 只看该作者

to qjy_dali:

不好意思,上面写P1只是方法举例,实际电路中使用的是P2口,
芯片是SST89E594,24C256,上拉为5.1K。

使用特权

评论回复
10
ayb_ice| | 2007-10-8 13:21 | 只看该作者

那就没有问题。。。

使用特权

评论回复
11
alphal|  楼主 | 2007-10-8 13:31 | 只看该作者

没有问题???那我问的哪些问题呢????

使用特权

评论回复
12
alphal|  楼主 | 2007-10-8 16:33 | 只看该作者

求助。。。。

使用特权

评论回复
13
ayb_ice| | 2007-10-8 16:39 | 只看该作者

先不用宏操作试一下。。。

使用特权

评论回复
14
hotpower| | 2007-10-9 00:42 | 只看该作者

程序不帖鬼才知道~~~

使用特权

评论回复
15
fsaok| | 2007-10-9 07:52 | 只看该作者

.

程序不帖鬼才知道~~~


既然 鬼才 知道,为什么不去问 鬼才

使用特权

评论回复
16
alphal|  楼主 | 2007-10-9 08:22 | 只看该作者

汗。。。。鬼才快献身。。。

贴什么程序?IIC驱动程序?情况和问题我已经说清楚了吧。

使用特权

评论回复
17
xwj| | 2007-10-9 08:24 | 只看该作者

LZ,鬼才 被你吓跑了...

使用特权

评论回复
18
ayb_ice| | 2007-10-9 08:27 | 只看该作者

鬼才

使用特权

评论回复
19
alphal|  楼主 | 2007-10-9 08:37 | 只看该作者

我贴。。。。

#include "global.h"
#include "hw_gpiodrv.h"

#define setBit(x,b)             (x) |=  (1U<<(b))
#define clearBit(x,b)        (x) &= ~(1U<<(b))
#define flipBit(x,b)         (x) ^=  (1U<<(b))
#define flipbyte(x)        (x) ^= 0xff
#define testBit(x,b)        ((x) &  (1U<<(b)))

#define      hwgpio_ReadPort(port_x)             port_x
#define     hwgpio_WritePort(port_x, val)    port_x = val
#define    hwgpio_SetPin(port_x,pin_x)             setBit(port_x,pin_x)
#define    hwgpio_ClearPin(port_x, pin_x)    clearBit(port_x, pin_x)
#define    hwgpio_flipPin(port_x, pin_x)        flipBit(port_x, pin_x)
#define    b_hwgpio_ReadPin(port_x, pin_x)    testBit(port_x,pin_x)            

#define     AT24C256_I2cWRITE         0xA0    // 定义24CXX的器件地址SLA和方向位W 
#define     AT24C256_I2cREAD          0xA1    //定义24CXX的器件地址SLA和方向位R

#define      I2CEPR_DELAY                          _nop_();_nop_(); _nop_(); _nop_();     _nop_();      _nop_(); _nop_();

#define      SET_SDAEPR_HIGH       hwgpio_SetPin( EPR_SDA_PORT, EPR_SDA_PIN)                /* set SDA to high */
#define      SET_SDAEPR_LOW    hwgpio_ClearPin( EPR_SDA_PORT, PR_SDA_PIN)        /* set SDA to low */

#define      SET_SCLEPR_HIGH   hwgpio_SetPin( EPR_SCL_PORT, EPR_SCL_PIN)             /* set SCL to high */
#define      SET_SCLEPR_LOW    hwgpio_ClearPin( EPR_SCL_PORT, EPR_SCL_PIN)         /* set SCL to low */

#define     SET_SDAEPR_TO_INPUT  hwgpio_SetPin( EPR_SDA_PORT, EPR_SDA_PIN)        
#define     SET_SDAEPR_TO_OUTPUT       ;

#define     GET_SDAEPR_VALUE   b_hwgpio_ReadPin( EPR_SDA_PORT, EPR_SDA_PIN)    

static void     _hwi2c_I2cSendStart(void);
static void     _hwi2c_I2cSendStop(void);
static void     _hwi2c_I2cSendNAck(void);
static u1_t     _u1_hwi2c_I2cGetAck(void);
static u1_t     _u1_hwi2c_I2cSendByte(u1_t value);
static void     _hwi2c_I2cSendAck(void);
static u1_t     _u1_hwi2c_I2cGetByte(void);
static u1_t     _u1_hwi2c_I2cGetLastByte(void);


/*
-----------------------------------------------------------------------------
Function name : _hwrtc_I2cSendStart  
Purpose :i2c bus write/read start program
Input parameters :none  
Output parameters : none
-----------------------------------------------------------------------------
*/
static void _hwi2c_I2cSendStart(void)
{
    SET_SDAEPR_HIGH;            //发送起始条件的数据信号     
    SET_SCLEPR_HIGH;                                     /* set SDA,SCL to high */
    I2CEPR_DELAY;                    //起始条件建立时间大于4.7us延时
    SET_SDAEPR_LOW;                //发送起始信号                      /* set SDA to low */
    I2CEPR_DELAY;                    //起始条件锁定时间大于4us
    SET_SCLEPR_LOW;                //钳住总线,准备发送或接收数据  /* set SCL to low */
    I2CEPR_DELAY;
}

/*
-----------------------------------------------------------------------------
Function name : _hwrtc_I2cSendStop  
Purpose :i2c bus write/read stop program
Input parameters :none  
Output parameters : none
-----------------------------------------------------------------------------
*/
static void _hwi2c_I2cSendStop(void)
{
    SET_SDAEPR_LOW;                                      /* set SDA to low */
    I2CEPR_DELAY ;
    SET_SCLEPR_HIGH;                                     /* set SCL to high */
    I2CEPR_DELAY ;
    SET_SDAEPR_HIGH;                                     /* set SDA to high */
    I2CEPR_DELAY ;
    SET_SCLEPR_LOW;  
}

/*
-----------------------------------------------------------------------------
Function name : _hwrtc_I2cSendNAck  
Purpose :Send NACK Signal
Input parameters :none  
Output parameters : none
-----------------------------------------------------------------------------
*/
static void _hwi2c_I2cSendNAck(void)
{
    SET_SDAEPR_HIGH;                         /* set SDA to high */
    I2CEPR_DELAY ;

    SET_SCLEPR_HIGH;                                     /* set SCL to high */
    I2CEPR_DELAY ;

    SET_SCLEPR_LOW;                                      /* set SCL to low */
    I2CEPR_DELAY ;
}


/*
-----------------------------------------------------------------------------
Function name : _u1_hwrtc_I2cGetAck  
Purpose :Get ACK Signal
Input parameters :none  
Output parameters : ACK Signal
-----------------------------------------------------------------------------
*/
static u1_t _u1_hwi2c_I2cGetAck(void)
{
    u1_t __temp = TRUE, __i = 0xFF;

    SET_SDAEPR_HIGH;                                             /* set SDA to high,Release SDA for ACK */
    I2CEPR_DELAY ;

//    SET_SDAEPR_TO_INPUT;                                /* set SDA -intput port */
    SET_SCLEPR_HIGH;                                             /* set SCL to high,raise ACK clock */
//--------------modified by whs 070929----------------------
    I2CEPR_DELAY ;
    while((--__i) && (__temp))
        {
             __temp = GET_SDAEPR_VALUE;
        } 

//    __temp = GET_SDAEPR_VALUE;                               /* get SDA status */
//-----------------------------------------------------------
//    __temp = rtc_SDA ;

//    SET_SDAEPR_TO_OUTPUT;                               /* set SDA -Output port */

    SET_SCLEPR_LOW;                                              /* set SCL to low */

    I2CEPR_DELAY ;

    if (__temp)                                              /* if success return 0x01,else return 0x00 */
    {
        return FALSE;
    }
    else
    {
        return TRUE;
    }
}

/*
-----------------------------------------------------------------------------
Function name : _u1_hwrtc_I2cSendByte  
Purpose :Send one byte to I2C interface
Input parameters :value-the Byte that will be sent  
Output parameters : TRUE or FALSE
-----------------------------------------------------------------------------
*/
static u1_t _u1_hwi2c_I2cSendByte(u1_t value)
{
    u1_t __i, __temp;

    for (__i = 0; __i < BITSOFBYTE; __i++)
    {
        __temp = value;
        __temp >>= 7 - __i;
        __temp &= 0x01;

        if (__temp == 0)
        {
            SET_SDAEPR_LOW;
        }                              /* set SDA to low */
        else
        {
            SET_SDAEPR_HIGH;
        }                             /* set SDA to high */

        I2CEPR_DELAY ;

        SET_SCLEPR_HIGH;                                 /* set SCL to high */
        I2CEPR_DELAY ;
        SET_SCLEPR_LOW;                                  /* set SCL to low */
        I2CEPR_DELAY ;
    }

    return(_u1_hwi2c_I2cGetAck());                         /* if sucess return 0x01,else return 0x00 */
}

/*
-----------------------------------------------------------------------------
Function name : _hwrtc_I2cSendAck  
Purpose :Send ACK Signal
Input parameters :none
Output parameters : none
-----------------------------------------------------------------------------
*/
static void _hwi2c_I2cSendAck(void)
{
    SET_SDAEPR_LOW;
    I2CEPR_DELAY ;
    SET_SCLEPR_HIGH;
    I2CEPR_DELAY ;

    SET_SCLEPR_LOW;
    I2CEPR_DELAY ;
}


/*
-----------------------------------------------------------------------------
Function name : _u1_hwrtc_I2cGetByte  
Purpose :Get one byte from  I2C interface
Input parameters :none
Output parameters : the byte from I2C interface
-----------------------------------------------------------------------------
*/
static u1_t _u1_hwi2c_I2cGetByte(void)
{
    u1_t __i, __temp, __temp1;

    __temp = 0;

    SET_SDAEPR_TO_INPUT;                

    for (__i = 0; __i < BITSOFBYTE; __i++)
    {
        __temp <<= 1;

        SET_SCLEPR_HIGH;
        I2CEPR_DELAY ;

        __temp1 = GET_SDAEPR_VALUE;
        __temp |= __temp1;

        SET_SCLEPR_LOW;
        I2CEPR_DELAY ;
    }

    SET_SDAEPR_TO_OUTPUT;

    _hwi2c_I2cSendAck();                    
    return(__temp);
}


/*
-----------------------------------------------------------------------------
Function name : _u1_hwrtc_I2cGetLastByte  
Purpose :Get the last byte form I2C interface
Input parameters :none
Output parameters : the last byte from I2C interface
-----------------------------------------------------------------------------
*/
static u1_t _u1_hwi2c_I2cGetLastByte(void)
{
    u1_t __i, __temp, __temp1;

    __temp = 0;

    SET_SDAEPR_TO_INPUT;                         

    for (__i = 0; __i < BITSOFBYTE; __i++)
    {
        __temp <<= 1;

        SET_SCLEPR_HIGH;
        I2CEPR_DELAY ;
        __temp1 = GET_SDAEPR_VALUE;
        __temp |= __temp1;

        SET_SCLEPR_LOW;
        I2CEPR_DELAY ;
    }

//    SET_SDAEPR_TO_OUTPUT;                 edit by whs  no define

    _hwi2c_I2cSendNAck();

    return(__temp);
}

/*
-----------------------------------------------------------------------------
Function name : u1_hwrtc_I2cReadBlock  
Purpose : write data to i2c device
Input parameters :
  mode: 1 for 1 byte address device,2 for 2 byte address device
Output parameters : none
-----------------------------------------------------------------------------
*/
u1_t u1_hwi2cepr_I2ceprReadBlock(u2_t address, u1_t* dat, u1_t size) 
{  
    u1_t         __i;
  u1_t         __status;
    bool_t    b_ea ;

    b_ea = _testbit_(EA) ;

    _hwi2c_I2cSendStart();
    __status = _u1_hwi2c_I2cSendByte(AT24C256_I2cWRITE);

  if (__status == TRUE)
  {
    __status = _u1_hwi2c_I2cSendByte((u1_t)(address>>BITSOFBYTE));   /*send the high byte first*/ 
  }

  if (__status == TRUE)
  {
    __status = _u1_hwi2c_I2cSendByte((u1_t)address);    
  }

  if (__status == TRUE)
  {
    _hwi2c_I2cSendStart();
    __status = _u1_hwi2c_I2cSendByte(AT24C256_I2cREAD);    
  }

  if (__status == TRUE)
  {
    for (__i=0; __i<size-1; __i++)
    {
      dat[__i] = _u1_hwi2c_I2cGetByte();
    }
    dat[__i] = _u1_hwi2c_I2cGetLastByte();
  }

    _hwi2c_I2cSendStop();

    EA = b_ea ;

  return (__status);
}

/*
-----------------------------------------------------------------------------
Function name : u1_hwrtc_I2cWriteBlock  
Purpose : read data from i2c device
Input parameters :
  mode: 1 for 1 byte address device,2 for 2 byte address device
Output parameters : none
-----------------------------------------------------------------------------
*/
u1_t u1_hwi2cepr_I2ceprWriteBlock(u2_t address, u1_t* dat, u1_t size)
{
    u1_t     __i;
  u1_t     __status;
    bool_t    b_ea ;

    b_ea = _testbit_(EA) ;

    _hwi2c_I2cSendStart();
    __status = _u1_hwi2c_I2cSendByte(AT24C256_I2cWRITE);

  if (__status == TRUE)
  {
    __status = _u1_hwi2c_I2cSendByte((u1_t)(address>>BITSOFBYTE));   /*send the high byte first*/ 
  }

  if (__status == TRUE)
  {
    __status = _u1_hwi2c_I2cSendByte((u1_t)address);    
  }

  if (__status == TRUE)
  {
    for (__i=0; __i<size; __i++)
    {
      __status = _u1_hwi2c_I2cSendByte( *(dat+__i) );
      if (__status == FALSE)
      {
        break;
      }
    }
  }

    _hwi2c_I2cSendStop();

    EA = b_ea ;

  return (__status);
}


/*
-----------------------------------------------------------------------------
Function name : hwrtc_I2cSetMode  
Purpose : set i2c mode 
Input parameters :
  mode: 1 for 1 byte address device,2 for 2 byte address device
Output parameters : none
-----------------------------------------------------------------------------
*/

void hwi2cepr_I2ceprInit(void)
{
        u1_t __i ;

        SET_SDAEPR_HIGH ;

        for(__i = 0; __i < 9; __i++)
        {
         SET_SCLEPR_HIGH ;
         I2CEPR_DELAY;
         SET_SCLEPR_LOW ;
         I2CEPR_DELAY;
        }

    _hwi2c_I2cSendStop();
}


问题:
1、该写数据没有问题(用该程序写,用正常的程序读发现没有问题),但读数据的时候统一被乘了2,(不会报失败),即本该是1读出却是2,本是2读出为4,而IO口操作改回之前的IO直接操作的方式就没有问题,并程序中已关掉了中断,程序时序、代码上没有问题,正常的和异常程序的不同只在于:一个指令周期能实现的端口操作现在需要大概6~8个周期实现,难道是IIC操作慢了就会造成这种问题吗???
2、中断程序有有对xdata的操作,并测试发现如果不关中断确实对iic操作有较大影响,(改回原来直接对io口操作的方式进行测试),也是也只是对写操作会报失败,读没有问题,这一点也比较费解,难道是中断中P2口有对xdata寻址而混淆iic操作,但为什么只写有错,而读的数据不会出错?
另:
芯片是SST89E594,24C256,上拉为5.1K。
sda和scl都是用的P2的口线,P2做io口用的,没有接地址总线,芯片内集成有3k的xdata空间,iic操作的时候把中断关闭了,(中断程序有有对xdata的操作,并测试发现如果不关中断确实对iic操作有较大影响,但是也只是对写操作会报失败,读没有问题,这一点也比较费解,难道是中断中P2口有对xdata寻址而混淆iic操作,但为什么只写有错,而读的数据不会出错?)。


使用特权

评论回复
20
alphal|  楼主 | 2007-10-9 10:09 | 只看该作者

help。。。。

使用特权

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

本版积分规则

112

主题

473

帖子

1

粉丝