zoukankan      html  css  js  c++  java
  • IIC 通信

    IIC 通用文件,文件是在NRF51xx 芯片基础,keil 平台开发测试通过,后期修改为STM32F2xx系列的配置。

    文件百度云盘链接 : https://pan.baidu.com/s/1AFxanwzrAViaubtERZMRsA  

    注意:在用于STM32Fx 系列时注意引脚读取函数的选择!

    下面是示波器现实,IIC通讯读的操作。

    理论基础:

    • SCL为高,SDA发生变化,即为发生了特殊状态(ACK, NACK, START, STOP)
    • SCL为低,SDA发生变化,即为数据端发生跳变,这个是无影响的。
    • IIC总线在数据传输时,时钟信号为高电平,数据线上的数据必须保持稳定,只有在SCL上的信号为低电平时,SDA线才允许变
    • IIC_confing.h 主要是SIMU_IIC.c 文件的一些结构体和端口设置, I2c_Str 结构体可以再添加数据属性,包括后期的数据,主要用于 SIMU_IIC.c 文件内部使用。
    • /**************************************************************************//**
       * @file    IIC_confing.h     
       * @brief For IIC communication
       * @author ning lv
       * @version 0.01
       ******************************************************************************
       * @section License
       ******************************************************************************
       *
       *****************************************************************************/
      
      #ifndef _I2C_CONFING_H_
      #define _I2C_CONFING_H_
      
      #ifdef __cplusplus
          extern "C" {
      #endif
      
      #include "SIMU_IIC.h"
      /*
      *** You can choose yours projects ...*/
      //#define NRF51822   //试用在蓝牙芯片上
      #define STM32F205       //
      
      /*
      *** Redefines the exact width signed integer type ...*/
      //typedef unsigned              char uint8;
      //typedef unsigned               int uint32;
      //typedef   signed          char uint8_t;
      
      /*
      *** Define variables and structures ... */
      typedef struct {
          uint32 SDA;            
          uint32 SCL;    
          uint32 GPIO;
      }I2c_Str;
      
      /*
      ***The global variable ... */
      I2c_Str type_Struct; //all 
      //sda  scl
      typedef void(*pI2cLineF)(uint32 sda,uint32 scl);
      pI2cLineF _I2cLine = _NULL;
      // gpio
      typedef void(*pI2cGpioF)(uint32 gpo);
      pI2cGpioF _I2cGpio = _NULL;
      /*
      ***Chip selection ... */
      #if defined NRF51822
      #define CHOOSE_IN                     _TRUE
      #define CHOOSE_OUT                    _NULL
      #elif defined STM32F205
      #define CHOOSE_IN                 (GPIO_Mode_IN )
      #define CHOOSE_OUT                (GPIO_Mode_OUT)
      #define GPIO_PORT                 ((GPIO_TypeDef*)type_Struct.GPIO)
      #endif
      
      /*
      ***Output 0/1 ... */
      #define SDA_OUT_H                           ( Gpio_Pin_Wr(type_Struct.SDA,_TRUE) )
      #define SDA_OUT_L                           ( Gpio_Pin_Wr(type_Struct.SDA,_NULL) )
      #define SCL_OUT_H                           ( Gpio_Pin_Wr(type_Struct.SCL,_TRUE) )
      #define SCL_OUT_L                           ( Gpio_Pin_Wr(type_Struct.SCL,_NULL) )
      
      /*
      ***Choose output/input ... */ 
      #define SDA_SET_IN                    ( I2c_Pin_Dir (type_Struct.SDA,CHOOSE_IN) ) 
      #define SDA_SET_OUT                    ( I2c_Pin_Dir (type_Struct.SDA,CHOOSE_OUT) )
      #define SCL_SET_IN_                    ( I2c_Pin_Dir (type_Struct.SCL,CHOOSE_IN) )
      #define SCL_SET_OUT                    ( I2c_Pin_Dir (type_Struct.SCL,CHOOSE_OUT) )
      /*
      *** Reads lines ... */ 
      #define RD_SDA_IN                      ( Gpio_Pin_Red(type_Struct.SDA) ) 
      #define RD_SCL_IN                      ( Gpio_Pin_Red(type_Struct.SCL) )
      
      /*
      *** times ... */ 
      #define NOP()                                                ( __nop()     )
      #define Iic_Delay(x)                                ( delay_us(x) )
      
      #ifdef __cplusplus
          }
      #endif
      #endif /*_I2C_CONFING_H_*/
      SIMU_IIC.c 文件主要的运行文件,开头是所需的芯片头文件,特别注意的是delay_ms();和delay_us();两个函数要根据芯片的不同,配置设备的不同定向修改,修改的过程中可以用示波器具体调试时间。
    • //Header files ...
      #include "IIC_confing.h"  //master and the explanation is here!!
      #include "usart.h"
      
      //Chip selection ...
      #if defined NRF51822
      #include "nrf_gpio.h"
      #elif defined STM32F205
      #include <stm32f2xx_gpio.h>
      #endif
      
      /*
      ***Function declaration ...*/
      void Delay5us(void);
      void Delay5us(void);
      void Delay10us(void);
      void Gpio_Pin_Wr(uint32 pin ,uint8 wr);
      void I2c_Pin_Dir(uint32 pin, uint8 dir);
      void Choose_I2c_Pin(uint32 sda,uint32 scl);
      void Gpio_Confing(uint32 gpo);
      
      //下面的可以发布在IIC.h 函数中,对外的接口设置
      void I2c_Stop(void);
      void I2c_NoAck(void);
      void I2c_RecAck(void);
      void I2c_Reset (void);
      uint8 I2c_Start(void);
      uint8 I2c_WaitACK(void);
      uint8 I2c_RcvByte(void);
      void I2c_SendByte(uint8 c);
      uint8 Gpio_Pin_Red(uint32 pin);
      void IIC_confing_Pin(uint32 sda,uint32 scl, uint32 gpo);
      void delay_ms(uint32 volatile number_of_ms);
      void delay_us(uint32 volatile number_of_us);
      
      /**@brief Delay 1us
       */
       void Delay1us(void)
      {
        NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
      #if defined STM32F205    
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
          NOP();NOP();NOP();NOP();
      #endif
      }
      /**@brief Delay 5us
       */
      void Delay5us(void)
      {
          Delay1us();
              Delay1us();
              Delay1us();
              Delay1us();
      }
      
      /**@brief Delay 10us
       */
      void Delay10us(void)
      {
          Delay5us();
          Delay5us();
      }
      
      /**@brief Delay(ms)  
       *
       * @param[in] number_of_ms 
       */
      void delay_ms(uint32 volatile number_of_ms)
      {
          number_of_ms = number_of_ms * 1000;
          while(number_of_ms != 0)
          {
                  number_of_ms--;
            Delay1us();
          }
      }
      
      /**@brief Delay(us)  
       *
       * @param[in] number_of_us 
       */
      void delay_us(uint32 volatile number_of_us)
      {
               while(number_of_us != 0)
          {
              number_of_us--;
                      Delay1us();
                  
          }
      }
      
      /**@brief Select the I2C sda and scl pins. 
       */
      void Choose_I2c_Pin(  uint32 sda,uint32 scl  )
      {
           type_Struct.SDA = sda;
           type_Struct.SCL = scl;
      }
      
      /**@brief Function Pointers set GPIO
       */
      void Gpio_Confing( uint32 gpo  )
      {
          type_Struct.GPIO = gpo;
      }
      
      /**@brief Function Pointers set the sda and SCL pins
       */
      void IIC_confing_Pin( uint32 sda,uint32 scl, uint32 gpo)
      {
      #if defined STM32F205
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
      #endif
          _I2cGpio = (pI2cGpioF)Gpio_Confing;
          _I2cGpio(gpo);
          
          _I2cLine = (pI2cLineF)Choose_I2c_Pin ;
          _I2cLine(sda,scl);
      }
      
      /**@brief Iic_Pin_Dir  支持文件 STM32F2xx or NRF51822 
       *
       * @param[in] dir 
       */
      #if defined ( STM32F205 )
      void STM32F205_Pin_Dir (uint32 pin, uint8 dir)
      {
            GPIO_InitTypeDef GPIO_InitStructure;
          if(GPIO_Mode_OUT == dir){
              GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
          }else if(GPIO_Mode_IN == dir){
              GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
          }
          GPIO_InitStructure.GPIO_Pin =  pin;
          GPIO_Init(GPIO_PORT, &GPIO_InitStructure);
      }
      #elif defined ( NRF51822 )
      void nRF51822_Pin_Dir (uint32 pin, uint8 dir)
      {
          if ( dir == 0 ) {
                  nrf_gpio_cfg_output(pin);
              }else {
                  nrf_gpio_cfg_input(pin,NRF_GPIO_PIN_PULLUP);
              }       
      }
      #endif
      
      /**@brief The pin line outputs 0/1.
       *
       * @param[in] dir 
       */
      void I2c_Pin_Dir (uint32 pin, uint8 dir)
      {
      #if defined ( NRF51822 )
              nRF51822_Pin_Dir (pin, dir);
      #elif defined ( STM32F205 )
              STM32F205_Pin_Dir (pin, dir);
      #endif   
      }
      
      
      /**@brief SDA/SCL line write 0/1.
       *
       * @param[in] pin ,wr
       */
      
      void Gpio_Pin_Wr(uint32 pin ,uint8 wr)
      {
          if ( wr == 0 ) {
      #if defined ( NRF51822 )
           nrf_gpio_pin_write(pin,0);
      #elif defined ( STM32F205 )
           GPIO_WriteBit(GPIO_PORT , pin , 0);
      #endif 
          }
          else {
      #if defined ( NRF51822 )
               nrf_gpio_pin_write(pin,1);
      #elif defined ( STM32F205 )
               GPIO_WriteBit(GPIO_PORT , pin , 1);
      #endif 
          }       
      }
      
      /**@brief SDA/SCL line read 0/1.
       *
       * @param[in] pin 
       */
      uint8 Gpio_Pin_Red(uint32 pin)
      {
      #if defined ( NRF51822 )
           return ((uint8) nrf_gpio_pin_read(pin));
      #elif defined ( STM32F205 ) 
          return (uint8) GPIO_ReadInputDataBit(GPIO_PORT , pin);
      #endif     
      }    
      
      /**@brief IIC communication to prepare.
       *
       * @param[in] i2c_master 
       */
      uint8 I2c_Start(void)
      {
          /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
              I2c_Reset();
          
            SCL_SET_OUT;
            SDA_SET_OUT;  
          
            SDA_OUT_H;
            SCL_OUT_H;
            Iic_Delay(I2C_DELAY_TM);
            if( !RD_SDA_IN ) {
                  return I2C_BUSY; //BUSY
              }
              SDA_OUT_L;    
            Iic_Delay(I2C_DELAY_TM);
            if( RD_SDA_IN ) {
                  return I2C_ERROR; //ERROR
              }
            SDA_OUT_L;/*CPU占线*/
            return I2C_TRUE;
      }
      
      /**@brief IIC stop the communication .
       *
       * @param[in] i2c_master 
       */
      void I2c_Stop(void)
      {
          /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
              SCL_OUT_L;
            Iic_Delay(I2C_DELAY_TM);
            SDA_OUT_L;
            Iic_Delay(I2C_DELAY_TM);
            SCL_OUT_H;
            Iic_Delay(I2C_DELAY_TM);
            SDA_OUT_H;
      }
      
      /**@brief reset  
       */
      void I2c_Reset (void)
      {
          if( RD_SDA_IN == 0  
              //|| READ_SCL_IN == 0 
              ) 
          {    
              SCL_SET_OUT;
            SDA_SET_OUT;  
          Iic_Delay(I2C_DELAY_TM);
          
            SDA_OUT_H;
            SCL_OUT_H;
            Iic_Delay(I2C_DELAY_TM);
              
              I2c_SendByte(0xFF);
              I2c_NoAck();       
              I2c_Stop();    
          }
      }
      /**@brief Send the data 'c' out,either as data or as an address.
       *
       * @param[in] C 
       */
      void I2c_SendByte(uint8 c)
      {
             uint8 i;
             i = 8;
        
              while(i--) 
              {
                  SCL_OUT_L;    /*允许SDA 数据跳变*/
                  Iic_Delay(I2C_DELAY_TM); 
                  if( c&0x80) {
                      SDA_OUT_H;    
                  }
                  else {
                      SDA_OUT_L;
                  }                
                  
                  c<<=1;          
                  SCL_OUT_H;  /*SDA 数据保持 1us*/
                  Iic_Delay(I2C_DELAY_TM);
              }    
             SCL_OUT_L;    
              SDA_OUT_H; /*CPU 释放总线*/
      }
      
      /**@brief Reads a bytes of data and returns it.
       *
       * @param[out] retc 
       */
      uint8 I2c_RcvByte(void)
      {
             uint8 i = 8;
             uint8 retc = 0;
          
             SDA_SET_IN;
             SDA_OUT_L;/*总线默认拉高*/
             while(i--) 
              {
                 retc<<=1;
                 SCL_OUT_L;  /*CPU 允许 SDA 数据跳变*/
                 Iic_Delay(I2C_DELAY_TM);
                 SCL_OUT_H;  /*CPU 保持 SDA 数据1us*/
                 Iic_Delay(I2C_DELAY_TM);
                 if( RD_SDA_IN ) {
                     retc |= 0x01;
                 }
             }
             SCL_OUT_L;
             SDA_SET_OUT;
             SDA_OUT_H; /*CPU 释放总线*/
              
             return retc;    
      }
      /**@brief watint ACK 
       */
      uint8 I2c_WaitACK(void)
      {
          uint8 errTime = 250; 
          uint8 retFlag = I2C_TRUE;
          
              SCL_OUT_L;
            SDA_OUT_H;                                 /*CPU 释放总线*/
            Iic_Delay(I2C_DELAY_TM);
          
              SCL_OUT_H;                                 /*CPU驱动SCL = 1, 此时器件会返回ACK应答*/
              SDA_SET_IN;
            Iic_Delay(I2C_DELAY_TM);
              while((RD_SDA_IN)&&((errTime--) > 0))
              {
                  if(errTime == 0){
                      retFlag = I2C_FALSE;
                  }
              }
              SCL_OUT_L;
              SDA_SET_OUT;
              return retFlag;
      }
      /**@brief ACK response
       */
      void I2c_RecAck(void)
      {
          SCL_OUT_L;    /*CPU 允许 SDA 数据跳变*/
          Iic_Delay(I2C_DELAY_TM);    
          SDA_OUT_L;  /*CPU 拉低SDA ,ACK器件*/
          Iic_Delay(I2C_DELAY_TM);
          SCL_OUT_H;    /*CPU 保持 SDA 数据1us*/
          Iic_Delay(I2C_DELAY_TM);
          SCL_OUT_L;
          Iic_Delay(I2C_DELAY_TM);
        SDA_OUT_H;    /* CPU释放SDA总线 */
      }
      
      /**@brief Don't reply 
       */
      void I2c_NoAck(void)
      {
            SCL_OUT_L;
            Iic_Delay(I2C_DELAY_TM);    
            SDA_OUT_H;
            Iic_Delay(I2C_DELAY_TM);
            SCL_OUT_H;
            Iic_Delay(I2C_DELAY_TM);
            SCL_OUT_L;
            Iic_Delay(I2C_DELAY_TM);
      }

        SIMCU_IIC.h对外发布函数接口和一些宏定义 ,  函数 void IIC_confing_Pin( uint32 sda,uint32 scl, uint32 gpo);//设置 sda 和 scl 的引脚设置. 是主要调用的文件,它是基础。

    • #ifndef SIMU_IIC_H_
      #define SIMU_IIC_H_
      
      /*
      *** Define some of the things ...*/
      #define _NULL          0
      #define _TRUE          1
      #define I2C_ERROR            _NULL     //returns 
      #define I2C_FALSE     _NULL
      #define I2C_TRUE            _TRUE     
      #define I2C_BUSY            3//3     
      #define I2C_DELAY_TM     5          //slot time (4.7us)
      
      /*
      *** Define variables and structures ... */
      typedef   unsigned          char uint8;
      typedef     unsigned               int uint32;
      
      void I2c_Stop(void);
      void I2c_NoAck(void);
      void I2c_RecAck(void);
      void I2c_Reset (void);
      uint8 I2c_Start(void);
      uint8 I2c_WaitACK(void);
      uint8 I2c_RcvByte(void);
      void I2c_SendByte(uint8 c);
      uint8 Gpio_Pin_Red(uint32 pin);
      void delay_ms(uint32 volatile number_of_ms);
      void delay_us(uint32 volatile number_of_us);
      void IIC_confing_Pin( uint32 sda,uint32 scl, uint32 gpo);//设置 sda 和 scl 的引脚设置.
      
      #endif /*SIMU_IIC_H_*/

       device_i2c.c 文件是给出的write和read实例文件。

    • #include "SIMU_IIC.h"
      #include "usart.h"
      
      #define DEVICE_SLAVEADDR_W   0xA0//0x40
      #define DEVICE_SLAVEADDR_R   0xA1
      uint8_t busy;
      uint8_t DEVICE_WriteByte (uint8_t addr,uint8_t *c,uint8_t len )
      {
          uint8_t i = 0;
              lock_busy = 1;
             i = I2c_Start();
      
             if(I2C_BUSY == i )
              {
                  printf(" 
       I2C_BUSY  
      ");
                      goto DEVICE_WriteByte_FAIL; //return Fail;    
              }
              else if (I2C_ERROR == i)
              {
                  printf(" 
       I2C_ERROR  
      ");
                      goto DEVICE_WriteByte_FAIL; //return Fail;    
              }
                  
             I2c_SendByte(DEVICE_SLAVEADDR_W);  //0x40  写    
             if(!I2c_WaitACK()) {
                 I2c_Stop();
                  printf(" 
       地址失败 :%02x  !
      ",DEVICE_SLAVEADDR_W);
                 goto DEVICE_WriteByte_FAIL; //return Fail;
             }    
             I2c_SendByte(addr);        //addr
         if(!I2c_WaitACK()) {
                 I2c_Stop();
                  printf(" 
       寄存器地址错误 :%02x  !
      ",DEVICE_SLAVEADDR_W);
                 goto DEVICE_WriteByte_FAIL; //return Fail;
             }    
          for(i=0;i<len;i++){
              I2c_SendByte(*c);    
              if(!I2c_WaitACK())
              {
                      printf(" 
       写入数据失败  
      ");
              }
              c++;
          }
             I2c_Stop();
              busy = 0;
             return 1;        
      DEVICE_WriteByte_FAIL:
               I2c_Stop();
              busy = 0;
             return 0;        
      } 
      uint8 DEVICE_II_ReadByte (uint8_t addr,uint8_t * c,uint8_t len)
      {
             uint8 i;
            busy = 1;
             if(!I2c_Start())  goto DEVICE_II_ReadByte_FAIL; //return Fail;
          
             I2c_SendByte (DEVICE_SLAVEADDR_W);
             if(!I2c_WaitACK()) 
          {
                 I2c_Stop();
                 goto DEVICE_II_ReadByte_FAIL; //return Fail;
             }    
             I2c_SendByte(addr);
             I2c_WaitACK();
             I2c_Start();
             I2c_SendByte(DEVICE_SLAVEADDR_R);    
             I2c_WaitACK();
          for(i=0;i<len;i++)
          {
              *c = I2c_RcvByte();
              c++;
          }
         
             I2c_NoAck();
             I2c_Stop();
            busy = 0;
             return 1;
         
      DEVICE_II_ReadByte_FAIL:
              busy = 0;
          return 0;
      }
  • 相关阅读:
    负载平衡问题
    [SHOI2008]堵塞的交通traffic
    Bzoj3626 [LNOI2014]LCA
    [TJOI2015]旅游
    [SCOI2016]美味
    [AH/HNOI2017]单旋
    Luogu3613 睡觉困难综合征
    [SCOI2007]降雨量
    [SCOI2005]王室联邦
    HAOI2011 problem a
  • 原文地址:https://www.cnblogs.com/LVNG2018/p/10364328.html
Copyright © 2011-2022 走看看