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

📄 twi._c

📁 mp3代码 要用的干净下啊 希望用东西共享啊
💻 _C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************************************************
**				          			       TWI 驱动程序
**                                  (c) Copyright 2006-2008, limaokui
**                                           All Rights Reserved
**
**                                             V1.0.0
**
**
**--------------文件信息--------------------------------------------------------------------------------
**文   件   名:TWI.h
**创   建   人: 李茂奎
**最后修改日期:  2006年8月29日
**描        述:  TWI驱动程序
**
**--------------历史版本信息----------------------------------------------------------------------------
** 创建人: 李茂奎
** 版  本: V1.00
** 日 期: 2006年8月29日
** 描 述: 原始版本
**
**------------------------------------------------------------------------------------------------------
** 修改人: 李茂奎
** 版  本:
** 日 期:
** 描 述: 
**
**--------------当前版本修订------------------------------------------------------------------------------
** 修改人:    李茂奎																					  
** 日 期:	 2006年9月1日
** 描 述:   
**
**------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
/*
说明:1、本驱动程序已经实现了TWI中断通讯的四种模式:MT、MR、ST、SR。
     2、MT方式调用Twi_MasterSend()函数,用到了Twi_SendBuffer队列,
	 	最大单次发送255Btye,理论上两次发送间隔5MS以上。
	 3、MR方式调用Twi_MasterRecive()函数,用到了Twi_ReceiveBuffer队列,
	 	最大单次发送255Btye,理论上两次发送间隔5MS以上。
	 4、SR方式用户不必关心何时中断,在中断结束后,调用Twi_SlaveReceiveService()函数,
	    此函数将接收到的数据传给上层缓冲区Twi_LocalBuffer,用到了Twi_ReceiveBuffer、Twi_LocalBuffer队列,
		最大单次发送255Btye。上层程序仅需检测Twi_LocalBuffer中的status即可,即若status值
		TWI_DATA_READY,就可以读取数据,读完后设置LocalBuffer的Status为TWI_DATA_FREE。
	 5、ST方式用户不必关心何时中断,在中断结束后,调用Twi_TransmintReceiveService()函数S玫搅薚wi_ReceiveBuffer、Twi_LocalBuffer队列,
	    如果想使能从机发送则可将要发数据传入LocalBuffer中并设置Status为TWI_DATA_SEND,在写
		LocalBuffer之前,应检测STATUS是否为Status为TWI_DATA_FREE。
	 6、非中断模式的接收发送没有经过验证。使用时请注意。
	 7、使用时首先调用TwiInit()进行初始化,(循环队列的长度可以自己修改对应的数组和结构中的queuesize),
	    然后打开中断即可。对于不同的单片机,此驱动中通过定义CPU_TYPE实现切换。对应的定义在config中。
*/
#include "config.h"
// Twi标准波特率: 
// 低速 100KHz  
// 高速 400KHz  

// Twi_ 状态和地址变量 
static volatile eTwi_StateType Twi_State; // 用于独占TWI的资源分配的信号量机制
static volatile uint8 Twi_DeviceAddrRW; 
// 发送缓冲区 
uint8 Twi_SendData[TWI_SEND_DATA_BUFFER_SIZE]; 
CirQueue Twi_SendBuffer={0,0,0,Twi_SendData,TWI_SEND_DATA_BUFFER_SIZE,QUEUE_OK,TWI_DATA_FREE,0};  
// 接收缓冲区 
uint8 Twi_ReceiveData[TWI_RECEIVE_DATA_BUFFER_SIZE]; 
CirQueue Twi_ReceiveBuffer={0,0,0,(uint8 *)Twi_ReceiveData,TWI_RECEIVE_DATA_BUFFER_SIZE,QUEUE_OK,TWI_DATA_FREE,0};  
//本地缓冲区,当为从机时,与TWI接口
static uint8 LocalBuffer[TWI_LOCAL_DATA_BUFFER_SIZE];
CirQueue Twi_LocalBuffer={0,0,0,LocalBuffer,TWI_LOCAL_DATA_BUFFER_SIZE,QUEUE_OK,TWI_DATA_FREE,0};  
//错误代码
static volatile uint8 TwiErrorCode;

// 指向接收处理函数的指针,当本机被选中从接收时调用函数:Twi_SlaveReceive 
static void (*Twi_SlaveReceive)(uint8 receiveDataLength, uint8* recieveData); 
// 指向发送处理函数的指针,当本机被选中从发送时调用函数:ITwi_SlaveTransmit  
static uint8 (*Twi_SlaveTransmit)(uint8 transmitDataLengthMax, uint8* transmitData); 



/*************************************************************************************
**延时公式
**  i*500-100 US  (8>i>2)
**  i*500         (255>i>8)
** i=1精确延时100us
** i=2 精确延时660US
** i=6 精确延时2.9ms
** i=10 精确延时5ms
** i=20        10ms
** i=100       50ms
** i=200       100ms
** i=255       128ms
**************************************************************************************/
void Delay(uint8 n)
{
	uint8 i;
	for(i=36;n!=0;n--)	
	{
	while(--i);
	WDR(); //喂狗;
	}
}
/*********************************************************************************************************
** 函数名称:Twi_SetBitrate
** 功能描述:设置TWI总线的速率
** 输 入:  bitrateKHZ : 总线速率
** 输  出:             
** 全局变量: 
** 调用模块: 无
** 说明:
** 注意:    
** 日 期:   2006年8月29日
********************************************************************************************************/
void Twi_SetBitrate(uint16 bitrateKHz){ 
   uint8 bitrate_div;
   WDR(); //喂狗; 
   // SCL freq = F_CPU/(16+2*TWBR)) 
   #ifdef TWPS0 
      // 对于用速率分频的AVR (mega128) 
      // SCL freq = F_CPU/(16+2*TWBR*4^TWPS) 
      // set TWPS to zero 
      TWSR&=~(1<<TWPS0); 
      TWSR&=~(1<<TWPS1); 
   #endif 
   // 计算分频 
   bitrate_div = ((F_CPU/1000)/bitrateKHz); 
   if(bitrate_div >= 16) 
      bitrate_div = (bitrate_div-16)/2; 
          TWBR = bitrate_div; 
} 
/*********************************************************************************************************
** 函数名称:Twi_MasterSend
** 功能描述:主发送
** 输 入:  deviceAddr:从机地址
**          length:数据长度
**          * data:发送缓冲区指针
**
** 输  出: 发送的字节数         
** 全局变量: 
** 调用模块: 
** 说明:
** 注意:    
** 日 期:   2006年8月29日
********************************************************************************************************/
uint8 Twi_MasterSend(uint8 deviceAddr, uint8 length, uint8* data) 
{ 
   uint8 i,result=0;
   WDR(); //喂狗; 
   // 等待总线准备完成 
   while(Twi_State);                          //此处为独占TWI的信号量机制
   // 设置状态 
   Twi_State = TWI_MASTER_TX; 
   // 准备数据 
   Twi_DeviceAddrRW = (deviceAddr & 0xFE);   // RW 为0: 写操作
   if(Twi_SendBuffer.status==TWI_DATA_FREE)  
         {
		 InitQueue(&Twi_SendBuffer);            //清空上次发送的信息
         Twi_SendBuffer.status=TWI_DATA_SEND;
		 }
   for(i=0; (i<length)&&(Twi_SendBuffer.errorcode!=QUEUE_OVERFLOW); i++) 
   EnQueue(&Twi_SendBuffer,*data++);
   result=i;

   // 发送开始条件 
   Twi_Start();
   WDR(); //喂狗;
   while(Twi_State);
   WDR(); //喂狗;
   i=0;
   while(((TwiErrorCode==TW_MT_SLA_NACK)||(TwiErrorCode==TW_MT_ARB_LOST)||(TwiErrorCode==TW_MT_DATA_NACK))&&i<TWI_FAIL_MAX)  //器件不响应或总线仲裁失败
         {
		 i++;
		 if((TwiErrorCode==TW_MT_DATA_NACK)&&(Twi_SendBuffer.count==0))
	         {
			 break;
			 }
		 Delay(255);
		 Twi_State = TWI_MASTER_TX; 
		 Twi_Start();
		 WDR(); //喂狗;
		 while(Twi_State);
		 WDR(); //喂狗;
		 }
   Twi_SendBuffer.status=TWI_DATA_FREE;
   if(i>=TWI_FAIL_MAX) 
     {
	 return (FALSE);
	 }
   else
     {
	 return (result-Twi_SendBuffer.count);
	 }
} 
/*********************************************************************************************************
** 函数名称:Twi_MasterReceive
** 功能描述:主模式接收
** 输 入:  deviceAddr:从机地址
**          length:数据长度
**          * data  缓冲区指针
**
** 输  出:  返回接收到的字节数           
** 全局变量: 
** 调用模块: 
** 说明:
** 注意:    
** 日 期:   2006年8月29日
********************************************************************************************************/

uint8 Twi_MasterReceive(uint8 deviceAddr, uint8 length, uint8* data) 
{ 
   uint8 i,result; 
   WDR(); //喂狗;
   // 等待总线准备完成 
   while(Twi_State); 
   // 设置状态 
   Twi_State = TWI_MASTER_RX; 
   // 保存数据 
   Twi_DeviceAddrRW = (deviceAddr|0x01);   // RW 为1 : 读操作
   
   if(Twi_ReceiveBuffer.status==TWI_DATA_FREE)  
         {
		 InitQueue(&Twi_ReceiveBuffer);            //清空上次发送的信息
         Twi_ReceiveBuffer.status=TWI_DATA_RECEIVE;
		 Twi_ReceiveBuffer.memo=length; 
		 }
 
   // 发送开始条件 
   Twi_Start(); 
   WDR(); //喂狗;
   //等待数据准备好 
   while(Twi_State);                           //注意有可能引起死循环
   WDR(); //喂狗;
   i=0;
   while(((TwiErrorCode==TW_MR_SLA_NACK)||(TwiErrorCode==TW_MR_ARB_LOST)||(TwiErrorCode==TW_MR_DATA_NACK))&&i<TWI_FAIL_MAX)  //器件不响应或总线仲裁失败
         {
		 i++;
		 if((TwiErrorCode==TW_MR_DATA_NACK)&&(Twi_ReceiveBuffer.count>=length))
	         {
			 break;
			 }
		 //Twi_Stop();
		 Delay(255);
		 Twi_State = TWI_MASTER_RX; 
		 Twi_Start();
		 WDR(); //喂狗;
		 while(Twi_State);
		 WDR(); //喂狗;
		 }
	   // 取数据 
   for(result=0; (result<length)&&(Twi_ReceiveBuffer.count>0); result++) 
      *data++ = DeQueue(&Twi_ReceiveBuffer);
   Twi_ReceiveBuffer.status=TWI_DATA_FREE;
   if(i>=TWI_FAIL_MAX) 
     {
	 return (FALSE);
	 }
   else
     {
	 return (result);    //返回接收到的字节数;
	 }
} 
/*********************************************************************************************************
** 函数名称:Twi_MasterSendNI
** 功能描述:主模式非中断发送
** 输 入:  deviceAddr:从机地址
**          length:数据长度
**          * data  缓冲区指针
** 输  出:             
** 全局变量: 
** 调用模块: 
** 说明:
** 注意:    
** 日 期:   2006年8月29日
********************************************************************************************************/
uint8 Twi_MasterSendNI(uint8 deviceAddr, uint8 length, uint8* data) 
{ 
   uint8 retval = TWI_OK; 
   WDR(); //喂狗;
   // 关Twi_中断 
   TWCR&=~(1<<TWIE); 
   WDR(); //喂狗;
   // 发送开始条件 
   Twi_Start(); 
   WDR(); //喂狗;
   Twi_WaitForComplete(); 
   // 发送器件写地址 
   Twi_SendByte( deviceAddr & 0xFE ); 
   Twi_WaitForComplete(); 
   // 检查器件是否可用 
   if( TWSR == TW_MT_SLA_ACK) 
   { 
      // 发送数据 
      while(length) 
      { 
         Twi_SendByte( *data++ ); 
         Twi_WaitForComplete(); 
         length--; 
		 WDR(); //喂狗;
      } 
   } 
   else 
   { 
      // 如未回应器件地址,停止发送,返回错误 
         retval = TWI_ERROR_NODEV; 
   } 

   // 发送停止条件,保持TWEA以便从接收 
   Twi_Stop(); 
   while( !(TWCR&(1<<TWSTO)) ); 
   // 开Twi_中断 
   TWCR|=(1<<TWIE); 
   return retval; 
} 
/*********************************************************************************************************
** 函数名称:主模式非中断接收
** 功能描述:
** 输 入:  deviceAddr:从机地址
**          length:数据长度
**          * data  缓冲区指针
** 输  出:             
** 全局变量: 
** 调用模块: 
** 说明:
** 注意:    
** 日 期:   2006年8月29日
********************************************************************************************************/

uint8 Twi_MasterReceiveNI(uint8 deviceAddr, uint8 length, uint8 *data) 
{ 
   uint8 retval = TWI_OK; 

⌨️ 快捷键说明

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