zoukankan      html  css  js  c++  java
  • STM32 软件模拟 IIC 代码,标准库、HAL库可用

     1 #ifndef _IIC_H
     2 #define _IIC_H
     3 
     4 #include "stdio.h"    
     5 #include "stm32f1xx_hal.h"
     6 
     7 
     8 /* 定义控制 SDA SCL 的宏 标准库版
     9 #define I2C_SDA_UP        GPIO_SetBits  (GPIOC,GPIO_PIN_8)    //SDA高电平
    10 #define I2C_SDA_LOW        GPIO_ResetBits(GPIOC,GPIO_PIN_8)    //SDA低电平
    11 #define I2C_SCL_UP        GPIO_SetBits  (GPIOC,GPIO_PIN_9)    //SCL高电平
    12 #define I2C_SCL_LOW        GPIO_ResetBits(GPIOC,GPIO_PIN_9)    //SCL低电平
    13 */
    14 
    15 
    16 /* 定义控制 SDA SCL 的宏 HAL库版    */
    17 
    18 #define I2C_SDA_UP        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET)                //SDA高电平
    19 #define I2C_SDA_LOW        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET)            //SDA低电平
    20 #define I2C_SCL_UP        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_SET)              //SCL高电平
    21 #define I2C_SCL_LOW        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_RESET)            //SCL低电平
    22 
    23 
    24 
    25 /* 获取 SDA SCL 引脚状态,标准库版也是用相同逻辑    */
    26 
    27 #define I2C_SDA        HAL_GPIO_ReadPin(GPIOC ,GPIO_PIN_8)        //获取SDA引脚状态
    28 #define I2C_SCL        HAL_GPIO_ReadPin(GPIOC ,GPIO_PIN_9)        //获取SCL引脚状态
    29 
    30 
    31 void         iic_stare(void);                    //*    开始信号    
    32 void         i2c_ack(void);                        //*    应答信号    
    33 void         I2C_No_ack(void);                    //*    非应答信号    
    34 void         i2c_stop(void);                        //*    停止信号    
    35 char         i2c_wit_ack(void);                //*    等待应答
    36 void         i2c_send(uint8_t dat);        //* 发送数据
    37 uint8_t i2c_read(void);                        //* 接收数据
    38 
    39 void SDA_OUT(void);                //*    SDA 设置为输出    
    40 void SDA_IN(void);                //*    SDA 设置为输入    
    41 
    42 void delay_us(uint32_t i);        //*延时    
    43 
    44 #endif
    /*****************************************************************************
    *                                                                                                                                                         *
    *                        File:    软件模拟IIC, HAL库版本,标准库也                                                     *
    *                                    可用,只需要做一些相对应修改即可                                                     *
    *                                                                                                                                                         *
    *****************************************************************************/
    
    #include "iic.h"
    
    
    /*******************************************************************************
    * 函 数 名         : i2c_stare
    * 函数功能         : iic开始信号,SCL高电平时,SDA出现一个下跳沿表示启动信号 
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void i2c_stare(void)
    {
        SDA_OUT();  
        I2C_SDA_UP;
        I2C_SCL_UP;
        delay_us(4);
         I2C_SDA_LOW;        //启动开始信号
        delay_us(4);
        I2C_SCL_LOW;      //钳住I2C总线,准备发送或接收数据
    }
    
    
    /*******************************************************************************
    * 函 数 名         : i2c_stop
    * 函数功能         : iic停止信号,SCL高电平时,SDA出现一个上跳沿表示停止信号
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void i2c_stop(void)
    {
        SDA_OUT();            //sda线输出
        I2C_SDA_LOW;         //发送结束条件的数据信号
        I2C_SCL_UP;
        delay_us(4);         //结束条件建立时间大于4μ
        I2C_SDA_UP;         //发送I2C总线结束信号
        delay_us(4);
        I2C_SCL_LOW; 
    }
    
    
    /*******************************************************************************
    * 函 数 名         : i2c_send
    * 函数功能         : iic发送数据
    * 输    入         : uint8_t dat,要发送的数据
    * 输    出         : 无
    *******************************************************************************/
    void i2c_send(uint8_t dat)
    {
    
         unsigned char temp;
         SDA_OUT();
       for(temp=0x80;temp!=0;temp>>=1)
       {
           if((temp & dat)== 0)
           {
              I2C_SDA_LOW;
           }
           else
           {
              I2C_SDA_UP;
           }
           delay_us(1);
           I2C_SCL_UP;
           delay_us(4);
           I2C_SCL_LOW;
       }
    }
    
    
    /*******************************************************************************
    * 函 数 名         : i2c_read
    * 函数功能         : iic接收数据
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    uint8_t i2c_read(void)
    {
       unsigned char temp;
       unsigned char dat;
       I2C_SDA_UP;                     //释放总线准备接收
         SDA_IN();
       for(temp=0x80;temp!=0;temp>>=1)
       {
          delay_us(1);
          I2C_SCL_UP;
          if(I2C_SDA==1)
          {
             dat|=temp;
          }
          else
          {
             dat&=~temp;
          }
          I2C_SCL_LOW;
       }
       return dat;
    }
    
    
    /*******************************************************************************
    * 函 数 名         : i2c_wit_ack
    * 函数功能         : iic等待应答
    * 输    入         : 无
    * 输    出         : 0/1,返回1表示无应答信号,返回0表示应答
    *******************************************************************************/
    char i2c_wit_ack(void)
    {
        
        uint8_t con=0;
        
      I2C_SDA_UP;       //释放数据线,准备接收应答
      delay_us(1);
        I2C_SCL_UP;                //CPU驱动SCL = 1, 此时器件会返回ACK应答
        SDA_IN(); 
        delay_us(1);
        
      while( I2C_SDA )    //CPU读取SDA口线状态
      {
            con++;
            if(con>255)
            {
                i2c_stop();
          return 1;     //无应答信号
            }
      }
    
      I2C_SCL_LOW; 
      delay_us(1);
      return 0;             //有应答
    }
    
    /*******************************************************************************
    * 函 数 名         : i2c_ack
    * 函数功能         : iic应答信号
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void i2c_ack(void)
    {
        SDA_OUT();
        I2C_SDA_LOW;
        delay_us(1);
        I2C_SCL_UP;            //CPU产生1个时钟
        delay_us(4);         //时钟低电平周期大于4μ
        I2C_SCL_LOW;         //清时钟线,钳住I2C总线以便继续接收
        delay_us(4);
        I2C_SDA_UP;            //CPU释放SDA总线
    }
    
    
    /*******************************************************************************
    * 函 数 名         : I2C_No_ack
    * 函数功能         : iic非应答信号
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void I2C_No_ack(void)
    {
         SDA_OUT();
       I2C_SDA_UP;
         delay_us(1);
       I2C_SCL_UP;
       delay_us(4);
       I2C_SCL_LOW; 
       delay_us(4);
    }
    
    
    /*******************************************************************************
    * 函 数 名         : SDA_OUT
    * 函数功能         : SDA 设置为输出
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void SDA_OUT(void)
    { 
        
    /*    标准库使用,修改端口引脚可用
      GPIO_InitTypeDef GPIO_InitTypeStruct;  
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  
      GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_Out_PP;  
      GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_7;  
      GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;  
      GPIO_Init(GPIOB,&GPIO_InitTypeStruct); 
    */    
        
        /*    HAL库使用,HAL库注意要把初始化函数的静态标记去掉    */
        GPIO_InitTypeDef GPIO_InitStruct;
      GPIO_InitStruct.Pin = SDA_Pin;                    //使用STM3cubemx是定义好的SDA_Pin为GPIO_PIN_8的标签
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    }
    
    
    /*******************************************************************************
    * 函 数 名         : SDA_IN
    * 函数功能         : SDA 设置为输入
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void SDA_IN(void)  
    {
      
    /*    标准库使用,修改端口引脚可用
      GPIO_InitTypeDef GPIO_InitTypeStruct;  
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);       
      GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;  
      GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_7;  
      GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;  
      GPIO_Init(GPIOB,&GPIO_InitTypeStruct);  
    */    
        
        /*    HAL库使用, HAL库注意要把初始化函数的静态标记去掉    */
        GPIO_InitTypeDef GPIO_InitStruct;
        GPIO_InitStruct.Pin = SDA_Pin    ;                    //使用STM3cubemx是定义好的SDA_Pin为GPIO_PIN_8的标签
      GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    } 
    
    
    /*******************************************************************************
    * 函 数 名         : delay_us
    * 函数功能         : 延时函数,延时us
    * 输    入         : i
    * 输    出         : 无
    *******************************************************************************/
    void delay_us(uint32_t i)
    {
        uint32_t temp;
        SysTick->LOAD=9*i;                     //设置重装数值, 72MHZ时
        SysTick->CTRL=0X01;                 //使能,减到零是无动作,采用外部时钟源
        SysTick->VAL=0;                 //清零计数器
        
        do
        {
            temp=SysTick->CTRL;                            //读取当前倒计数值
        }
        while((temp&0x01)&&(!(temp&(1<<16))));     //等待时间到达
            
        SysTick->CTRL=0;         //关闭计数器
        SysTick->VAL=0;        //清空计数器
    }

    该代码,标准库可用,HAL库也可用,只需要代码做一些修改即可!

  • 相关阅读:
    洛谷P1170 兔八哥与猎人 欧拉函数的应用
    洛谷P1056 排座椅
    洛谷P1177 【模板】快速排序
    洛谷1059 明明的随机数
    洛谷P1372 又是毕业季I
    洛谷P1042 乒乓球
    洛谷P1086 花生采摘
    洛谷P1031 均分纸牌
    洛谷P1068 分数线划定
    洛谷P1781 宇宙总统
  • 原文地址:https://www.cnblogs.com/xingboy/p/9585350.html
Copyright © 2011-2022 走看看