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

📄 i2c_wr_rd.c

📁 PIC16系列单片机上使用软件方式模拟I2C接口读写AT24存储芯片
💻 C
字号:
//AT24地址0xa0,采用页写入方式(连续字节写)写入CODE数组9个数据
//采用页读取方式读出0x00~0x08地址上9个字节数据
//PIC使用1M晶振,用软件模拟I2C接口
//SCL=RC0,SDA=RC1,用RB循环显示读取到的数据(隔一段时间换一个数据)
//在PROTEUS仿真软件上成功运行

#include<pic166x.h>
#define uchar unsigned char
#define nop() asm("nop")   //当晶振提高时,此延时单元须加倍,以保证SCL,SDA电平宽度
#define SCL TRISC0
#define SDA TRISC1

void start_i2c();
void stop_i2c();
void send_byte(uchar c);
uchar receive_byte();
//void send_str(uchar sla,uchar suba,uchar*s,uchar no);
void delay_250ms();
void i2c_error();
void send_ack();
void send_nack();
uchar code[]={0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar get[0x09];

uchar no;
uchar ackk;
uchar c,data;

void main(void)
{
 uchar i;
 TRISA=0x00;
 PORTA=0x0f;
 TRISC=0xff;
 PORTC=0x00;
 TRISB=0x00;
 PORTB=0x00;

//连续写入9个数据
 start_i2c();   
 send_byte(0xa0);
 if(ackk==0x00) i2c_error();
 send_byte(0x00);
 if(ackk==0x00) i2c_error();
 for(i=0x00;i<0x09;)
 {
  send_byte(code[i++]);
  if(ackk==0x00) i2c_error();
    }
 stop_i2c();
 delay_250ms();


 while(1)
 {
  //连续读取9个字节数据
   start_i2c();
   send_byte(0xa0);
   if(ackk==0x00) i2c_error(); //无应答,显示错误
   send_byte(0x00);           //send word address
   if(ackk==0x00) i2c_error();
   
   start_i2c();
   send_byte(0xa1);
   if(ackk==0x00) i2c_error();

  for(i=0x00;i<0x08;)
  {
   get[i++]=receive_byte();
   send_ack();
   }
   get[0x08]=receive_byte();
   send_nack();   
   stop_i2c();

   for(i=0x00;i<0x09;i++)       //循环显示读取到的9个数据
   {
   PORTB=get[i];
   delay_250ms();
    }
  }
}


/*
 while()
 {
  for(i=0x00;i<0x09;i++)
  {
   start_i2c();
   send_byte(0xa0);
   if(ack==0x00) i2c_error(); //无应答,显示错误
  ssend_byte(i);           //send word address
   if(ack==0x00) i2c_error();
   
   start_i2c();
   send_byte(0xa1);
   if(ack==0x00) i2c_error();
   data=receive_byte();
   send_nack();
   stop_i2c();
   PORTB=data;
   delay_250ms();
   delay_250ms();
   }
  }
 }
*/

//***************I2C操作子程序(包括起始、结束、读、写)
void start_i2c()
{
 SDA=1;
 nop();
 SCL=1;
 nop(); nop(); nop(); nop(); nop();
 SDA=0;
  nop(); nop(); nop(); nop(); nop();
 SCL=0;
  nop(); nop();
 }

void stop_i2c()
{
 SDA=0;
  nop();
 SCL=1;
  nop(); nop(); nop(); nop(); nop();
 SDA=1;
  nop(); nop(); nop(); nop(); nop();
 }

void send_ack()
{
 SDA=0;
 SCL=0;
  nop(); nop();nop(); nop();nop(); 
 SCL=1;
  nop(); nop(); nop();nop(); nop();
 SCL=0;      //release SCL to be free
}
 
void send_nack()
{
 SDA=1;
 SCL=0;
  nop(); nop();nop(); nop();nop(); 
 SCL=1;
  nop(); nop(); nop();nop(); nop();
 SCL=0;                                //SCL低电平为空闲状态
}

void send_byte(uchar c)
{
 uchar bit_count;
 for(bit_count=0x00;bit_count<0x08;bit_count++)
 {
  if((c<<bit_count)&0x80)  SDA=1;
  else  SDA=0;
  
   nop();
  SCL=1;  
    nop(); nop(); nop(); nop();nop();  //SCL低电平时改变SDA值,SCL高电平时传递出去,故只需保证SCL高电平宽度
  SCL=0;
  }

//*******接收应答信号,ack=1表示收到应答****
 nop(); nop();        
 SDA=1;
  nop(); nop();
 SCL=1;
  nop(); nop(); nop();
 ackk=0x01; 
 if(RC1==1)    
{  ackk=0x00 ; }    //接收方须在第9个SCL周期把SDA线拉低
  SCL=0;
  nop(); nop();
 }

uchar receive_byte()
{
 uchar retc,bit_count;
 retc=0x00;
 SDA=1;
 for(bit_count=0x00;bit_count<0x08;bit_count++)
 {
   nop();
  SCL=0;                
   nop(); nop(); nop(); nop(); nop();
  SCL=1;
  nop(); nop();  
  retc<<=0x01;
  if(RC1==1) retc+=0x01;   //数据在SCL为低时改变,而在SCL为高时稳定不变,所以在SCL高电平时读取SDA值
   nop(); nop();
  }
 SCL=0;
 nop(); nop();
 return retc;
 }


/*void send_str(uchar sla,uchar suba,uchar *s,uchar no)
{
 uchar i;
 start_i2c();
 send_byte(sla);
 if(ackk==0x00) i2c_error();
 send_byte(suba);
 if(ackk==0x00) i2c_error();
 for(i=0;i<no;i++)
 {
  send_byte(*s);
  if(ackk==0x00) i2c_error();
  s++;
  }
 stop_i2c();
 }
*/

void delay_250ms()
{
 unsigned int d=24999;
 while(--d);
}



void i2c_error()      //RB7闪动8次表示总线操作失败1次
{
 uchar i;
 for(i=0x00;i<0x08;i++)
 { 
  PORTB=~PORTB;
  delay_250ms();
  PORTB=~PORTB;
  delay_250ms();
  }
 } 

⌨️ 快捷键说明

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