zoukankan      html  css  js  c++  java
  • STM32 IIC协议 HAL库

    IIC是多主、多从、单工IIC的串行总线,传输仅需两根线,SDA(数据线)、SCL(时钟线)

    IIC空闲时SDA和SCL都处于高电平状态(两根线一般情况均接上拉电阻)

    IIC传输数据的模式为每传输8位后,要通过一个ACK位进行相互确认。

    个人认为SCL产生上升沿后,设备开始检测SDA的电平,当SDA下降,SCL为高,表示开始工作,以此作为当前传输的数据,SCL的下降沿是作为SDA信息可调整的信号,在之后就能进行SDA的电平调整。

    IIC有三种速率选择:

    普通模式(100kbps)

    快速模式(400kbps)

    高速模式(3.4Mbps)

    具体选用哪种速率要看对应IIC设备数据手册能支持的最大速率是多少,并通过更改时序中的延时时间进行切换。 IIC驱动代码基本上通用于任何IIC设备上。实现包括IIC 的初始化(IO 口)、 IIC 开始、 IIC 结束、 ACK、 IIC读写等功能 IIC 的初始化(IO 口)、 IIC 开始、 IIC 结束、 ACK、 IIC读写等功能 。

    IIC初始化代码:

    #define IIC_SCL_H   HAL_GPIO_WritePin(GPIOC,GPIO_PIN_12,GPIO_PIN_SET) //SCL H
    #define IIC_SCL_L   HAL_GPIO_WritePin(GPIOC,GPIO_PIN_12,GPIO_PIN_RESET) //SCL H
    #define IIC_SDA_H    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_11,GPIO_PIN_SET) //SDA_H
    #define IIC_SDA_L      HAL_GPIO_WritePin(GPIOC,GPIO_PIN_11,GPIO_PIN_RESET) //SDA_L
    #define READ_SDA      HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_11)  //输入SDA
    View Code

    上面为.h中的SDA、SCL的宏定义

    void IIC_Init(void)
        {
        GPIO_InitTypeDef GPIO_Initure;
        
        __HAL_RCC_GPIOC_CLK_ENABLE();   //使能GPIOC时钟
        
        //PC11,12初始化设置
        GPIO_Initure.Pin=GPIO_PIN_11|GPIO_PIN_12;
        GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
        GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
        GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;     //高速
        HAL_GPIO_Init(GPIOC,&GPIO_Initure);
        
            GPIO_Initure.Pin = GPIO_PIN_10;
            GPIO_Initure.Mode=GPIO_MODE_INPUT;  
        GPIO_Initure.Pull=GPIO_NOPULL;          
        GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;     //高速
        HAL_GPIO_Init(GPIOC,&GPIO_Initure);
            
        IIC_SDA_H;
        IIC_SCL_H;  
            delay_nms(5);
    }
    View Code

    记得初始化时把SDA和SCL拉高

    IIC开始:

    void IIC_Start(void)
    {
        IIC_SDA_H;            
        IIC_SCL_H;
        delay_nns(5);
         IIC_SDA_L;//START:when CLK is high,DATA change form high to low 
        delay_nns(5);
        IIC_SCL_L;//钳住I2C总线,准备发送或接收数据 
        delay_nns(5);
    }    

    IIC结束:

    void IIC_Stop(void)
    {
        IIC_SDA_L;//STOP:when CLK is high DATA change form low to high
         delay_nns(5);
        IIC_SCL_H; 
            delay_nns(5);
        IIC_SDA_H;//发送I2C总线结束信号
        delay_nns(5);                                   
    }

    发送ACK:

    void IIC_Ack(void)
    {
        IIC_SDA_L;
        delay_nns(5);
        IIC_SCL_H;
        delay_nns(5);
        IIC_SCL_L;
        delay_nns(5);
        IIC_SDA_H;
    }

    不发送NACK:

    void IIC_NAck(void)
    {
        IIC_SDA_H;
        delay_nns(5);
        IIC_SCL_H;
    delay_nns(5);
        IIC_SCL_L;
        delay_nns(5);
        IIC_SDA_L;
    }        

    等待ACK:

    uint8_t IIC_Wait_Ack(void)
    {
        uint8_t ucErrTime=0;
        //SDA_IN();      //SDA设置为输入  
        IIC_SDA_H;
        delay_nns(5);       
        IIC_SCL_H;
        delay_nns(5);          
        
        while(READ_SDA)
        {
            ucErrTime++;
            if(ucErrTime>250)
            {
                IIC_Stop();
                return 1;
            }
        }
        IIC_SCL_L;//时钟输出0        
        return 0;  
    }

    发送字节:

    void IIC_Send_Byte(uint8_t txd)
    {                              
       IIC_SCL_L;//拉低时钟开始数据传输
       for(uint8_t i = 0;i < 8;i++)
        {              
            if(txd&0x80)
                        IIC_SDA_H;
                    else
                        IIC_SDA_L;                
            txd<<=1;       
                    
            IIC_SCL_H;
            delay_nns(5);
            IIC_SCL_L;
            delay_nns(5);
        }            
        //    IIC_SDA_H;
        //    IIC_SCL_H;            //当去掉wait_ack时的时候添加
        //    delay_nns(5);
            //IIC_SCL_L;
    } 

    读取字节:

    uint8_t IIC_Read_Byte(unsigned char ack)
    {
          uint8_t TData=0,i;
        for(i=0;i<8;i++)
        {
            IIC_SCL_H;
            delay_nns(5);
            TData=TData<<1;
            //if(GPIOB->IDR& GPIO_IDR_IDR7)        //判断SDA是否为高
                if(SDA_READ)
            {
                TData|=0x01;
            }
            IIC_SCL_L;
            delay_nns(5);
        }
            if(!ack)
                IIC_NAck();
            else
                IIC_Ack();
    //    IIC_SCL_L;
    //    delay_nns(5);
    //    IIC_SDA_L;
    //    delay_nns(5);                //ACK
    //    IIC_SCL_H;
    //    delay_nns(5);
    //    IIC_SCL_L;
    //    delay_nns(5);
    //    IIC_SDA_H;
        return TData;
    }

    以上为IIC通用代码,但是注意每次发完数据之后需要 wait_ACK检测是否发送成功!

  • 相关阅读:
    优酷菜单
    下拉列表
    图片循环滑动
    android 官网处理图片 代码
    获取手机内存可用内存单个APP运行内存
    Android中View绘制流程以及invalidate()等相关方法分析
    Andriod中绘(画)图----Canvas的使用详解
    Android中获取应用程序(包)的信息----PackageManager
    android桌面小火箭升空动画
    3、自定义控件-----刮刮奖
  • 原文地址:https://www.cnblogs.com/zjx123/p/12785182.html
Copyright © 2011-2022 走看看