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;

}

 

posted @ 2021-10-01 10:11  Lxk-  阅读(582)  评论(0编辑  收藏  举报