单片机
返回首页

ATMEGA16通过TWI对24C02进行读写

2016-01-19 来源:eefocus

#ifndef TWI_H
#define TWI_H

//主机模式启动状态码
#define    TWI_START                 0X08
#define    TWI_RESTART               0X10
//主机发送模式状态码
#define    TWI_MT_SLA_ACK            0X18   //SLA+W 已发送,接收到ACK
#define    TWI_MT_SLA_NACK           0X20   //SLA+W 已发送,接收到NOT ACK
#define    TWI_MT_DATA_ACK           0X28   //数据已发送,接收到ACK
#define    TWI_MT_DATA_NACK          0X30   //数据已发送,接收到NOT ACK
#define    TWI_MT_ARB_LOST           0X38   //SLA+W 或数据的仲裁失败
//主机接收模式状态码
#define    TWI_MR_ARB_LOST           0X38   //SLA+R 或数据的仲裁失败
#define    TWI_MR_SLA_ACK            0X40   //SLA+R 已发送,接收到ACK
#define    TWI_MR_SLA_NACK           0X48   //SLA+R 已发送,接收到NOT ACK
#define    TWI_MR_DATA_ACK           0X50   //数据已接收,接收到ACK
#define    TWI_MR_DATA_NACK          0X58   //数据已接收,接收到NOT ACK
//从机接收模式状态码
#define    TWI_SR_SLA_ACK            0X60   //自己的SLA+W 已经被接收,ACK 已返回
#define    TWI_SR_ARB_LOST_SLA_ACK   0X68   //SLA+R/W 作为主机的仲裁失败;自己的SLA+W 已经被接收,ACK 已返回
#define    TWI_SR_GCALL_ACK          0X70   //接收到广播地址,ACK 已返回
#define    TWI_SR_ARB_LOST_GCALL_ACK 0X78   //SLA+R/W 作为主机的仲裁失败;接收到广播地址ACK 已返回
#define    TWI_SR_DATA_ACK           0X80   //以前以自己的 SLA+W 被寻址;数据已经被接收ACK 已返回
#define    TWI_SR_DATA_NACK          0X88   //以前以自己的 SLA+W 被寻址;数据已经被接收NOT ACK 已返回
#define    TWI_SR_GCALL_DATA_ACK     0X90   //以前以广播方式被寻址;数据已经被接收ACK 已返回
#define    TWI_SR_GCALL_DATA_NACK    0X98   //以前以广播方式被寻址;数据已经被接收NOT ACK 已返回
#define    TWI_SR_STOP               0XA0   //在以从机工作时接收到STOP或重复START
//从机发送模式状态码
#define    TWI_ST_SLA_ACK            0XA8   //自己的SLA+R 已经被接收ACK 已返回
#define    TWI_ST_ARB_LOST_SLA_ACK   0XB0   //SLA+R/W 作为主机的仲裁失败;自己的SLA+R 已经被接收ACK 已返回
#define    TWI_ST_DATA_ACK           0XB8   //TWDR 里数据已经发送,接收到ACK
#define    TWI_ST_DATA_NACK          0XC0   //TWDR 里数据已经发送,接收到NOT ACK
#define    TWI_ST_LAST_DATA          0XC8   //TWDR 的一字节数据已经发送(TWAE = “0”);接收到ACK
//其他状态
#define    TWI_NO_INFO       0xF8   //没有相关的状态信息,TWINT='0'
#define    TWI_BUS_ERROR      0x00   //由于非法的START或STOP引起的总线错误
//TWI使用时的控制位
#define    TWI_Start()            TWCR = (1<  //清零TWINT、清零start状态、使能TWI.发出START 信号
#define    TWI_Wait()             while (!(TWCR & (1<            //等待TWINT 置位, TWINT 置位表示START 信号已发出
#define    TWI_Status             (TWSR & 0xF8)                            //检验TWI 状态寄存器,屏蔽预分频位
#define    TWI_Stop()             TWCR=(1<    //发送STOP 信号
#define    TWI_SendAck()          (TWCR|=(1<                       //使能TWI应答
#define    TWI_SendNoAck()        (TWCR&=~(1<                      //不使能TWI应答
#define    TWI_RcvNckByte()       (TWCR=(1<             //使能TWI不产生应答
#define    TWI_RcvAckByte()       (TWCR=(1<   //使能TWI、产生应答
#define    TWI_Writebyte(twi_d)   {TWDR=(twi_d);TWCR=(1< // 定义TWI运行状态的极性
#define    TWI_ERR                 0
#define    TWI_CRR                 1

#define    TWI_WRITE                 0
#define    TWI_READ                 1
void delay(uint ms)
{
   uint i,j;
   for(i=ms;i>0;i--)
      for(j=1141;j>0;j--);
}

void TWI_Init(void)
{
   TWBR=0X0F;
   TWSR=0;
}

uchar TWIWait(void)
{
   uchar i=100;
   while(!(TWCR&(1<     //等待TWINT置1
   {
      if((--i)==0)
   return TWI_ERR;
   }
   return TWI_CRR;
}

uchar TWIStart(void)
{
   TWI_Start();
   if(TWIWait()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Status!=TWI_START)
      return TWI_ERR;
   return TWI_CRR;  
}

uchar TWIREStart(void)
{
   TWI_Start();
   if(TWIWait()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Status!=TWI_RESTART)
      return TWI_ERR;
   return TWI_CRR; 
}

uchar TWI_Write_WADDR(uchar addr)
{
   TWI_Writebyte(addr);
   if(TWIWait()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Status!=TWI_MT_SLA_ACK)
      return TWI_ERR;
   return TWI_CRR;
}


uchar TWI_Write_RADDR(uchar addr)
{
   TWI_Writebyte(addr);
   if(TWIWait()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Status!=TWI_MR_SLA_ACK)
      return TWI_ERR;
   return TWI_CRR;
}


uchar TWI_SendData(uchar data)
{
   TWI_Writebyte(data);
   if(TWIWait()==TWI_ERR)
      return TWI_ERR; 
   if(TWI_Status!=TWI_MT_DATA_ACK)
      return TWI_ERR;
   return TWI_CRR;
}

uchar TWI_ReciveDATA_ACK(uchar *pdata)
{
   TWI_RcvAckByte();
   if(TWIWait()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Status!=TWI_MR_DATA_ACK)
      return TWI_ERR;
   *pdata=TWDR;
   return TWI_CRR;
}

uchar TWI_ReciveDATA_NACK(uchar *pdata)
{
   TWI_RcvNckByte();
   if(TWIWait()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Status!=TWI_MR_DATA_NACK)
      return TWI_ERR;
   *pdata=TWDR;
   return TWI_CRR;
}

uchar TWI_W_Byte(uchar Maddr,uchar Saddr,uchar data)
{
   if(TWIStart()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Write_WADDR((Maddr&0xfe)|TWI_WRITE)==TWI_ERR)  //保证写入的SLA+W正确
      return TWI_ERR;
   if(TWI_SendData(Saddr)==TWI_ERR)   //器件内寄存器的地址作为一般数据发送
      return TWI_ERR;
   if(TWI_SendData(data)==TWI_ERR)     //发送要写入的数据
      return TWI_ERR;
   TWI_Stop();
   return TWI_CRR;
}

uchar TWI_W_Data(uchar Maddr,uchar Saddr,uchar *pdata,uchar num)
{
   uchar i;
   if(TWIStart()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Write_WADDR((Maddr&0xfe)|TWI_WRITE)==TWI_ERR)   //保证写入的SLA+W正确
      return TWI_ERR;
   if(TWI_SendData(Saddr)==TWI_ERR)                       //器件内寄存器的地址作为一般数据发送
      return TWI_ERR;
   for(i=0;i    {
      if(TWI_SendData(*(pdata++))==TWI_ERR)
         return TWI_ERR;
  
   TWI_Stop();
   return TWI_CRR;
}

uchar TWI_R_Byte(uchar Maddr,uchar Saddr,uchar *pdata)
{
   if(TWIStart()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Write_WADDR((Maddr&0xfe)|TWI_WRITE)==TWI_ERR)    //保证写入的SLA+W正确
      return TWI_ERR;
   if(TWI_SendData(Saddr)==TWI_ERR)                         ////器件内寄存器的地址作为一般数据发送
      return TWI_ERR;
   if(TWIREStart()==TWI_ERR)  //这里的重新发送start很重要,这里我们的主机不想放弃TWI的使用权   参看《深入浅出AVR单片机》289页
      return TWI_ERR;
   if(TWI_Write_RADDR((Maddr&0xfe)|TWI_READ)==TWI_ERR)   //参看《深入浅出AVR单片机》289页
      return TWI_ERR;
   if(TWI_ReciveDATA_NACK(pdata)==TWI_ERR)               //读取数据时,最后1字节的数据读取完成以后发送NAK而不是ACK
      return TWI_ERR;
   TWI_Stop();
   return TWI_CRR;
}

uchar TWI_R_Data(uint Maddr,uchar Saddr,uchar *pdata,uchar num)

   uchar i;
   if(TWIStart()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Write_WADDR((Maddr&0xfe)|TWI_WRITE)==TWI_ERR)
      return TWI_ERR;
   if(TWI_SendData(Saddr)==TWI_ERR)
      return TWI_ERR;
   if(TWIREStart()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Write_RADDR((Maddr&0xfe)|TWI_READ)==TWI_ERR)
      return TWI_ERR;
   for(i=0;i    {
   if(TWI_ReciveDATA_ACK(pdata+i)==TWI_ERR)
      return TWI_ERR;
   }
   if(TWI_ReciveDATA_NACK(pdata+i)==TWI_ERR) //读取数据时,最后1字节的数据读取完成以后发送NAK而不是ACK,这点很重要
      return TWI_ERR;
   TWI_Stop();
   return TWI_CRR;
}

uchar TWI_W_NAddr(uchar addr,uchar data)
{
    if(TWIStart()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Write_WADDR(addr)==TWI_ERR)
      return TWI_ERR;
   if(TWI_SendData(data)==TWI_ERR)
      return TWI_ERR;
   TWI_Stop();
   return TWI_CRR;
}

uchar TWI_R_NAddr(uchar addr,uchar *pdata)
{
    if(TWIStart()==TWI_ERR)
      return TWI_ERR;
   if(TWI_Write_RADDR(addr)==TWI_ERR)
      return TWI_ERR;
   if(TWI_ReciveDATA_NACK(pdata)==TWI_ERR)
      return TWI_ERR;
   TWI_Stop();
   return TWI_CRR;
}
#endif


#include
#include 'IIC.h'
void port_init(void)
{
   DDRB=0XFF;
   PORTB=0XFF;
   TWCR=0X44;
   DDRD=0XFF;
   PORTD=0XFF;
}

 uchar temp1[8]={18,17,16,15,14,13,12,11};
  uchar temp2[8]={0};
  uchar temp3[8]={0,0,0,0,0,0,0,0};
void main(void)
{
   TWI_Init();
   port_init();
   if(TWI_W_Data(0Xa0,0x00,temp1,8)==TWI_ERR)
      PORTD&=~(BIT(PD0));
   delay(5);      //这里的延时很重要,如果不加,读出来的数据很是匪夷所思
   if((TWI_R_Data(0Xa1,0x00,temp2,8))==TWI_ERR)
      PORTD&=~BIT(PD7);
   if(temp2[1]==17)
      PORTB=0X00;
   while(1)
   {
      if(temp2[0]==18)
     {
         PORTB=0XFE;
         delay(100);
         PORTB=0XFF;
      delay(50);
     }
      if(temp2[1]==17)
     {
         PORTB=0XFD;
         delay(100);
         PORTB=0XFF;
      delay(50);
     }
      if(temp2[2]==16)
     {
         PORTB=0XFB;
         delay(100);
         PORTB=0XFF;
      delay(50);
     }
    
      if(temp2[3]==15)
     {
         PORTB=0XF7;
         delay(100);
         PORTB=0XFF;
      delay(50);
     }
    
      if(temp2[4]==14)
     {
         PORTB=0XEF;
         delay(100);
         PORTB=0XFF;
      delay(50);
     }
    
      if(temp2[5]==13)
     {
         PORTB=0XDF;
         delay(100);
         PORTB=0XFF;
      delay(50);
     }
    
      if(temp2[6]==12)
     {
         PORTB=0XBF;
         delay(100);
         PORTB=0XFF;
      delay(50);
     }
    
      if(temp2[7]==11)
     {
         PORTB=0X7F;
         delay(100);
         PORTB=0XFF;
      delay(50);
     }
  }
}

仿真PROTUES7.5图如下



示波器查看波形如图


IIC接收数据查看如图
进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 用NE555制作定时器

  • 如何构建一个触摸传感器电路

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章