#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操作,但为什么只写有错,而读的数据不会出错?)。
|