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

📄 twi.c

📁 ICCavr的硬件读写IIC有完整的应用说明
💻 C
字号:
#include <iom8v.h>
#include <macros.h>
#include"twi.h"

static unsigned char ORGDATA[16];
struct str_TWI         //TWI数据结构
{
    volatile unsigned char STATUS;    //TWI_操作状态
    unsigned char SLA;      //从设备的器件地址
    unsigned int ADDR;      //从设备的数据地址
    unsigned char *pBUF;      //数据缓冲区指针
    unsigned int DATALEN;     //数据长度
    unsigned char STATE;      //TWI读写操作步骤
    unsigned char FAILCNT;     //失败重试次数
};
struct str_TWI strTWI;       //TWI的数据结构变量
//---------------------Function---------------------------------------------
void twi_init();
unsigned char TWI_RW(unsigned char sla,unsigned int addr,unsigned char *ptr,unsigned int len);

//--------------------------------------------------------------------------

void twi_init(void)
{

 //    unsigned char i;
    //上电默认DDRx=0x00,PORTx=0x00 输入,无上拉电阻
 //不用的管脚使能内部上拉电阻。
    PORTB=0xFF;
    PORTC=0xFF;         //SCL,SDA使能了内部的10K上拉电阻
    PORTD=0xFF;
    
    //TWI初始化
    TWSR=0x00;         //预分频=0^4=1
    TWBR=TWBR_SET;
    TWAR=0x00;         //主机模式,该地址无效
    TWCR=0x00;         //关闭TWI模块
	
	         //使能全局中断
    strTWI.STATUS=TW_OK;
}


unsigned char TWI_RW(unsigned char sla,unsigned int addr,unsigned char *ptr,unsigned int len)
{
    if (strTWI.STATUS==TW_BUSY)
    {//TWI忙,不能进行操作
        return OP_BUSY;
    }
    strTWI.STATUS=TW_BUSY;         //考虑了24C04/08的EEPROM地址高位放在SLA里面
    strTWI.SLA=sla;
    strTWI.ADDR=addr;
    strTWI.pBUF=ptr;
	//UDR=*ptr;
    strTWI.DATALEN=len;
    strTWI.STATE=ST_START;
    strTWI.FAILCNT=0;
    TWCR=(1<<TWSTA)|TW_ACT;      //启动start信号
    return OP_RUN;
}
#pragma interrupt_handler twi_isr:18
void twi_isr(void)
{

 //twi event
//}
//void SIGNAL(SIG_2WIRE_SERIAL)
//{//IIC中断
    unsigned char action,state,status;
    action=strTWI.SLA&TW_READ;     //取操作模式
    state=strTWI.STATE;
    status=TWSR&0xF8;       //屏蔽预分频位
    if ((status>=0x60)||(status==0x00))
    {//总线错误或从机模式引发的中断,不予处理
        return;
    }
//-----------------------------------------------------------------------------
 switch(state)
    {
    case ST_START: //START状态检查
        if(status==TW_START)
        {//发送start信号成功
            TWDR=strTWI.SLA&0xFE;    //发送器件地址写SLAW
            TWCR=TW_ACT;             //触发下一步动作,同时清start发送标志
        }
        else
        {//发送start信号出错
            state=ST_FAIL;
        }
        break;
    case ST_SLAW: //SLAW状态检查
        if(status==TW_MT_SLA_ACK)
        {//发送器件地址成功
            TWDR=strTWI.ADDR/256;     //发送eeprom地址
            TWCR=TW_ACT;             //触发下一步动作
        }
        else
        {//发送器件地址出错
            state=ST_FAIL;
        }
        break;
    case ST_ADDR:
       if(status==TW_MT_DATA_ACK)
       {
         TWDR=strTWI.ADDR%256;     //发送eeprom地址
            TWCR=TW_ACT;
        }
        else
        {//发送器件地址出错
            state=ST_FAIL;
        }
       break;

    case ST_WADDR: //ADDR状态检查
        if(status==TW_MT_DATA_ACK)
        {//发送eeprom地址成功
            if (action==TW_READ)
            {//读操作模式
                TWCR=(1<<TWSTA)|TW_ACT;   //发送restart信号,下一步将跳到RESTART分支
            }
            else
            {//写操作模式
                TWDR=*strTWI.pBUF++;          //写第一个字节
                strTWI.DATALEN--;
                state=ST_WDATA-1;    //下一步将跳到WDATA分支
                TWCR=TW_ACT;            //触发下一步动作
            }
        }
        else
        {//发送eeprom地址出错
            state=ST_FAIL;
        }
        break;
    case ST_RESTART: //RESTART状态检查,只有读操作模式才能跳到这里
        if(status==TW_REP_START)
        {//发送restart信号成功
            TWDR=strTWI.SLA;     //发器件地址读SLAR
            TWCR=TW_ACT;             //触发下一步动作,同时清start发送标志
        }
        else
        {//重发start信号出错
            state=ST_FAIL;
        }
        break;
    case ST_SLAR: //SLAR状态检查,只有读操作模式才能跳到这里
        if(status==TW_MR_SLA_ACK)
        {//发送器件地址成功
            if (strTWI.DATALEN--)
            {//多个数据
                TWCR=(1<<TWEA)|TW_ACT;   //设定ACK,触发下一步动作
            }
            else
            {//只有一个数据
                TWCR=TW_ACT;     //设定NAK,触发下一步动作
            }
        }
        else
        {//发送器件地址出错
            state=ST_FAIL;
        }
        break;
    case ST_RDATA: //读取数据状态检查,只有读操作模式才能跳到这里
        state--;        //循环,直到读完指定长度数据
        if(status==TW_MR_DATA_ACK)
        {//读取数据成功,但不是最后一个数据
		  //  UDR=TWDR;
            *strTWI.pBUF=TWDR;	//*strTWI.pBUF++=TWDR;				
			strTWI.pBUF++;		
            if (strTWI.DATALEN--)
            {//还有多个数据
                TWCR=(1<<TWEA)|TW_ACT;   //设定ACK,触发下一步动作
            }
            else
            {//准备读最后一个数据
                TWCR=TW_ACT;     //设定NAK,触发下一步动作
            }
			
        }
        else if(status==TW_MR_DATA_NACK)
        {//已经读完最后一个数据
            *strTWI.pBUF=TWDR;//*strTWI.pBUF++=TWDR;			
            TWCR=(1<<TWSTO)|TW_ACT;    //发送停止信号,不会再产生中断了
            strTWI.STATUS=TW_OK;
        }
        else
        {//读取数据出错
		
            state=ST_FAIL;
        }
        break;
    case ST_WDATA: //写数据状态检查,只有写操作模式才能跳到这里
        state--;        //循环,直到写完指定长度数据
        if(status==TW_MT_DATA_ACK)
        {//写数据成功
            if (strTWI.DATALEN)
            {//还要写
                TWDR=*strTWI.pBUF++;
				
                strTWI.DATALEN--;
                TWCR=TW_ACT;            //触发下一步动作
            }
            else
            {//写够了
                TWCR=(1<<TWSTO)|TW_ACT;   //发送停止信号,不会再产生中断了
                strTWI.STATUS=TW_OK;
                //启动写命令后需要10ms(最大)的编程时间才能真正的把数据记录下来
                //编程期间器件不响应任何命令
            }
        }
        else
        {//写数据失败
            state=ST_FAIL;
        }
        break;
    default:
        //错误状态
        state=ST_FAIL;
        break;
    }
//------------------------------------------------------------------------------
    if (state==ST_FAIL)
    {//错误处理
        strTWI.FAILCNT++;
        if (strTWI.FAILCNT<FAIL_MAX)
        {//重试次数未超出最大值,
            TWCR=(1<<TWSTA)|TW_ACT;    //发生错误,启动start信号
        }
        else
        {//否则停止
            TWCR=(1<<TWSTO)|TW_ACT;    //发送停止信号,不会再产生中断了
            strTWI.STATUS=TW_FAIL;
        }
    }
    state++;
    strTWI.STATE=state;       //保存状态
}
/*
void uart0_init(void)
{
 UCSRB=0x00; 
 UCSRA = 0x00;
 UBRRL=(fosc/16/(baud+1))%256;
 UBRRH=(fosc/16/(baud+1))/256;//设置UBRR
 UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
// UCSRB=(1<<RXEN)|(1<<RXCIE)|(1<<TXEN)|(1<<TXCIE);
UCSRB=(1<<TXEN);
}
void main(void)
{

twi_init();
uart0_init();

  //  TWI_RW(SLA_24CXX+(ADDR_24C64<<1)+,0x10,&ORGDATA[0],16);
  //TWI_RW(SLA_24CXX+(ADDR_24C64<<1)+TW_WRITE,0x00,&cc[0],16);

SEI();
TWI_RW(SLA_24CXX+(ADDR_24C64<<1)+TW_READ,0x00,cc,16);	
    //从0x10地址开始写入8个字节数据
    while(strTWI.STATUS==TW_BUSY);    //等待操作完成
    if (strTWI.STATUS==TW_FAIL)
    {
	 UDR=0x06;	
        //操作失败  
	}
  //  _delay_ms(10);        //延时等待编程完成

UDR=cc[8];
  
	
 while(1);
}
*/
 

⌨️ 快捷键说明

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