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

📄 twi.c

📁 LCD图形显示_菜单管理程序
💻 C
字号:
#include "includes.h"

/*-----------------------------------变量定义---------------------------------*/
/* 发送缓冲区 */ 
INT8U TWI_SendData[TWI_SEND_DATA_BUFFER_SIZE]; 
INT8U TWI_SendDataIndex; 
INT8U TWI_SendDataLength; 
/* 接收缓冲区 */
INT8U TWI_ReceiveData[TWI_RECEIVE_DATA_BUFFER_SIZE]; 
INT8U TWI_ReceiveDataIndex; 
INT8U TWI_ReceiveDataLength; 
/*----------------------------------TWI初始化---------------------------------*/
void TWI_Init(void) 
{ 
	/*设置总线上拉 */
   	#ifndef __iom128_h  
   	//#ifndef __iom64v_h
   		PORTD |= 0x03;   														// TWI SCL SDA on ATmega128,64 															
  	#else  
  		PORTC|= 0x03;   														// TWI SCL SDA on ATmega163,323,16,32,等 
  	#endif 
   	/*设置 TWI 波特率为 100KHz; TWI标准波特率: 低速 100KHz ;高速 400KHz */ 
   	TWI_SetBitrate(100); 
   	/*TWI总线使能*/ 
   	TWCR|=1<<TWEN; 
   	/*开TWI中断和回应*/ 
    TWCR|=1<<TWIE; 
    TWCR|=1<<TWEA;  
} 
/*---------------------------------设置总线速率-------------------------------*/
void TWI_SetBitrate(INT8U       bitrateKHz) 
{ 
	INT8U bitrate_div; 
   	// SCL freq = Crystal/(16+2*TWBR)) 
   	#ifdef TWPS0 
    /* 对于用速率分频的AVR (mega128) 
       SCL freq = Crystal/(16+2*TWBR*4^TWPS) 
       set TWPS to zero 
		TWSR&=~(1<<TWPS0); 
      	TWSR&=~(1<<TWPS1); */
	#endif 
   	/*计算分频*/ 
   		bitrate_div = ((Crystal/1000l)/bitrateKHz); 
   		if(bitrate_div >= 16) 
   		{
      		bitrate_div = (bitrate_div-16)/2; 
    	}
     	TWBR = bitrate_div; 
} 
/*---------------------------------TWI发送开始--------------------------------*/
void TWI_SendStart(void) 
{ 
    
  	TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWSTA); 
} 

/*-----------------------发送停止条件,保持TWEA以便从接收---------------------*/
void TWI_SendStop(void) 
{ 
	TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO); 
} 
/*------------------------------等待TWI 总线操作完成--------------------------*/
void TWI_WaitForComplete(void) 
{ 
   	while( !(TWCR&(1<<TWINT)) )WDR(); 
} 
/*-------------------------------返回接收到的数据-----------------------------*/
INT8U TWI_GetReceivedByte(void) 
{ 
   	return( TWDR ); 
} 
/*--------------------------------TWI单字节发送-------------------------------*/
void TWI_SendByte(INT8U data) 
{ 
	TWDR=data;  																// 装载数据到 TWDR 
	TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT);  										// 发送开始
} 
/*--------------------------------TWI单字节接收-------------------------------*/
void TWI_ReceiveByte(INT8U ackFlag) 
{ 
 	if( ackFlag ) 																// 开始通过 TWI 接收
   	{ 
      
		TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWEA); 							// ackFlag = TRUE: 数据接收后回应ACK  
   	} 
   	else 
   	{ 
		TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT); 									// ackFlag = FALSE: 数据接收后无回应
   	} 
} 

/*-----------------------TWI主机发送,用于I2C器件读写-------------------------*/
INT8U TWI_MasterSendNI(INT8U deviceAddr, INT8U length, INT8U* data) 
{ 
   	INT8U retval = TWI_OK; 
	//CLI();
   	/*关TWI中断*/ 
   	TWCR&=~(1<<TWIE); 

   	/*发送开始条件*/ 
   	TWI_SendStart(); 
   	TWI_WaitForComplete(); 

   	/*发送器件写地址*/ 
   	TWI_SendByte( deviceAddr & 0xFE ); 
   	TWI_WaitForComplete(); 

   	/*检查器件是否可用*/ 
   	if( TWSR == TW_MT_SLA_ACK) 
   	{ 
      	/*发送数据*/ 
      	while(length) 
      	{ 
			WDR();
         	TWI_SendByte( *data++ ); 
         	TWI_WaitForComplete(); 
         	length--; 
      	} 
   	} 
   	else 
   	{ 
      	/*如未回应器件地址,停止发送,返回错误*/  
      	retval = TWI_ERROR_NODEV; 
   	} 
   	/*发送停止条件,保持TWEA以便从接收*/ 
   	TWI_SendStop(); 
   	while( !(TWCR&(1<<TWSTO)) )WDR(); 
   	/*开TWI中断*/
   	TWCR|=(1<<TWIE); 
	//SEI();
   	return retval; 
} 

/*-----------------------TWI主机接收,用于I2C器件读写-------------------------*/
INT8U TWI_MasterReceiveNI(INT8U deviceAddr, INT8U length, INT8U *data) 
{ 
   	INT8U retval = TWI_OK; 
	//CLI();
   	/*关TWI中断*/ 
    TWCR&=~(1<<TWIE); 
   	/*发送开始条件*/ 
   	TWI_SendStart(); 
   	TWI_WaitForComplete(); 
   	/*发送器件读地址*/ 
   	TWI_SendByte(deviceAddr| 0x01  ); 
   	TWI_WaitForComplete(); 
   	/*检查器件是否可用*/ 
   	if( TWSR == TW_MR_SLA_ACK) 
   	{ 
      	/*接收数据并回应*/ 
      	while(length > 1) 
      	{ 
			WDR();
         	TWI_ReceiveByte(TRUE); 
         	TWI_WaitForComplete(); 
         	*data++ = TWI_GetReceivedByte(); 
         	length--; 
      	} 
      	/*接收数据无回应 (末位信号)*/ 
      	TWI_ReceiveByte(FALSE); 
      	TWI_WaitForComplete(); 
      	*data++ = TWI_GetReceivedByte(); 
   	} 
   	else 
   	{ 
      	/*如未回应器件地址,停止发送,返回错误*/ 
      	retval = TWI_ERROR_NODEV; 
   	} 
   	/*发送停止条件,保持TWEA以便从接收*/ 
   	TWI_SendStop(); 
   	/*开TWI中断*/ 
   	TWCR|=TWIE; 
	//SEI();
   	return retval; 
}  
/*---------------------------------TWI中断服务程序----------------------------*/
void TWI_ISR(void) 
{ 
   	INT8U status;
   	
   	//CLI();
    /*读状态位*/
   	status = TWSR & TWSR_STATUS_MASK; 
   	switch(status) 
   	{ 
   		/*-------------------主方式-----------------*/ 
   		case TW_START:                  										// 0x08: START 已发送 
   		case TW_REP_START:              							 			// 0x10: 重复START 已发送 
      	break; 
   		/*主发送,主接收状态码*/ 
   		case TW_MT_SLA_ACK:               										// 0x18: SLA+W 已发送;接收到ACK 
   		case TW_MT_DATA_ACK:            										// 0x28: 数据已发送;接收到ACK 
      		if(TWI_SendDataIndex < TWI_SendDataLength) 
      		{ 	
         		TWI_SendByte( TWI_SendData[TWI_SendDataIndex++] ); 				// 发送数据 
      		} 
      		else 
      		{ 
         		TWI_SendStop(); 												// 发送停止条件,保持TWEA以便从接收 
      		} 
      	break; 
   		case TW_MR_DATA_NACK:            										// 0x58: 接收到数据;NOT ACK 已返回 
      		TWI_ReceiveData[TWI_ReceiveDataIndex++] = TWDR; 					// 保存最终数据
      	/*继续发送条件*/ 
   		case TW_MR_SLA_NACK:            										// 0x48: SLA+R 已发送,接收到NOT ACK 
   		case TW_MT_SLA_NACK:            										// 0x20: SLA+W 已发送,接收到NOT ACK 
   		case TW_MT_DATA_NACK:            										// 0x30: 数据已发送,接收到NOT ACK 
      		TWI_SendStop(); 													// 发送停止条件,保持TWEA以便从接收 
      	break; 
   		case TW_MT_ARB_LOST:            										// 0x38: SLA+W 或数据的仲裁失败 
    		TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT); 								// 释放总线 
      	break; 
   		case TW_MR_DATA_ACK:            										// 0x50: 接收到数据,ACK 已返回  
      		TWI_ReceiveData[TWI_ReceiveDataIndex++] = TWDR; 					// 保存接收到的数据位 
      	/*检查是否接收完*/ 
   		case TW_MR_SLA_ACK:               										// 0x40: SLA+R 已发送,接收到ACK 
      		if(TWI_ReceiveDataIndex < (TWI_ReceiveDataLength-1)) 
      		{
         		TWI_ReceiveByte(TRUE);										 	// 数据位将接收 , 回复 ACK (传送更多字节) 
			}
      		else 
      		{
                TWI_ReceiveByte(FALSE); 										// 数据位将接收 , 回复 NACK (传送最后字节) 
			}
      	break; 

   		case TW_NO_INFO:                 										// 0xF8: 没有相关的状态信息;TWINT = “0” 
      		;																	// 无操作 
      	break; 
   		case TW_BUS_ERROR:              										// 0x00: 由于非法的START 或STOP 引起的总线错误 
      		TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWSTO)|(1<<TWEA);  			// 内部硬件复位,释放总线 
      	break; 
   	} 
   	//SEI();
}
/*------------------------------------------------------------------------------
                                        0ooo
						      ooo0     (   ) 
                              (   )     ) /
						       \ (     (_/
	    				        \_) 
------------------------------------------------------------------------------*/ 

⌨️ 快捷键说明

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