14、IIC主机控制--引脚软件模拟

这篇具有很好参考价值的文章主要介绍了14、IIC主机控制--引脚软件模拟。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

时序图:
14、IIC主机控制--引脚软件模拟
软件基于STM32 HAL库
推荐使用版本二

IIC–定时器精确延时

软件用涉及到使用定时器做精确延时,可以参考我的文章–“CubeMx 定时器高精度延时”
延时使用的文件:
tim.c

/**
  ******************************************************************************
  * @file    tim.c
  * @brief   This file provides code for the configuration
  *          of the TIM instances.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "tim.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

TIM_HandleTypeDef htim17;

/* TIM17 init function */
void MX_TIM17_Init(void)
{

  /* USER CODE BEGIN TIM17_Init 0 */

  /* USER CODE END TIM17_Init 0 */

  /* USER CODE BEGIN TIM17_Init 1 */

  /* USER CODE END TIM17_Init 1 */
  htim17.Instance = TIM17;
  htim17.Init.Prescaler = 24-1;
  htim17.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim17.Init.Period = 65535;
  htim17.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim17.Init.RepetitionCounter = 0;
  htim17.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim17) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM17_Init 2 */

  /* USER CODE END TIM17_Init 2 */

}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{

  if(tim_baseHandle->Instance==TIM17)
  {
  /* USER CODE BEGIN TIM17_MspInit 0 */

  /* USER CODE END TIM17_MspInit 0 */
    /* TIM17 clock enable */
    __HAL_RCC_TIM17_CLK_ENABLE();
  /* USER CODE BEGIN TIM17_MspInit 1 */

  /* USER CODE END TIM17_MspInit 1 */
  }
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{

  if(tim_baseHandle->Instance==TIM17)
  {
  /* USER CODE BEGIN TIM17_MspDeInit 0 */

  /* USER CODE END TIM17_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM17_CLK_DISABLE();
  /* USER CODE BEGIN TIM17_MspDeInit 1 */

  /* USER CODE END TIM17_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Delay_Driver.c

/**********************************************************************
*file:定时器高精度延时
*author:残梦
*date:2022.9.26
*note:注:用户禁止使用、更改
    该定时器配置:
	分频系数 -- 24,周期 -- 65535
	无需开启中断
**********************************************************************/
#include "Delay_Driver.h"

/******************************
@function:us延时
@param:us--待延时的时间
@return:void
@date:2022.9.26
@remark:
******************************/
void Delay_us(unsigned int us)
{
    if(!us){return;}
    us = (us > 6553)?6553:us;
    us *= 10;//基础是100ns
    _DelayTIM_Handle.Instance->CNT = 0;
	HAL_TIM_Base_Start(&_DelayTIM_Handle);
	while(_DelayTIM_Handle.Instance->CNT < us);
	HAL_TIM_Base_Stop(&_DelayTIM_Handle);
}

/******************************
@function:ms延时
@param:ms--待延时的时间
@return:void
@date:2022.9.26
@remark:
******************************/
void Delay_ms(unsigned int ms)
{
    unsigned int i = 0;
    if(!ms){return;}
    while(ms)
    {
        i = (ms < 6)?(ms):6;
        Delay_us(i*1000);
        ms -= i;
    }
}

/******************************
@function:s延时
@param:s--待延时的时间
@return:void
@date:2022.9.26
@remark:
******************************/
void Delay_s(unsigned int s)
{
    unsigned int i = 0;
    if(!s){return;}
    while(s)
    {
        i = (s < 60)?(s):60;
        Delay_ms(i*1000);
        s -= i;
    }
}

Delay_Driver.h

#ifndef _Delay_Driver_H_
#define _Delay_Driver_H_
#include "tim.h"

#define _DelayTIM_Handle htim17

extern void Delay_us(unsigned int us);
extern void Delay_ms(unsigned int ms);
extern void Delay_s(unsigned int s);

#endif

模拟IIC主机:版本一

此版本SDA引脚,SCK引脚使用宏定义
IIC_simulate.c

/**********************************************************************
*file:模拟IIC文件
*author:残梦
*date:2023.5.20
*note:V1.0
**********************************************************************/
#include "IIC_simulate.h"
#include "stdio.h"
#include "gpio.h"
#include "Delay_Driver.h"

#define _SET_PIN(GPIOx,Pin) GPIOx->BSRR = Pin //pin set 1
#define _RESET_PIN(GPIOx,Pin) GPIOx->BSRR =  ((uint32_t)Pin << 16u) //pin set 0
#define _READ_PIN(GPIOx,Pin) (GPIOx->IDR & Pin)?1:0

#define dIIC_DELAY() Delay_us(1)//IIC延时函数,设置IIC通信速度:500KHz
#define dIIC_SDA_CLOCK  __HAL_RCC_GPIOB_CLK_ENABLE()
#define dIIC_SDA_PORT   GPIOB
#define dIIC_SDA_PIN    GPIO_PIN_3
#define dIIC_SCK_CLOCK  __HAL_RCC_GPIOB_CLK_ENABLE()
#define dIIC_SCK_PORT   GPIOB
#define dIIC_SCK_PIN    GPIO_PIN_4

#define dIIC_SDA(x) if(x){_SET_PIN(dIIC_SDA_PORT,dIIC_SDA_PIN);}else _RESET_PIN(dIIC_SDA_PORT,dIIC_SDA_PIN)
#define dIIC_SCL(x) if(x){_SET_PIN(dIIC_SCK_PORT,dIIC_SCK_PIN);}else _RESET_PIN(dIIC_SCK_PORT,dIIC_SCK_PIN)

//IO 方向设置
#define dIIC_SDA_IN     {GPIOB->MODER &= ~(3<<(dIIC_SDA_PIN*2));GPIOB->MODER |= 0<<(dIIC_SDA_PIN*2);}//输入模式
#define dIIC_SDA_OUT    {GPIOB->MODER &= ~(3<<(dIIC_SDA_PIN*2));GPIOB->MODER |= 1<<(dIIC_SDA_PIN*2);}//输出模式
#define dIIC_SDA_READ   _READ_PIN(dIIC_SDA_PORT,dIIC_SDA_PIN)
#define dIIC_SCK_READ   _READ_PIN(dIIC_SCK_PORT,dIIC_SCK_PIN)

/******************************
@function:模拟IIC初始化
@param:void
@return:void
@note:
******************************/
void simIIC_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    dIIC_SDA_CLOCK;dIIC_SCK_CLOCK;

    GPIO_InitStruct.Pin = dIIC_SDA_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(dIIC_SDA_PORT, &GPIO_InitStruct);
    GPIO_InitStruct.Pin = dIIC_SCK_PIN;
    HAL_GPIO_Init(dIIC_SCK_PORT, &GPIO_InitStruct);
    dIIC_SCL(1);
    dIIC_SDA(1);
}

/******************************
@function:IIC起始信号
@param:void
@return:void
@note:
******************************/
void simIIC_Start(void)
{
    dIIC_SDA_OUT;
    dIIC_SDA(1);
    dIIC_SCL(1);
    dIIC_DELAY();

    dIIC_SDA(0);
    dIIC_DELAY();
    dIIC_SCL(0);
}

/******************************
@function:IIC结束信号
@param:void
@return:void
@note:
******************************/
void simIIC_Stop(void)
{
    dIIC_SCL(0);    
    dIIC_SDA(0);
    dIIC_DELAY();

    dIIC_SCL(1);
    dIIC_DELAY();
    dIIC_SDA(1);
    dIIC_DELAY();
}

/******************************
@function:IIC写数据(请勿其他使用)
@param: data--待发送的数据
@return:0--写成功,-1--写失败(从机地址不存在)
@note:不含IIC起始,IIC结束
******************************/
signed int simIIC_WriteOneByte(unsigned char data)
{
    unsigned char ack = 0,mask = 0;

    dIIC_SDA_OUT;
    for(mask=0x80;mask != 0;mask >>= 1)
    {
        dIIC_SDA(((mask & data) ? 1 : 0));
        dIIC_DELAY();
        dIIC_SCL(1);
        dIIC_DELAY();
        dIIC_SCL(0);
    }
    dIIC_SDA(1);
    dIIC_SDA_IN;
    dIIC_DELAY();
    dIIC_SCL(1);
    dIIC_DELAY();
    ack = dIIC_SDA_READ;
    dIIC_SCL(0);
    dIIC_SDA_OUT;

    return (ack?-1:0);
}

/******************************
@function:IIC读数据(请勿其他使用)
@param: ack:0--应答,1--不应答
@return:读取的数据
@note:不含IIC起始,IIC结束
******************************/
unsigned char simIIC_ReadOneByte(unsigned char ack)
{
    unsigned char mask = 0,data = 0;

    dIIC_SDA(1);
    dIIC_SDA_IN;
    for(mask=0x80;mask != 0;mask >>= 1)
    {
        dIIC_DELAY();
        dIIC_SCL(1);
        dIIC_DELAY();
        data |= ((dIIC_SDA_READ)?mask:0);
        dIIC_SCL(0);
    }
    dIIC_SDA_OUT;
    dIIC_SDA((ack?1:0));
    dIIC_DELAY();
    dIIC_SCL(1);
    dIIC_DELAY();
    dIIC_SCL(0);

    return data;
}

/******************************
@function:IIC写数据
@param: data--待发送的数据
        byteNum--数据字节数,不含地址字节
        address--从机地址
@return:0--写成功,-1--写失败(从机地址不存在|数据字节数0)
@note:
******************************/
signed int simIIC_Write(unsigned char *data,unsigned int byteNum,unsigned char address)
{
    unsigned int pos = 0;
    if(byteNum == 0)return -1;

    simIIC_Start();
    if(simIIC_WriteOneByte(address << 1) < 0){simIIC_Stop();return -1;}//地址访问:写
    for(pos=0;pos < byteNum;pos++){if(simIIC_WriteOneByte(data[pos]) < 0){simIIC_Stop();return -1;}}
    simIIC_Stop();
    return 0;
}

/******************************
@function:IIC读数据
@param: data--读取到的数据
        byteNum--待读取数据字节数,不含地址字节
        address--从机地址
@return:0--读成功,-1--读失败(从机地址不存在|读取错误)
@note:
******************************/
signed int simIIC_Read(unsigned char *data,unsigned int byteNum,unsigned char address)
{
    unsigned int pos = 0;
    if(byteNum == 0)return -1;
    address = (address << 1) | 0x01;

    simIIC_Start();
    if(simIIC_WriteOneByte(address) < 0){simIIC_Stop();return -1;}//地址访问:读
    for(pos=0;pos < byteNum;pos++){data[pos] = simIIC_ReadOneByte((pos == (byteNum-1))?1:0);}
    simIIC_Stop();
    return 0;
}

IIC_simulate.h

#ifndef _IIC_simulate_H_
#define _IIC_simulate_H_

void simIIC_Init(void);
void simIIC_Start(void);
void simIIC_Stop(void);
signed int simIIC_WriteOneByte(unsigned char data);
unsigned char simIIC_ReadOneByte(unsigned char ack);
signed int simIIC_Write(unsigned char *data,unsigned int byteNum,unsigned char address);
signed int simIIC_Read(unsigned char *data,unsigned int byteNum,unsigned char address);

#endif

简易示例

/******************************
@function:发送两个字节数据
@param:MSB 高8位;LSB 低8位
@return:-1--写失败,0--成功
@note:
******************************/
int SHT3x_WriteByte(uint8_t MSB,uint8_t LSB)
{
  uint8_t data[2] = {0};
  data[0] = MSB;data[1] = LSB;
  return (simIIC_Write(data,2,dSHT3X_IIC_ADDRESS) < 0) ? -1 : 0;
}

uint8_t data[6] = {0};
if(simIIC_Read(data,6,dSHT3X_IIC_ADDRESS) < 0)return -1;

已测试使用
14、IIC主机控制--引脚软件模拟

模拟IIC主机:版本二

本文件模拟IIC主机,函数使用的都是simIIC_StructDef结构体实体,方便多个外设使用
IIC_simulate.c

/**********************************************************************
*file:模拟IIC文件
*author:残梦
*date:2023.5.20
*note:V2.0
本文件模拟IIC主机,函数使用的都是simIIC_StructDef结构体实体,方便多个外设使用
eg:
#define dSHT3X_SDA_CLOCK  __HAL_RCC_GPIOB_CLK_ENABLE()
#define dSHT3X_SDA_PORT   GPIOB
#define dSHT3X_SDA_PIN    GPIO_PIN_3
#define dSHT3X_SCL_CLOCK  __HAL_RCC_GPIOB_CLK_ENABLE()
#define dSHT3X_SCL_PORT   GPIOB
#define dSHT3X_SCL_PIN    GPIO_PIN_4
#define dSHT3X_IIC_ADDRESS 0x44

void SHT3x_GPIO_EnableColock(void)//sht3x 初始化IIC的SDA|SCL的GPIO时钟使能函数
{
  dSHT3X_SDA_CLOCK;
  dSHT3X_SCL_CLOCK;
}

simIIC_StructDef SHT3X_IIC;//初始化IIC结构体变量
SHT3X_IIC.SDA_Pin = dSHT3X_SDA_PIN;
SHT3X_IIC.SCL_Pin = dSHT3X_SCL_PIN;
SHT3X_IIC.SDA_GPIO = dSHT3X_SDA_PORT;
SHT3X_IIC.SCL_GPIO = dSHT3X_SCL_PORT;
SHT3X_IIC.GPIO_EnableColock = &SHT3x_GPIO_EnableColock;
SHT3X_IIC.DelayMicrosecond = 1;//IIC速度:500KHz
SHT3X_IIC.Delay_us = &Delay_us;//外部us延时精确函数
simIIC_Init(SHT3X_IIC);//初始化IIC

uint8_t data[6] = {0};
if(simIIC_Read(SHT3X_IIC,data,6,dSHT3X_IIC_ADDRESS) < 0)return -1;//读取6个字节的数据
if(simIIC_Write(SHT3X_IIC,data,2,dSHT3X_IIC_ADDRESS) < 0)return -1;//写入6个字节的数据
**********************************************************************/
#include "IIC_simulate.h"

#define dxSET_PIN(GPIOx,Pin) GPIOx->BSRR = Pin //pin set 1
#define dxRESET_PIN(GPIOx,Pin) GPIOx->BSRR =  ((uint32_t)Pin << 16u) //pin set 0
#define dxREAD_PIN(GPIOx,Pin) (GPIOx->IDR & Pin)?1:0
#define dxSET_LEVEL_PIN(gpio,pin,level) if(level){dxSET_PIN(gpio,pin);}else dxRESET_PIN(gpio,pin)

//IO 方向设置
#define dxPIN_MODE_IN(gpio,pin)     {gpio->MODER &= ~(3<<(pin*2));gpio->MODER |= 0<<(pin*2);}//输入模式
#define dxPIN_MODE_OUT(gpio,pin)    {gpio->MODER &= ~(3<<(pin*2));gpio->MODER |= 1<<(pin*2);}//输出模式

#define dIIC_SCL(simIIC,x)      dxSET_LEVEL_PIN(simIIC.SCL_GPIO,simIIC.SCL_Pin,x)
#define dIIC_SDA(simIIC,x)      dxSET_LEVEL_PIN(simIIC.SDA_GPIO,simIIC.SDA_Pin,x)
#define dIIC_SDA_IN(simIIC)     dxPIN_MODE_IN(simIIC.SDA_GPIO,simIIC.SDA_Pin)
#define dIIC_SDA_OUT(simIIC)    dxPIN_MODE_OUT(simIIC.SDA_GPIO,simIIC.SDA_Pin)
#define dIIC_SDA_READ(simIIC)   dxREAD_PIN(simIIC.SDA_GPIO,simIIC.SDA_Pin)

static void simIIC_DelayUs(simIIC_StructDef simIIC);

/******************************
@function:模拟IIC延时函数
@param:
@return:void
@note:
******************************/
static void simIIC_DelayUs(simIIC_StructDef simIIC)
{
    if(simIIC.DelayMicrosecond == 0)return;
    simIIC.Delay_us(simIIC.DelayMicrosecond);
}

/******************************
@function:模拟IIC初始化
@param:simIIC--待初始化的simIIC_StructDef
@return:void
@note:
******************************/
void simIIC_Init(simIIC_StructDef simIIC)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    simIIC.GPIO_EnableColock();
    GPIO_InitStruct.Pin = simIIC.SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(simIIC.SDA_GPIO, &GPIO_InitStruct);
    GPIO_InitStruct.Pin = simIIC.SCL_Pin;
    HAL_GPIO_Init(simIIC.SCL_GPIO, &GPIO_InitStruct);
    dIIC_SCL(simIIC,1);
    dIIC_SDA(simIIC,1);
}

/******************************
@function:IIC起始信号
@param:simIIC--待初始化的simIIC_StructDef
@return:void
@note:
******************************/
void simIIC_Start(simIIC_StructDef simIIC)
{
    dIIC_SDA_OUT(simIIC);
    dIIC_SDA(simIIC,1);
    dIIC_SCL(simIIC,1);
    simIIC_DelayUs(simIIC);
    dIIC_SDA(simIIC,0);
    simIIC_DelayUs(simIIC);
    dIIC_SCL(simIIC,0);
}

/******************************
@function:IIC结束信号
@param:simIIC--待初始化的simIIC_StructDef
@return:void
@note:
******************************/
void simIIC_Stop(simIIC_StructDef simIIC)
{
    dIIC_SCL(simIIC,0);    
    dIIC_SDA(simIIC,0);
    simIIC_DelayUs(simIIC);

    dIIC_SCL(simIIC,1);
    simIIC_DelayUs(simIIC);
    dIIC_SDA(simIIC,1);
    simIIC_DelayUs(simIIC);
}

/******************************
@function:IIC写数据(请勿其他使用)
@param: data--待发送的数据
@return:0--写成功,-1--写失败(从机地址不存在)
@note:不含IIC起始,IIC结束
******************************/
signed int simIIC_WriteOneByte(simIIC_StructDef simIIC,unsigned char data)
{
    unsigned char ack = 0,mask = 0;

    dIIC_SDA_OUT(simIIC);
    for(mask=0x80;mask != 0;mask >>= 1)
    {
        dIIC_SDA(simIIC,((mask & data) ? 1 : 0));
        simIIC_DelayUs(simIIC);
        dIIC_SCL(simIIC,1);
        simIIC_DelayUs(simIIC);
        dIIC_SCL(simIIC,0);
    }
    dIIC_SDA(simIIC,1);
    dIIC_SDA_IN(simIIC);
    simIIC_DelayUs(simIIC);
    dIIC_SCL(simIIC,1);
    simIIC_DelayUs(simIIC);
    ack = dIIC_SDA_READ(simIIC);
    dIIC_SCL(simIIC,0);
    dIIC_SDA_OUT(simIIC);

    return (ack?-1:0);
}

/******************************
@function:IIC读数据(请勿其他使用)
@param: ack:0--应答,1--不应答
@return:读取的数据
@note:不含IIC起始,IIC结束
******************************/
unsigned char simIIC_ReadOneByte(simIIC_StructDef simIIC,simIIC_xACK_EnumDef ack)
{
    unsigned char mask = 0,data = 0;

    dIIC_SDA(simIIC,1);
    dIIC_SDA_IN(simIIC);
    for(mask=0x80;mask != 0;mask >>= 1)
    {
        simIIC_DelayUs(simIIC);
        dIIC_SCL(simIIC,1);
        simIIC_DelayUs(simIIC);
        data |= ((dIIC_SDA_READ(simIIC))?mask:0);
        dIIC_SCL(simIIC,0);
    }
    dIIC_SDA_OUT(simIIC);
    dIIC_SDA(simIIC,ack);
    simIIC_DelayUs(simIIC);
    dIIC_SCL(simIIC,1);
    simIIC_DelayUs(simIIC);
    dIIC_SCL(simIIC,0);

    return data;
}

/******************************
@function:IIC写数据
@param: data--待发送的数据
        byteNum--数据字节数,不含地址字节
        address--从机地址
@return:0--写成功,-1--写失败(从机地址不存在|数据字节数0)
@note:
******************************/
signed int simIIC_Write(simIIC_StructDef simIIC,unsigned char *data,unsigned int byteNum,unsigned char address)
{
    unsigned int pos = 0;
    if(byteNum == 0)return -1;

    simIIC_Start(simIIC);
    if(simIIC_WriteOneByte(simIIC,address << 1) < 0){simIIC_Stop(simIIC);return -1;}//地址访问:写
    for(pos=0;pos < byteNum;pos++){if(simIIC_WriteOneByte(simIIC,data[pos]) < 0){simIIC_Stop(simIIC);return -1;}}
    simIIC_Stop(simIIC);
    return 0;
}

/******************************
@function:IIC读数据
@param: data--读取到的数据
        byteNum--待读取数据字节数,不含地址字节
        address--从机地址
@return:0--读成功,-1--读失败(从机地址不存在|读取错误)
@note:
******************************/
signed int simIIC_Read(simIIC_StructDef simIIC,unsigned char *data,unsigned int byteNum,unsigned char address)
{
    unsigned int pos = 0;
    if(byteNum == 0)return -1;
    address = (address << 1) | 0x01;

    simIIC_Start(simIIC);
    if(simIIC_WriteOneByte(simIIC,address) < 0){simIIC_Stop(simIIC);return -1;}//地址访问:读
    for(pos=0;pos < byteNum;pos++){data[pos] = simIIC_ReadOneByte(simIIC,(pos == (byteNum-1))?simIIC_NACK:simIIC_ACK);}
    simIIC_Stop(simIIC);
    return 0;
}

IIC_simulate.h

#ifndef _IIC_simulate_H_
#define _IIC_simulate_H_
#include "gpio.h"

typedef struct
{
    uint32_t SDA_Pin;//SDA引脚
    uint32_t SCL_Pin;//SCL引脚
    GPIO_TypeDef  *SDA_GPIO;//SDA端口
    GPIO_TypeDef  *SCL_GPIO;//SCL端口
    void (*GPIO_EnableColock)(void);//使能SDA、SCL的GPIO时钟函数,用户定义:eg:void SHT3x_GPIO_EnableColock(void)
    unsigned short int DelayMicrosecond;//IIC延时时间,频率接近1/(2*DelayMicrosecond) * 1000000;为0时不予延时;注意IIC实际延时会稍大于此时间,因为还有引脚翻转时间消耗
    void (*Delay_us)(unsigned int us);//微秒延时精确函数,用户定义:eg:void Delay_us(unsigned int us)
}simIIC_StructDef;

typedef enum
{
    simIIC_ACK = 0, //IIC应答
    simIIC_NACK = 1 //IIC不应答
}simIIC_xACK_EnumDef;

void simIIC_Init(simIIC_StructDef simIIC);
void simIIC_Start(simIIC_StructDef simIIC);
void simIIC_Stop(simIIC_StructDef simIIC);
signed int simIIC_WriteOneByte(simIIC_StructDef simIIC,unsigned char data);
unsigned char simIIC_ReadOneByte(simIIC_StructDef simIIC,simIIC_xACK_EnumDef ack);
signed int simIIC_Write(simIIC_StructDef simIIC,unsigned char *data,unsigned int byteNum,unsigned char address);
signed int simIIC_Read(simIIC_StructDef simIIC,unsigned char *data,unsigned int byteNum,unsigned char address);

#endif

示例:

eg:
#define dSHT3X_SDA_CLOCK  __HAL_RCC_GPIOB_CLK_ENABLE()
#define dSHT3X_SDA_PORT   GPIOB
#define dSHT3X_SDA_PIN    GPIO_PIN_3
#define dSHT3X_SCL_CLOCK  __HAL_RCC_GPIOB_CLK_ENABLE()
#define dSHT3X_SCL_PORT   GPIOB
#define dSHT3X_SCL_PIN    GPIO_PIN_4
#define dSHT3X_IIC_ADDRESS 0x44

void SHT3x_GPIO_EnableColock(void)//sht3x 初始化IIC的SDA|SCL的GPIO时钟使能函数
{
  dSHT3X_SDA_CLOCK;
  dSHT3X_SCL_CLOCK;
}

simIIC_StructDef SHT3X_IIC;//初始化IIC结构体变量
SHT3X_IIC.SDA_Pin = dSHT3X_SDA_PIN;
SHT3X_IIC.SCL_Pin = dSHT3X_SCL_PIN;
SHT3X_IIC.SDA_GPIO = dSHT3X_SDA_PORT;
SHT3X_IIC.SCL_GPIO = dSHT3X_SCL_PORT;
SHT3X_IIC.GPIO_EnableColock = &SHT3x_GPIO_EnableColock;
SHT3X_IIC.DelayMicrosecond = 1;//IIC速度:500KHz
SHT3X_IIC.Delay_us = &Delay_us;//外部us延时精确函数
simIIC_Init(SHT3X_IIC);//初始化IIC

uint8_t data[6] = {0};
if(simIIC_Read(SHT3X_IIC,data,6,dSHT3X_IIC_ADDRESS) < 0)return -1;//读取6个字节的数据
if(simIIC_Write(SHT3X_IIC,data,2,dSHT3X_IIC_ADDRESS) < 0)return -1;//写入6个字节的数据

已经测试使用
14、IIC主机控制--引脚软件模拟文章来源地址https://www.toymoban.com/news/detail-457505.html

到了这里,关于14、IIC主机控制--引脚软件模拟的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32单片机初学4-IIC通信(软件模拟)

    IIC ( Inter-Integrated Circuit )又称I2C(习惯读“I方C”),是 IIC Bus简称,中文名为 集成电路总线 ,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。适用于IC间的短距离数据传输。 最初的IIC通信速

    2024年02月05日
    浏览(52)
  • stm32使用模拟IIC控制四针0.96寸OLED

    STM32系列模拟IIC控制0.96寸OLED方法 首先说为什么要采用模拟IIC来控制OLED,采用STM32系列单片机硬件IIC时有可能出现程序死掉的情况,我遇到的情况是与程序while的使用有关(听说原因很随机)。这个时候我们可以采用两个GPIO来模拟IIC通信控制OLED屏幕。顺带说一下OLED的使用原理

    2024年02月14日
    浏览(50)
  • STM32之模拟IIC总线控制SHT20温湿度芯片

    一、IIC总线概述 1、IIC总线介绍 I2C (Inter-Integrated Circuit)总线产生于在80年代, 由PHILIPS公司开发的 两线式串行总线 ,用于连接微控制器及其外围设备, 最初为音频和视频设备开发。I2C总线两线制包括: 串行数据 SDA (Serial Data)、 串行时钟 SCL (Serial Clock)。时钟线必须由主

    2024年02月02日
    浏览(32)
  • STM32 软件IIC 控制OLED 显示屏

    需要看原理图了

    2024年02月09日
    浏览(40)
  • GPIO模拟时序控制外设4——红外发射管

    上一篇介绍了使用GPIO模拟时序实现I2C协议的功能,本文继续使用GPIO模拟的方式来实现一个平时生活中常用的模块——红外发射管的驱动,红外在家电的应用中十分广泛,空调、电视、投影等都是通过红外遥控来实现的。 红外发射管实物就是下图中左边的红框内的器件,右侧

    2024年02月11日
    浏览(35)
  • GPIO模拟时序控制外设1——WS2812B

    上一篇文章中介绍了整个板子的最基本功能模块——使用GPIO的通用输入输出实现简单的按键输入以及推挽输出控制的功能。本文深入一步,在只使用GPIO的输入输出功能的基础上,通过查看对应模块的芯片手册,模拟其对应的通信时序来驱动对应的模块。 首先来个网红模块—

    2024年02月12日
    浏览(35)
  • STM32 Cube MX 之hal库软件模拟IIC 可直接移植使用

    此为软件模拟IIC,可以直接移植到HAL库使用。.h文件需要自己做函数声明这里就不再放出,如有问题大家可以讨论。 使用的时候只需要更改SDA 和SCL引脚的宏定义就可以移植使用,当然IIC协议其实就是根据IIC的时序图编写代码,主要内容就是包括开始信号,停止信号以及发送数

    2024年02月15日
    浏览(50)
  • ARM开发之基于IIC协议的TM1650驱动实现(模拟IIC实现)

    目录 一、内存映射 1、什么是内存映射?为什么要内存映射? 2、gec6818如何进行内存映射?(相关的函数) 3、内存映射代码 : 二、模拟IIC的底层代码实现 1、配置输入输出方向 2、拉高拉低引脚 3、获得总线传回的数据 4、协议的实现 三、TM1650的使用 1、TM1650简介 2、TM1650怎

    2024年02月12日
    浏览(35)
  • STM32F103模拟IIC控制4针0.96寸OLED显示屏

    OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。OLED由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为

    2023年04月24日
    浏览(45)
  • STM32软件模拟实现IIC写入和读取AT24C02(STM32CubeMx配置)

    IIC:Inter Integrated Circuit,集成电路总线,是一种 同步 串行 半双工 通信总线。 在使用IIC时分为硬件IIC以及软件IIC,下图为两者的区别: 在使用IIC前先来了解一下IIC总线结构图,即下图: 从图中可以看出IIC有两个双向信号线,一根是数据线SDA,一根是时钟线SCL,并且都接上拉

    2024年02月04日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包