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

📄 twi.c.svn-base

📁 AVR单片机下
💻 SVN-BASE
字号:
/*                ****ROBOCON 2009 | BUPT TEAM******* * ------------------------------------------------------------------------ * FileName   : twi.c * Version    : 2.0 * Brief      : * Code by    : leaf * Date       : Apr 28, 2009 * Note       : 接收者不处理NACK后的数据。 *  			发送者在收到NACK后发送一个0 *              主机接收如果没有收到足够的数据,应用程序应该处理这种情况 * * * ------------------------------------------------------------------------ */#include "lib_bupt.h"#ifdef TWI_H_INCLUDEDstatic TwiMode mode = TwiModeStop;inline void twiWait( void );static Mutex twiSignal;AVRX_SIGINT( TWI_vect ){	IntProlog();	AvrXIntSetSemaphore( &twiSignal );	Epilog();}void twiInit( UINT8 baud ){	cli();	AvrXResetSemaphore( &twiSignal );	TWBR = baud;	PORTD |= 0x03;	DDRD  &= ~0x03;	mode = TwiModeStop;	sei();}/* 初始化Twi传输,如果成功,返回当前的模式,失败返回负数值 * 对应的四种模式 * MT-发送START, 发送SLA+W * MR-发送START, 发送SLA+R * ST-等待SLA+R * SR-等待SLA+W */inttwiOpen( TwiAddr addr, TwiMode m ){	/*Check Parameter */	if( m == TwiModeMT || m == TwiModeMR )	{		TWCR = _BV(TWIE) | _BV(TWINT)|_BV(TWSTA)|_BV(TWEN); //发送START		twiWait();		if( TW_STATUS != 0x08 && TW_STATUS != 0x10 ){  //START|REP_START没发出去			return TwiErrStart;		}		TWDR = (addr << 1) | (m & TWI_TR_MASK);          //发送SLA+W或R( SLA<<1 + 0(或1) )		TWCR = _BV(TWIE) | _BV(TWINT) | _BV(TWEN);		twiWait();		if( TW_STATUS == TW_MT_SLA_ACK ){                //没有SLA+ACK,状态不对			mode = TwiModeMT;			return TwiModeMT;		}		else if( TW_STATUS == TW_MR_SLA_ACK ){			mode = TwiModeMR;			return TwiModeMR;		}		else{			return TwiErrSla;		}	}	else if( m == TwiModeST || m == TwiModeSR )	{		TWAR = (addr << 1) | _BV(TWGCE);       //设置自己的地址,默认也接收广播		TWCR = _BV(TWIE) | _BV(TWEA) | _BV(TWEN);          //TWEA使能地址匹配,TWEN使能TW模块		twiWait();		if( TW_STATUS == TW_SR_SLA_ACK ){			mode = TwiModeSR;			return TwiModeSR;		}		else if( TW_STATUS == TW_ST_SLA_ACK ){			mode = TwiModeST;			return TwiModeST;		}		else{			return TwiErrMatch;		}	}	else{		return TwiErrOther;	}}/* 主模式写入,遇到NACK认为文件结束,写入最后一个字节,返回不包括最后数据的实际写入字节数 */inline inttwiMasterWrite( const void *data, size_t sz){	int i = 0;	const UINT8 *src = data;	for( i = 0; i < sz; ++i )	{		if( TW_STATUS == TW_MT_DATA_ACK || TW_STATUS == TW_MT_SLA_ACK ){			TWDR = src[i];			TWCR = _BV(TWIE) | _BV(TWINT) | _BV(TWEN);			twiWait();		}		else if( TW_STATUS == TW_MT_DATA_NACK ){			TWDR = src[i];			TWCR = _BV(TWIE) | _BV(TWINT) | _BV(TWEN);			twiWait();			return i;		}		else{			return i;		}	}	return i;}/* 遇到了NACK后认为文件结束,返回实际写入数 */inline inttwiSlaveWrite( const void *data, size_t sz ){	int i;	const UINT8 *src = data;	for( i = 0; i < sz; ++i ){		switch(TW_STATUS){		case TW_ST_SLA_ACK:		case TW_ST_DATA_ACK:			TWDR = src[i];			TWCR = _BV(TWIE) | _BV(TWEN) | _BV(TWEA) | _BV(TWINT);			twiWait();			break;		case TW_ST_DATA_NACK:/*主机希望停止传输*/			return i;			break;	    /*case TW_ST_LAST_DATA: 是从机发送者主动停止了传输,此行为在close中执行 */		default:			break;		}	}	return i;}/* Twi发送数据,-1代表Twi没有正确的打开 */inttwiWrite( const void *data, size_t sz ){	if( mode == TwiModeMT){		return twiMasterWrite( data, sz );	}	else if( mode == TwiModeST ){		return twiSlaveWrite( data, sz );	}	else{		return TwiErrOpen;	}}/* 主模式输入,SLA_NACK表示单字节传输,并不中止 * 在遇到DATA_NACK时(从机希望中止传输),读入最后数据,返回不包括最后数据的数据数 * 应用应该判断这种情况,作出反应(如 twiClose) */inline inttwiMasterRead( void *buf, size_t sz ){	UINT8 *dest = buf;	int i;	for( i = 0; i < sz; ++i ){		switch( TW_STATUS )		{		case TW_MR_SLA_NACK:		case TW_MR_SLA_ACK:			--i;			TWCR = _BV(TWIE) | _BV(TWEN) | _BV(TWEA) | _BV(TWINT);			twiWait();			break;		case TW_MR_DATA_ACK:			dest[i] = TWDR;			TWCR = _BV(TWIE) | _BV(TWEN) | _BV(TWEA) | _BV(TWINT);			twiWait();			break;		case TW_MR_DATA_NACK:			dest[i] = TWDR;			return i;			break;		default:			return i;			break;		}	}	return i;}/* 从模式读入, * read应该在open之后调用 * 遇到SLA+W,则重新读入这一字节数据 * 如果遇到主机中止传输的情况,应该返回实际读入数,应用应该判断作出反应(如twiClose) */inline inttwiSlaveRead( void *buf, size_t sz){	int i;	UINT8 *dest = buf;	for( i = 0; i < sz; ++i ){		if( TW_STATUS == TW_SR_DATA_ACK ){			dest[ i ] = TWDR;			TWCR = _BV(TWIE) | _BV(TWINT) | _BV(TWEA) | _BV(TWEN);			twiWait();		}		else if( TW_STATUS == TW_SR_SLA_ACK ){			-- i;			TWCR = _BV(TWIE) | _BV(TWINT) | _BV(TWEA) | _BV(TWEN);			twiWait();			continue;		}		else if( TW_STATUS == TW_SR_STOP ){			return i;		}		else{			break;		}		/*case TW_ST_DATA_NACK: 是从机接收者希望停止传输,此行为在close中执行 */	}	return i;}/* twi读入 */inttwiRead( void *buf, size_t sz ){	if( mode == TwiModeMR){		return twiMasterRead( buf, sz );	}	else if( mode == TwiModeSR ){		return twiSlaveRead( buf, sz );	}	else{		return TwiErrOpen;	}}inttwiClose( void ){	TwiMode md = mode;	mode = TwiModeStop;	if( md == TwiModeMR ){ //MR模式时要先发一个NACK使从机发送者停下来		TWCR = _BV(TWIE) | _BV(TWINT) | _BV(TWEN);		twiWait();	}	if( md == TwiModeMT || md == TwiModeMR )	{		TWCR = _BV(TWIE) | _BV(TWINT)|_BV(TWSTO)|_BV(TWEN);		twiWait();	}	else if( md == TwiModeSR || md == TwiModeSR ) //发送一个NACK	{		TWCR = _BV(TWIE) | _BV(TWEN) | _BV(TWINT);		twiWait();	}	return 0;}inline void twiWait( void ){	AvrXWaitSemaphore( &twiSignal );	while( bit_is_clear(TWCR, TWINT) );}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -