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

📄 i2c.c

📁 用pic单片机做的一个温度计 实现实时时钟显示和存储
💻 C
字号:
#include<p18f452.h>
#include"delays.h"

/*****************************************************************************
 ******函 数 名 称 :  i2c_idle()
 ******函 数 功 能 :  判读i2c是否空闲
 ******输       入 : 
 ******输       出 :  
 ******注       意 :  
 ******************************************************************************/ 
void i2c_idle(void)
{
 while( SSPSTATbits.R_W);
}

/*****************************************************************************
 ******函 数 名 称 :  initial_i2c()
 ******函 数 功 能 :  初始化i2c
 ******输       入 :  无
 ******输       出 :  无
 ******************************************************************************/ 

void initial_i2c(void)
 {
        TRISCbits.TRISC3=1;       //定义SCL(RC3)输入  
        TRISCbits.TRISC4=1;       //定义SDA(RC4)输入
       
                                
        SSPCON1=0x28;            //SSPEN=1 同步串口使能 and SSPM3:SSPM0=1000 主动模式 时钟=Fosa/(4*(SSPADD+1))
        
        SSPADD= 0x28;            //传输速率100k 
      
 }

/*****************************************************************************
 ******函 数 名 称 :  start_i2c()
 ******函 数 功 能 :  i2c开始条件产生
 ******输       入 :  无
 ******输       出 :  无
 ******************************************************************************/ 
void start_i2c( void )
 {
  SSPCON2bits.SEN = 1;            // 在SDA和SCL启动启动条件  由硬件自动清零
  while(!PIR1bits.SSPIF);         //判断 i2c传输(接收、发送)中断位
       PIR1bits.SSPIF=0;  
 }

/*****************************************************************************
 ******函 数 名 称 :  restart_i2c()
 ******函 数 功 能 :  i2c重起条件产生
 ******输       入 :  无
 ******输       出 :  无
 ******************************************************************************/ 
void  restart_i2c( void )
 {
  SSPCON2bits.RSEN = 1;           //在SDA和SCL启动重复启动条件  由硬件自动清零
  while(!PIR1bits.SSPIF);        
       PIR1bits.SSPIF=0;  
 }


/*****************************************************************************
 ******函 数 名 称 :  stop_i2c()
 ******函 数 功 能 :  i2c停止条件产生
 ******输       入 :  无
 ******输       出 :  无
 ******************************************************************************/ 
void  stop_i2c( void )
 {
  SSPCON2bits.PEN = 1;            // 在SDA和SCL启动停止条件  由硬件自动清零
  while(!PIR1bits.SSPIF);         
       PIR1bits.SSPIF=0;  
 }

/*****************************************************************************
 ******函 数 名 称 :  write_i2c()
 ******函 数 功 能 :  i2c写条件产生
 ******输       入 :  无
 ******输       出 :  无
 ******************************************************************************/ 
void write_i2c(  char date )
   {
        SSPBUF = date;

         while(!PIR1bits.SSPIF);  
         PIR1bits.SSPIF=0;  
   }



/*****************************************************************************
 ******函 数 名 称 :  write_i2c_data()
 ******函 数 功 能 :  通过硬件IIC向器件写入数据
 ******输       入 :  addr(从器件地址), child_addr(从器件内部寄存器的子地址),date( 要写入的数据)
 ******输       出 :  无
 ******注       意 :  地址的最低位总是0
 ******************************************************************************/ 

void  write_i2c_data( char addr, char child_addr, char date)

{ 
  i2c_idle();                    //等待i2c处于空闲
  start_i2c();                     // 启动开始
  
  write_i2c(addr&0xFE);                 // 写入从器件地址
  while(SSPCON2bits.ACKSTAT);          //接受来自从器件的应答
  
  write_i2c(child_addr);           // 从器件内部寄存器的子地址
  while(SSPCON2bits.ACKSTAT); 

  write_i2c(date);                // 写入信息
  while(SSPCON2bits.ACKSTAT); 

  stop_i2c();                      // 停止
  delays(100,150);
}

/*****************************************************************************
 ******函 数 名 称 :  write_i2c_pagedate()
 ******函 数 功 能 :  通过硬件IIC向器件写入多组数据
 ******输       入 :  addr(从器件地址), child_addr(从器件内部寄存器的子地址),*dptr( 要写入的数据的首地址);unsigned char length(写入的数据长度)
 ******输       出 :  
 ******注       意 :  
 ******************************************************************************/ 
void write_i2c_pagedate( char addr,char child_addr,char length, char *dptr)
{
  
  
     while(length!=0)
       {
           write_i2c_data(  addr, child_addr, *dptr++);
           child_addr++;
           length--;
       }


  
   
}
/*****************************************************************************
 ******函 数 名 称 :  read_i2c_date()
 ******函 数 功 能 :  通过硬件IIC从从器件读数据
 ******输       入 :  addr(从器件地址), child_addr(从器件内部将被读的寄存器的子地址)
 ******输       出 :  读到的数据
 ******注       意 :  地址的最低位总是0
 ******************************************************************************/ 
unsigned char  read_i2c_date( char addr, char child_addr)

{ 
 
  char f;
  i2c_idle();                            ///等待i2c处于空闲
  start_i2c();                             // 启动开始
  
  write_i2c(addr&0xFE);                         //写入从器件地址
  while(SSPCON2bits.ACKSTAT);          //接受来自从器件的应答

  write_i2c(child_addr);                   //从器件内部寄存器的子地址
  while(SSPCON2bits.ACKSTAT); 

  restart_i2c();
  
  write_i2c(addr|0x01);                    // 从器件内部寄存器的子地址并使能读操作
  while(SSPCON2bits.ACKSTAT); 
  
  SSPCON2bits.RCEN=1;                     // 使能接受
  while(!PIR1bits.SSPIF);  
  f=SSPBUF;             
  PIR1bits.SSPIF=0;
    
  SSPCON2bits.ACKDT=1;                    // 应答数据为 1=不应答 0=应答
  SSPCON2bits.ACKEN=1;                    //启动SCL SDA应答序列  发送ACKDTS数据位
  while(!PIR1bits.SSPIF);               
       PIR1bits.SSPIF=0;          
      
  stop_i2c();                              // 停止I2C工作
  delays(100,150);
  return (f);                        // 返回 SSPBUF值
 }
/*****************************************************************************
 ******函 数 名 称 :  read_i2c_pagedate()
 ******函 数 功 能 :  通过硬件IIC从从器件读出多组数据
 ******输       入 :  addr(从器件地址), child_addr(从器件内部寄存器的子地址),*dptr( 要读出的数据的首地址);unsigned char length(读出的数据长度)
 ******输       出 :  
 ******注       意 :  
 ******************************************************************************/ 
void read_i2c_pagedate( char addr, char child_addr, char length, char *dptr)
{ 

  while(length!=0)
       {   
            
           *dptr++=read_i2c_date( addr,child_addr++);            
            length--;
       }   
                          // 停止I2C工作
 }



/*****************************************************************************
 ******函 数 名 称 :  float stof()
 ******函 数 功 能 :  从eeprom中读取小数
 ******输       入 : 
 ******输       出 :  
 ******注       意 :  
 ******************************************************************************/ 
 float stof( char addr, char child_addr)
{
  char  i; 
  union {
          char c[4];
          float f;
        }temp;
  temp.f=0;
  for(i=0;i<4;i++)
   {
     temp.c[i]=read_i2c_date(addr, child_addr+i);
   }
 
   return temp.f;
  
}      
/*****************************************************************************
 ******函 数 名 称 :  float ftos()
 ******函 数 功 能 :  往eeprom中写入小数
 ******输       入 : 
 ******输       出 :  
 ******注       意 :  
 ******************************************************************************/ 
void   ftos(float a, char addr, char child_addr)
{ 
  char dat;
  char  i; 
  union {
          char c[4];
          float f;
        }temp;
  temp.f=a; 
  for(i=0;i<4;i++)
   {  
    
    dat=temp.c[i];
    write_i2c_data( addr, child_addr+i, dat);

   }   
  
}























⌨️ 快捷键说明

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