ARM7 Getting Started 11, IIC Communication

Publisher:WiseThinkerLatest update time:2016-11-01 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
If D1 is lit, it is correct; if D1 is blinking, it is wrong.

Main program:

/*******************************************************************************
*File: Main.C
*Function: Use hardware I2C to operate EEPROM, and use interrupt mode to operate
******************************************************************************/
#include "config.h"
#define CAT24WC02 0xA0 /*Define device address*/
#define LED1CON 0x00000400 /*P0.10 pin controls LED1, low level lights up*/
/*The following are the variables required for I2C operation, and these variables must be set before calling the I2C subroutine*/
volatile uint8 I2C_sla; //Slave addressvolatile
uint8 I2C_suba; //Sub addressvolatile
uint8 *I2C_buf; //Data buffer pointer (will be changed during read operation)
volatile uint8 I2C_num; //Number of operation datavolatile
uint8 I2C_end; //Operation end flag, 1 indicates the operation is over, 0xFF indicates the operation failed
volatile uint8 I2C_suba_en; //Sub-address enable control, set to 1 for read operation and 2 for write operation


/*******************************************************************************
*Name: IRQ_I2C()
*Function: I2C interrupt, perform corresponding operations by judging the I2C status word
********************************************************************/
void __irq IRQ_I2C(void)
{ uint8 sta;
  sta=I2STAT; //Read out the I2C status wordswitch
  (sta)
  { case 0x08: //The start condition has been sentif
    (1==I2C_suba_en)I2DAT=I2C_sla&0xFE; //When specifying the sub-address to read, write the address firstelse
    I2DAT=I2C_sla; //Otherwise, send the slave address directlyI2CONCLR
    =0x28; //SI=0
    break;
    
    case 0x10:
    I2DAT=I2C_sla; //After restarting the bus, send the slave addressI2CONCLR
    =0x28; //SI=0
    break;
    case 0x18: //SLA+W has been sent, and the response has been received
    if(0==I2C_suba_en) //No sub-address, then send data directly
    { if(I2C_num>0)
    { I2DAT=*I2C_buf++;
      I2CONCLR=0x28;
      I2C_num--;
    }
    else
    { I2CONSET=0x10; //No data to send, end the bus
      I2CONCLR=0x28;
      I2C_end=1; //Set the bus operation end flag
    }
    break;
    }
    if(1==I2C_suba_en) //Send sub-address
    { I2DAT=I2C_suba;
      I2CONCLR=0x28;
    }
    if(2==I2C_suba_en) //Send sub-address
    { I2DAT=I2C_suba;
      I2CONCLR=0x28;
      I2C_suba_en=0; //Subaddress processed
    }
    break;
  case 0x28: //I2C data sent, and response received
    if(0==I2C_suba_en) //No subaddress, send data directly
    { if(I2C_num>0)
    { I2DAT=*I2C_buf++;
    I2CONCLR=0x28;
    I2C_num--;
    }
    else
    { I2CONSET=0x10; //No data sent, end bus
      I2CONCLR=0x28;
      I2C_end=1;
     }
    break;
    }
    if(1==I2C_suba_en) //If the address is specified, restart the bus
    { I2CONSET=0x20;
      I2CONCLR=0x18;
      I2C_suba_en=0; //Subaddress processed
    }
    break; 
   
case 0x20:
case 0x30:
case 0x38:
  I2CONCLR=0x28; //The bus enters the non-addressable slave mode
  I2C_end=0xFF; //Bus error, set the flag
  break;
case 0x40: //SLA+R has been sent and the response has been received
  if(1==I2C_num) //The last byte, send a non-response signal after receiving the data
  { I2CONCLR=0x2C; //AA=0, generate a non-response after receiving the data
  }
  else //Receive data and send a response signal
  { I2CONSET=0x04; //AA=1, generate a response after receiving the data
    I2CONCLR=0x28;
  }
  break;
case 0x50:
  *I2C_buf++=I2DAT; //Read data
  I2C_num--;
  if(1==I2C_num)
  { I2CONCLR=0x2C;  
  }
  else
  {I2CONSET=0x04;
   I2CONCLR=0x28;
  }
  break;
case 0x58:
  *I2C_buf++=I2DAT; //Read the last byte of data
  I2CONSET=0x10; //End the bus
  I2CONCLR=0x28;
  I2C_end=1;
  break;
case 0x48:
  I2CONCLR=0x28; //The bus enters the non-addressable slave mode
  I2C_end=0xFF;
  break;
}
VICVectAddr=0x00; //End of interrupt processing
}  

/*******************************************************************************
*Name: ISendStr()
*Function: Use hardware I2C to send data
****************************************************************************/
uint8 ISendStr(void)
{ I2C_end=0;

  I2CONCLR=0x2C;
  I2CONSET=0x40; //Enable I2C
  I2CONSET=0x64; //Set as host and start the buswhile
  
  (0==I2C_end);
  if(1==I2C_end)return(1);
  else return(0);
}
/*******************************************************************************
*Name: IRcvStr()
*Function: Use hardware I2C to read data
*******************************************************************************/
uint8 IRcvStr(void)
{ if(0==I2C_num)return(0);
  I2C_end=0;
  I2CONCLR=0x2C;
  I2CONSET=0x40; //Enable I2C
  I2CONSET=0x64; //Set as host and start the buswhile
  (0==I2C_end);
  if(1==I2C_end)return(1);
  else return(0);
}
/*******************************************************************************
*Name: I2C_Init()
*Function: I2C initialization, including initialization of its interrupt as vector IRQ interrupt
*******************************************************************************/
void I2C_Init(void)
{ /*Set I2C clock to 100kHz*/
  I2SCLH=I2SCLL=14; //Crystal oscillator is 11.0592MHz, Fpclk=2.7648MHz
  /*Set I2C interrupt enable*/
  VICIntSelect=0x00000000; //Set all channels to IRQ interrupt
  VICVectCntl0=0x29; //I2C channel is assigned to IRQ Slot0, which has the highest priority
  VICVectAddr0=(int)IRQ_I2C; //Set I2C interrupt vector address
  VICIntEnable=0x0200; //Enable I2C interrupt
  
}
/****************************************************************************
*Name: DelayNS()
*Function: Long software delay
************************************************************************/
void DelayNS(uint32 dly)
{ uint32 i;
  for(;dly>0;dly--)
    for(i=0;i<50000;i++);
}
/***********************************************************************************
*Name: WrEepromErr()
*Function: Read and write E2PROM error alarm, i.e. flashing LED1
*******************************************************************************/
void WrEepromErr(void)
{ while(1)
 { IO0SET=LED1CON;
  DelayNS(50);
  IO0CLR=LED1CON;
  DelayNS(50);
 }
}
/*******************************************************************************
*Name: main()
*Function: Write 10 bytes of data to E2PROM, and then read it out to determine whether it is written correctly
******************************************************************************/
int main(void)
{ uint8 i;
   uint8 data_buf[30];
   PINSEL0=0x00000050; //Set the I/O port working mode to use I2C
   PINSEL1=0x00000000;
   IO0DIR=LED1CON; //Set LED1 control port to output and other I/O to input
   I2C_Init(); //I2C initialization
   for (i=0;i<10;i++)data_buf[i]=i+'0';
   I2C_sla=CAT24WC02;
   I2C_suba=0x00;
   I2C_suba_en=2;
   I2C_buf=data_buf;
   I2C_num=10;
   ISendStr(); //Write 10 bytes of data at 0x00 address
   DelayNS(1); //Wait for the write cycle to end
   for(i=0;i<10;i++)data_buf[i]=0;
   I2C_sla=CAT24WC02+1;
   I2C_suba=0x00;
   I2C_suba_en=1;
   I2C_buf=data_buf;
   I2C_num=10;
   IRcvStr(); //Read 10 bytes of data at 0x00 address
   /*Check the read data, if incorrect, flash the LED alarm*/
   for(i=0;i<10;i++)
   { if(data_buf[i]!=(i+'0'))WrEepromErr();
   }
   IO0CLR=LED1CON; //Light up LED1
   while(1);
}

Reference address:ARM7 Getting Started 11, IIC Communication

Previous article:ARM7 Getting Started 10, Serial Port Communication
Next article:IIC bus application

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号