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

📄 i2c.c

📁 msp430模拟iic程序,读写外部eeprom
💻 C
字号:
#include "msp430x14x.h"
#include "i2c.h"

#define   add_max   0x7f  //EEPROM换页判断

extern void delay(unsigned int time);//延时子程序
/**********************************************************************/
//函数功能: Stop_I2总线,即发送I2C起始条件.
//函数原型: void Start_I2c(void);
//入口:无C();	//写入完毕停止总线
//出口:无
/**********************************************************************/
void Start_I2C(void);
void Start_I2C(void)
{
  iic_port_ini(); //初始化SDA,SCL输出高电平
  delay(250);
  CLR_SDA();   	  //发送起始信号
  delay(250);     //起始条件锁定时间大于4μs
  CLR_SCL();   	  //钳住I2C总线,准备发送或接收数据
  delay(100);
}
/**********************************************************************/
//函数功能: 结束I2C总线,即发送I2C结束条件.
//函数原型: void  Stop_I2c();
//入口:无
//出口:无
/**********************************************************************/
void Stop_I2C(void);
void Stop_I2C(void)
{
  SDA_OUT();
  CLR_SDA();  
  SET_SCL();  	//发送结束条件的时钟信号,结束条件建立时间大于4μs
  delay(250);
  SET_SDA();  	//发送I2C总线结束信号
  delay(100);
}
/**********************************************************************/
//函数功能:将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
//       此状态位进行操作.(不应答或非应答都使ack=0)
//     	 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
//函数原型: void  SendByte(uchar c);
//入口:c--要发送的数据
//出口:返回0表示未接到应答,1表示接到应答
/**********************************************************************/
unsigned char SendByte(unsigned char cc);
unsigned char SendByte(unsigned char cc)
{
  unsigned char BitCnt;
  unsigned int i=0;
  
  SDA_OUT();
  CLR_SCL();//拉低时钟
  for(BitCnt=0;BitCnt<8;BitCnt++)
  {
    CLR_SCL();//拉低时钟
    if((cc&0x80)==0x80)
      SET_SDA();
    else
      CLR_SDA();
    delay(100);
    SET_SCL();
    delay(100);
    cc=cc<<1;
  }
  CLR_SCL();//8位发送完后释放数据线,准备接收应答位
  delay(200);
  SDA_IN();
  SET_SCL();
  BitCnt = 0;
  while((SDA&IICPORTIN)==SDA)
  {
    i++;
    if(i>500)
    {
      BitCnt=1;
      break;
    }
  }
  CLR_SCL();
  SDA_OUT();
  return BitCnt;
}
/**********************************************************************/
//函数功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
//         发完后请用应答函数应答从机。
//函数原型: uchar  RcvByte();带参数返回
//入口:无
//出口:返回读取到的总线数据
/**********************************************************************/
unsigned char RcvByte(void);
unsigned char RcvByte(void)
{
  unsigned char retc;
  unsigned char BitCnt;
  
  retc=0;
  SDA_IN();                       //置数据线为输入方式
  for(BitCnt=0;BitCnt<8;BitCnt++)
  {
      SET_SCL();//置时钟线为高使数据线上数据有效
      delay(100);
      retc<<=1;
      if((SDA&IICPORTIN)==SDA)
        retc=retc+1;//读数据位,接收的数据位放入retc中
      CLR_SCL();
      delay(100);
  }
  SDA_OUT();                   //置数据线为输出方式
  return(retc);
}
/**********************************************************************/
//函数功能: 主控器进行应答信号(可以是应答或非应答信号,由参数a决定)
//      a=0不发送应答信号应答子函数
//函数原型:  void Ack_I2c(uchar a);
//入口:a--决定是否要发送应答信号,a=0不发送应答信号应答子函数
//出口:无
/**********************************************************************/
void Ack_I2c(unsigned char aa);
void Ack_I2c(unsigned char aa)
{
  SDA_OUT();
  CLR_SCL();
  if(aa==0) SET_SDA();     //在此发出应答或不发送应答信号
     else  CLR_SDA();
  delay(100);
  SET_SCL();
  delay(100);             //时钟低电平周期大于4μs
  CLR_SCL();             //清时钟线,钳住I2C总线以便继续接收
}
/**********************************************************************/
//函数功能:写数据到EEPROM
//函数原型:void write_in(uint addr,uchar data)
//入口:eaddr-EEPROM片地址,addr--所要写入数据的地址,wdata_addr--所要写入的数据首地址,lenth所要写入数据长度
//出口:无
/**********************************************************************/
void write_in(unsigned char eaddr,unsigned int addr,unsigned char *wdata_addr,unsigned int lenth);
void write_in(unsigned char eaddr,unsigned int addr,unsigned char *wdata_addr,unsigned int lenth)
{
  _DINT();
  Start_I2C();//启动总线
  SendByte(0xa0+eaddr);//外部地址+控制数据
  SendByte(addr/256);//寻址EEPROM写命令,写入地址高低字节地址
  SendByte(addr%256);
  for(;lenth>0;lenth--)
  {
    SendByte(*wdata_addr);//写入数据
    if((addr&add_max)==add_max)//换页判断
    {
         Stop_I2C();
         delay(20000);
         Start_I2C();//启动总线
         SendByte(0xa0+eaddr);
         SendByte((addr+1)/256);//寻址EEPROM写命令,写入地址高低字节地址
         SendByte((addr+1)%256);
    }
    wdata_addr++;
    addr++;
  }
  Stop_I2C();
  delay(7000);
  _EINT();
}
/**********************************************************************/
//函数功能:从EEPROM某个地址读出数据
//函数原型:void read_out(uint addr)
//入口:eaddr-EEPROM片地址,addr--所要读出数据的地址,rdata_addr--RAM中存放数据的首地址,lenth--读取数据的长度
//出口:无
/**********************************************************************/
void read_out(unsigned char eaddr,unsigned int addr,unsigned char *rdata_addr,unsigned int lenth);
void read_out(unsigned char eaddr,unsigned int addr,unsigned char *rdata_addr,unsigned int lenth)
{
  _DINT();
  Start_I2C(); //启动总线
  SendByte(0xa0+eaddr);//外部地址+控制数据
  SendByte(addr/256);//寻址EEPROM写命令,写入地址高低字节地址
  SendByte(addr%256);
  Start_I2C(); //启动总线
  SendByte(0xa0+eaddr+0x01);//寻址EEPROM读命令
  for(;lenth>0;lenth--)
  {
      *rdata_addr=RcvByte();//读取数据
      if(lenth==1)
        Ack_I2c(0);
      else
        Ack_I2c(1);
      rdata_addr++;
  }
  Stop_I2C();	//读完停止总线
  _EINT();
}

/**********************************************************************/
//函数功能:写数据到EEPROM
//函数原型:void write_in(uint addr,uchar data)
//入口:addr--所要写入数据的地址,wdata_addr--所要写入的数据首地址,lenth所要写入数据长度
//出口:无
/**********************************************************************/
void write_in_byte(unsigned char eaddr,unsigned int addr,unsigned char dat);
void write_in_byte(unsigned char eaddr,unsigned int addr,unsigned char dat)
{
  _DINT();
  Start_I2C();//启动总线
  SendByte(0xa0+eaddr);//外部地址+控制数据
  SendByte(addr/256);//寻址EEPROM写命令,写入地址高低字节地址
  SendByte(addr%256);
  SendByte(dat);
  Stop_I2C();
  delay(700);
  _EINT();
}

⌨️ 快捷键说明

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