📄 i2c.c
字号:
retstat=status=i2c_wait_for_script();
if( status == stat_success )
{
retstat = status;
flgFinished = true;
}
// timeouts: serious problem. Try to revive the bus, if successful, try action again. If not -> bad.
if( (status == stat_timeout_in_init) || (status == stat_timeout_after_address )
|| ( status == stat_timeout_at_address) || (status == stat_timeout_in_start) ||
(status == stat_timeout_in_write) || (status == stat_timeout_in_read))
{
retstat = stat_bus_broken;
if( !reviveBus() || (revivCnt == MAX_REVIV_CNT) )
{
flgFinished = true;
}
U2C1 = 0x05;
++revivCnt;
}
if( status == stat_no_ack_from_device )
{
if( nackCnt == max_nackcount )
{
flgFinished = true;
}
++nackCnt;
}
if(( status == stat_arb_lost_in_address ) || (status == stat_arb_lost_in_write)
|| (status==stat_arb_lost_in_nack))
{
if( narbCnt == max_errcount )
{
flgFinished = true;
}
++narbCnt;
}
if ((status == stat_data_error_write) || (status == stat_data_error_read))
{
if( readCnt == max_errcount )
{
flgFinished = true;
}
++readCnt;
}
} while( !flgFinished );
return retstat;
}
//#define WC_EEPROM_PORT P6
//#define WC_EEPROM_PORT_DIR PD6
//#define WC_EEPROM_MASK 0x01
/*
* --------------------------------------------------------------
* Has to be entered with locked semaphore
* --------------------------------------------------------------
*/
int
switchMux(byte adr,byte val) {
I2C_Context *ctxt=&i2cContext;
int ip=0;
i2c_clear_script(ctxt);
ctxt->script[ip++]=CMD_I2C_CHECK_ADDR_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
ctxt->data=&val;
ctxt->script[ip++]=CMD_I2C_WRITEDATA;
ctxt->script[ip++]=CMD_I2C_CHECK_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
ctxt->script[ip++]=CMD_I2C_STOP;
ctxt->script[ip++]=CMD_I2C_WAKEUP;
ctxt->script[ip++]=CMD_I2C_SCRIPT_END;
return i2c_execute_master_transaction(adr,0,I2C_MAX_ARBLOSS,I2C_MAX_NACKS);
}
static int
switch_to_i2c_bus(I2C_Context *ctxt,byte new_bus) {
int retval;
word ip=0;
byte mux_nr;
byte old_mux_nr;
if(new_bus==ctxt->currBus) {
return stat_success;
}
mux_nr=(new_bus>>4)&0xf;
if(ctxt->muxAddrs[mux_nr]==-1) {
return stat_success;
}
if(ctxt->currBus>=0) {
old_mux_nr=(ctxt->currBus>>4)&0xf;
retval=switchMux(ctxt->muxAddrs[old_mux_nr],e_busNoneActive);
}
ctxt->currBus=new_bus;
retval= switchMux(ctxt->muxAddrs[mux_nr],new_bus&0xf);
return retval;
}
/*
* --------------------------------------------
* Write to an I2C device
* --------------------------------------------
*/
byte masterWriteI2C( byte nBytes, void* pData, word devAdr )
{
word ip=0;
byte retstat;
I2C_Context *ctxt=&i2cContext;
OS_Use( &ctxt->i2cLockSema );
switch_to_i2c_bus(ctxt,devAdr>>8);
i2c_clear_script(ctxt);
ctxt->script[ip++]=CMD_I2C_CHECK_ADDR_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
ctxt->data=pData;
if(nBytes) {
ctxt->script[ip++]=CMD_I2C_LOOP; *(word*)(ctxt->script+ip)=nBytes;ip+=2;
ctxt->script[ip++]=CMD_I2C_WRITEDATA;
ctxt->script[ip++]=CMD_I2C_CHECK_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
ctxt->script[ip++]=CMD_I2C_ENDLOOP;
}
ctxt->script[ip++]=CMD_I2C_STOP;
ctxt->script[ip++]=CMD_I2C_WAKEUP;
ctxt->script[ip++]=CMD_I2C_SCRIPT_END;
retstat=i2c_execute_master_transaction(devAdr,0,I2C_MAX_ARBLOSS,I2C_MAX_NACKS);
OS_Unuse( &ctxt->i2cLockSema );
return retstat;
}
/*
* -----------------------------------------------------------
* Check if a device is present at the given adress
* This is done by trying to write 0 bytes to the device
* -----------------------------------------------------------
*/
byte
scanAddressI2C( word devAdr )
{
word ip=0;
byte retstat;
I2C_Context *ctxt=&i2cContext;
OS_Use( &ctxt->i2cLockSema );
switch_to_i2c_bus(ctxt,devAdr>>8);
i2c_clear_script(ctxt);
ctxt->script[ip++]=CMD_I2C_CHECK_ADDR_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
ctxt->script[ip++]=CMD_I2C_STOP;
ctxt->script[ip++]=CMD_I2C_WAKEUP;
ctxt->script[ip++]=CMD_I2C_SCRIPT_END;
retstat=i2c_execute_master_transaction(devAdr,0,I2C_MAX_ARBLOSS,SCAN_MAX_NACKS);
OS_Unuse( &ctxt->i2cLockSema );
return retstat;
}
/*
* ------------------------------------------------------------------------
* Read from an I2C device like temperature sensor....
* ------------------------------------------------------------------------
*/
byte
masterReadI2C( byte nBytes, void* pData, word devAdr)
{
word ip=0;
byte retstat;
I2C_Context *ctxt=&i2cContext;
if(!nBytes)
return stat_success;
OS_Use(&ctxt->i2cLockSema);
switch_to_i2c_bus(ctxt,devAdr>>8);
i2c_clear_script(ctxt);
ctxt->script[ip++]=CMD_I2C_CHECK_ADDR_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
ctxt->data=pData;
if(nBytes>1) {
ctxt->script[ip++]=CMD_I2C_LOOP; *((word*)(ctxt->script+ip))=nBytes-1; ip+=2;
ctxt->script[ip++]=CMD_I2C_TRIGGER_RX;
ctxt->script[ip++]=CMD_I2C_READDATA;
ctxt->script[ip++]=CMD_I2C_SEND_ACKBIT;
ctxt->script[ip++]=CMD_I2C_ENDLOOP;
}
ctxt->script[ip++]=CMD_I2C_TRIGGER_RX_NOACK;
ctxt->script[ip++]=CMD_I2C_READDATA;
ctxt->script[ip++]=CMD_I2C_SEND_NACKBIT;
ctxt->script[ip++]=CMD_I2C_STOP;
ctxt->script[ip++]=CMD_I2C_WAKEUP;
ctxt->script[ip++]=CMD_I2C_SCRIPT_END;
retstat=i2c_execute_master_transaction(devAdr,1,I2C_MAX_ARBLOSS,I2C_MAX_NACKS);
OS_Unuse( &ctxt->i2cLockSema );
return retstat;
}
/*
* ---------------------------------------------------------------------------------------
* routine for reading from 24c02...24c64 I2C-EEPROMS or devices with the same protocol
* ---------------------------------------------------------------------------------------
*/
byte readEEProm(word adr, word len, void *pdata, word devAdr, byte eepromType)
{
word ip=0;
byte retstat;
I2C_Context *ctxt=&i2cContext;
if(!len) {
return stat_success;
}
OS_Use( &ctxt->i2cLockSema );
switch_to_i2c_bus(ctxt,devAdr>>8);
i2c_clear_script(ctxt);
ctxt->script[ip++]=CMD_I2C_CHECK_ADDR_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
if( eepromType == eeprom_Large ) {
ctxt->script[ip++]=CMD_I2C_WRITEB; ctxt->script[ip++]=adr>>8;
ctxt->script[ip++]=CMD_I2C_CHECK_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
}
ctxt->script[ip++]=CMD_I2C_WRITEB; ctxt->script[ip++] = adr & 0xff;
ctxt->script[ip++]=CMD_I2C_CHECK_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
ctxt->script[ip++]=CMD_I2C_REPSTART; ctxt->script[ip++] = (devAdr<<1)|1;
ctxt->script[ip++]=CMD_I2C_CHECK_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
ctxt->data=pdata;
if(len>1) {
ctxt->script[ip++]=CMD_I2C_LOOP; *((word*)(ctxt->script+ip))=len-1; ip+=2;
ctxt->script[ip++]=CMD_I2C_TRIGGER_RX;
ctxt->script[ip++]=CMD_I2C_READDATA;
ctxt->script[ip++]=CMD_I2C_SEND_ACKBIT;
ctxt->script[ip++]=CMD_I2C_ENDLOOP;
}
ctxt->script[ip++]=CMD_I2C_TRIGGER_RX_NOACK;
ctxt->script[ip++]=CMD_I2C_READDATA;
ctxt->script[ip++]=CMD_I2C_SEND_NACKBIT;
ctxt->script[ip++]=CMD_I2C_STOP;
ctxt->script[ip++]=CMD_I2C_WAKEUP;
ctxt->script[ip++]=CMD_I2C_SCRIPT_END;
retstat=i2c_execute_master_transaction(devAdr,0,I2C_MAX_ARBLOSS,EEPROM_MAX_NACKS);
OS_Unuse( &ctxt->i2cLockSema );
return retstat;
}
/*
* ------------------------------------------
* Write to an I2C EEPROM pagewise
* ------------------------------------------
*/
byte writeEEProm(word adr, word len, void* pdata, word devAdr, byte eepromType )
{
word ip;
word nbytes;
word pagelen = (eepromType==eeprom_Large) ? 0x20 : 0x10;
word pagemask=pagelen-1;
byte retstat=stat_success;
I2C_Context *ctxt=&i2cContext;
OS_Use( &ctxt->i2cLockSema );
switch_to_i2c_bus(ctxt,devAdr>>8);
ctxt->data=pdata;
while(len > 0) {
nbytes=pagelen - (adr & pagemask);
if(nbytes>len)
nbytes=len;
ip=0;
i2c_clear_script(ctxt);
ctxt->script[ip++]=CMD_I2C_CHECK_ADDR_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
if( eepromType == eeprom_Large ) {
ctxt->script[ip++]=CMD_I2C_WRITEB; ctxt->script[ip++]=adr>>8;
ctxt->script[ip++]=CMD_I2C_CHECK_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
}
ctxt->script[ip++]=CMD_I2C_WRITEB; ctxt->script[ip++] = adr & 0xff;
ctxt->script[ip++]=CMD_I2C_CHECK_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
if(len) {
ctxt->script[ip++]=CMD_I2C_LOOP; *(word*)(ctxt->script+ip)=nbytes;ip+=2;
ctxt->script[ip++]=CMD_I2C_WRITEDATA;
ctxt->script[ip++]=CMD_I2C_CHECK_ARB;
ctxt->script[ip++]=CMD_I2C_CHECK_ACK;
ctxt->script[ip++]=CMD_I2C_ENDLOOP;
}
ctxt->script[ip++]=CMD_I2C_STOP;
ctxt->script[ip++]=CMD_I2C_WAKEUP;
ctxt->script[ip++]=CMD_I2C_SCRIPT_END;
retstat=i2c_execute_master_transaction(devAdr,0,I2C_MAX_ARBLOSS,EEPROM_MAX_NACKS);
if(retstat!=stat_success)
break;
adr+=nbytes;len-=nbytes;
ctxt->data+=nbytes;
}
OS_Unuse( &ctxt->i2cLockSema );
return retstat;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -