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檢測是否發送成功!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM