⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 Discription: This multi-master driver provides the software interface to the I2C Bus hardware of th
💻 C
📖 第 1 页 / 共 2 页
字号:
		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 + -