STM32 CUBEIDE模擬IIC文件


1.配置IOC文件

SCL和SDA都為普通GPIO口 按照以下配置

 

 

2.添加IIC.h和IIC.c文件

IIC.h

/*
 * myiic.h
 *
 *  Created on: Aug 30, 2021
 *      Author: along
 */

#ifndef INC_MYIIC_H_
#define INC_MYIIC_H_
#include "main.h"
#include "stm32f4xx_hal.h"


#define FALSE 0
#define TRUE 1

#define SCL_H HAL_GPIO_WritePin(GPIOB, SCL_Pin, GPIO_PIN_SET)
#define SCL_L HAL_GPIO_WritePin(GPIOB, SCL_Pin, GPIO_PIN_RESET)

#define SDA_H HAL_GPIO_WritePin(GPIOB, SDA_Pin, GPIO_PIN_SET)
#define SDA_L HAL_GPIO_WritePin(GPIOB, SDA_Pin, GPIO_PIN_RESET)

//IO方向設置
#define SDA_IN()  my_SDA_IN()
#define SDA_OUT() my_SDA_OUT()


#define SDA_read HAL_GPIO_ReadPin(GPIOB, SDA_Pin)


//IIC所有操作函數
void IIC_Init(void);                //初始化IIC的IO口
void IIC_Start(void);                //發送IIC開始信號
void IIC_Stop(void);                  //發送IIC停止信號
void IIC_Send_Byte(uint8_t txd);            //IIC發送一個字節
uint8_t IIC_Read_Byte(unsigned char ack);//IIC讀取一個字節
uint8_t IIC_Wait_Ack(void);                 //IIC等待ACK信號
void IIC_Ack(void);                    //IIC發送ACK信號
void IIC_NAck(void);                //IIC不發送ACK信號

void IIC_Write_One_Byte(uint8_t daddr,uint8_t addr,uint8_t data);
uint8_t IIC_Read_One_Byte(uint8_t daddr,uint8_t addr);

unsigned char I2C_Readkey(unsigned char I2C_Addr);
unsigned char I2C_ReadOneByte(unsigned char I2C_Addr,unsigned char addr);
unsigned char IICwriteByte(unsigned char dev, unsigned char reg, unsigned char data);
unsigned char IICwriteCmd(unsigned char dev, unsigned char cmd);
uint8_t IICwriteBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t* data);
uint8_t IICwriteBits(uint8_t dev,uint8_t reg,uint8_t bitStart,uint8_t length,uint8_t data);
uint8_t IICwriteBit(uint8_t dev,uint8_t reg,uint8_t bitNum,uint8_t data);
uint8_t IICreadBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t *data);
#endif /* INC_MYIIC_H_ */

IIC.c

/*
 * IIC.c
 *
 *  Created on: Sep 26, 2021
 *      Author: LK
 */
#include "IIC.h"

/*
 * myiic.c
 *
 *  Created on: Aug 30, 2021
 *      Author: along
 */
#include <stdio.h>


/*******************************************************************************
* Function Name  : delay_us
* Description    : Simulation IIC Timing series delay
* Input          : None
* Output         : None
* Return         : None
****************************************************************************** */
void delay_us(uint32_t us)
{
    uint32_t i = 0;
    for(i=0;i<us;i++)
    {
        uint8_t a = 10;
        while(a--);
    }
}

void my_SDA_IN(void)
{
    GPIO_InitTypeDef GPIO_InitStruct= {0};
    GPIO_InitStruct.Pin = SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void my_SDA_OUT(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Pin = SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void IIC_Init(void)
{
    SDA_H;
    SCL_H;
}

/*******************************************************************************
* Function Name  : IIC_Start
* Description    : Master Start Simulation IIC Communication
* Input          : None
* Output         : None
* Return         : Wheather     Start
****************************************************************************** */
void IIC_Start(void)
{
    SDA_OUT();     //sda線輸出
    SDA_H;
    SCL_H;
    delay_us(5);
     SDA_L;//START:when CLK is high,DATA change form high to low
    delay_us(5);
    SCL_L;//鉗住I2C總線,准備發送或接收數據
}

/*******************************************************************************
* Function Name  : IIC_Stop
* Description    : Master Stop Simulation IIC Communication
* Input          : None
* Output         : None
* Return         : None
****************************************************************************** */
void IIC_Stop(void)
{
    SDA_OUT();//sda線輸出
    SCL_L;
    SDA_L;//STOP:when CLK is high DATA change form low to high
     delay_us(4);
    SCL_H;
    SDA_H;//發送I2C總線結束信號
    delay_us(4);
}

/*******************************************************************************
* Function Name  : IIC_Wait_Ack
* Description    : Master Reserive Slave Acknowledge Single
* Input          : None
* Output         : None
* Return         : Wheather     Reserive Slave Acknowledge Single  1,接收應答失敗;0,接收應答成功
****************************************************************************** */
uint8_t IIC_Wait_Ack(void)
{
    uint8_t ucErrTime=0;
    SDA_IN();      //SDA設置為輸入
    SDA_H;delay_us(1);
    SCL_H;delay_us(1);
    while(SDA_read)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            IIC_Stop();
            return 1;
        }
    }
    SCL_L;//時鍾輸出0
    return 0;
}

/*******************************************************************************
* Function Name  : IIC_Ack
* Description    : Master Send Acknowledge Single
* Input          : None
* Output         : None
* Return         : None
****************************************************************************** */
void IIC_Ack(void)
{
    SCL_L;
    SDA_OUT();
    SDA_L;
    delay_us(2);
    SCL_H;
    delay_us(2);
    SCL_L;
}

/*******************************************************************************
* Function Name  : IIC_NAck
* Description    : Master Send No Acknowledge Single
* Input          : None
* Output         : None
* Return         : None
****************************************************************************** */
void IIC_NAck(void)
{
    SCL_L;
    SDA_OUT();
    SDA_H;
    delay_us(2);
    SCL_H;
    delay_us(2);
    SCL_L;
}


/*******************************************************************************
* Function Name  : IIC_Send_Byte
* Description    : Master Send a Byte to Slave
* Input          : Will Send Date
* Output         : None
* Return         : None
****************************************************************************** */
void IIC_Send_Byte(uint8_t txd)
{
    uint8_t t;
    SDA_OUT();
    SCL_L;//拉低時鍾開始數據傳輸
    for(t=0;t<8;t++)
    {
        //IIC_SDA=(txd&0x80)>>7;
        if((txd&0x80)>>7)
            SDA_H;
        else
            SDA_L;
        txd<<=1;
        delay_us(2);   //對TEA5767這三個延時都是必須的
        SCL_H;
        delay_us(2);
        SCL_L;
        delay_us(2);
    }
}
/*******************************************************************************
* Function Name  : I2C_RadeByte
* Description    : Master Reserive a Byte From Slave
* Input          : ack=1時,發送ACK,ack=0,發送nACK
* Output         : None
* Return         : Date From Slave
****************************************************************************** */
uint8_t IIC_Read_Byte(unsigned char ack)
{
    unsigned char i,receive=0;
    SDA_IN();//SDA設置為輸入
    for(i=0;i<8;i++ )
    {
        SCL_L;
        delay_us(2);
        SCL_H;
        receive<<=1;
        if(SDA_read)receive++;
        delay_us(1);
    }
    if (!ack)
        IIC_NAck();//發送nACK
    else
        IIC_Ack(); //發送ACK
    return receive;
}

/**************************實現函數********************************************
*函數原型:        uint8_t IICreadBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t *data)
*功  能:        讀取指定設備 指定寄存器的 length個值
輸入    dev  目標設備地址
        reg      寄存器地址
        length 要讀的字節數
        *data  讀出的數據將要存放的指針
返回   讀出來的字節數量
*******************************************************************************/
uint8_t IICreadBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t *data){
    uint8_t count = 0;

    IIC_Start();
    IIC_Send_Byte(dev<<1);       //發送寫命令
    IIC_Wait_Ack();
    IIC_Send_Byte(reg);   //發送地址
    IIC_Wait_Ack();
    IIC_Start();
    IIC_Send_Byte((dev<<1)+1);  //進入接收模式
    IIC_Wait_Ack();

    for(count=0;count<length;count++){

         if(count!=length-1)data[count]=IIC_Read_Byte(1);  //帶ACK的讀數據
             else  data[count]=IIC_Read_Byte(0);     //最后一個字節NACK
    }
    IIC_Stop();//產生一個停止條件
    return count;
}

/**************************實現函數********************************************
*函數原型:        uint8_t IICwriteBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t* data)
*功  能:        將多個字節寫入指定設備 指定寄存器
輸入    dev  目標設備地址
        reg      寄存器地址
        length 要寫的字節數
        *data  將要寫的數據的首地址
返回   返回是否成功
*******************************************************************************/
uint8_t IICwriteBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t* data){

     uint8_t count = 0;
    IIC_Start();
    IIC_Send_Byte(dev<<1);       //發送寫命令
    IIC_Wait_Ack();
    IIC_Send_Byte(reg);   //發送地址
    IIC_Wait_Ack();
    for(count=0;count<length;count++){
        IIC_Send_Byte(data[count]);
        IIC_Wait_Ack();
 }
    IIC_Stop();//產生一個停止條件

    return 1; //status == 0;

}

 


免責聲明!

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



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