注:以下文件进行移植,直接修改IIC.H的引脚,就可以使用了
IIC.C
/*
* softiic.c
*
* Created on: 2024年6月12日
* Author: Administrator
*/
#include "softiic.h"
uint8_t send_data[]={0x01,0x02,0x03,0x04,0x05,0x06};
uint8_t receive_data[]={0x00,0x00,0x00,0x00,0x00,0x00};
uint32_t delay1us;
/**
* @brief: 1us延时
* @param {uint32_t} delay_1us
* @return {*}
*/
void delay_1us(uint32_t delay_1us)
{
__IO uint32_t Delay = delay_1us * 168 / 8;//(SystemCoreClock / 8U / 1000000U)
//见stm32f1xx_hal_rcc.c -- static void RCC_Delay(uint32_t mdelay)
do
{
__NOP();
}
while (Delay --);
}
/**
* @brief: IIC延时时间
* @return {*}
*/
void analog_i2c_delay(void)
{
delay_1us(5);
}
/**
* @brief: 软件模拟I2C初始化
* @return {*}
*/
void bsp_analog_i2c_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/*Configure GPIO pins : PD6 */
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pins : PC1 */
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
i2c_sda_high();
i2c_scl_high();
// bsp_analog_i2c_stop();
}
/**
* @brief: I2C 开始,SCL为高电平的时候SDA产生一个下降沿信号
* @return {*}
*/
void bsp_analog_i2c_start(void)
{
/* _____
*SDA \_____________
* __________
*SCL \________
*/
SDA_OUT();
i2c_sda_high();
i2c_scl_high();
analog_i2c_delay();
i2c_sda_low();
analog_i2c_delay();
i2c_scl_low();
analog_i2c_delay();
}
/**
* @brief: I2C 停止,SCL为高电平的时候SDA产生一个上升沿信号
* @return {*}
*/
void bsp_analog_i2c_stop(void)
{
/* _______
*SDA __________/
* ____________
*SCL _____/
*/
SDA_OUT();
i2c_sda_low();
i2c_scl_high();
analog_i2c_delay();
i2c_sda_high();
analog_i2c_delay();
}
/**
* @brief: I2C 等待响应
* @return {*}
*/
uint8_t bsp_analog_i2c_wait_ack(void)
{
uint32_t timeout = 0;
i2c_sda_high();
SDA_IN();
analog_i2c_delay();
i2c_scl_high();
analog_i2c_delay();
while(i2c_read_sda())
{
timeout++;
if(timeout > 255)
{
bsp_analog_i2c_stop();
return 1;
}
//printf("timeout=%d\r\n",timeout);
}
i2c_scl_low();
analog_i2c_delay();
return 0;
}
/**
* @brief: I2C 响应
* @return {*}
*/
void bsp_analog_i2c_ack(void)
{
/* ____
*SCL ______/ \______
* ____ _____
*SDA \_______/
*/
SDA_OUT();
i2c_sda_low();
analog_i2c_delay();
i2c_scl_high();
analog_i2c_delay();
i2c_scl_low();
analog_i2c_delay();
i2c_sda_high();
}
/**
* @brief: I2C 不响应
* @return {*}
*/
void bsp_analog_i2c_nack(void)
{
/* ____
*SCL ______/ \______
* __________________
*SDA
*/
SDA_OUT();
i2c_sda_high();
analog_i2c_delay();
i2c_scl_high();
analog_i2c_delay();
i2c_scl_low();
analog_i2c_delay();
}
/**
* @brief: I2C 发送一个字节数据
* @param {uint8_t} data
* @return {*}
*/
void bsp_analog_i2c_send_byte(uint8_t data)
{
uint8_t i;
SDA_OUT();
for(i = 0; i < 8; i++)
{
if(data & 0x80)
{
i2c_sda_high();
}
else
{
i2c_sda_low();
}
analog_i2c_delay();
i2c_scl_high();
analog_i2c_delay();
i2c_scl_low();
if(i == 7)
{
i2c_sda_high();
}
data <<= 1;
analog_i2c_delay();
}
}
/**
* @brief: I2C 读一个字节数据
* @return {*}
*/
uint8_t bsp_analog_i2c_read_byte(void)
{
uint8_t i, data = 0;
i2c_sda_high();
SDA_IN();
for(i = 0; i < 8; i++ )
{
data <<= 1;
i2c_scl_high();
analog_i2c_delay();
if(i2c_read_sda())
{
data++;
}
i2c_scl_low();
analog_i2c_delay();
}
return data;
}
void WriteOneByte(uint8_t WriteAddr,uint8_t DataToWrite)
{
bsp_analog_i2c_start();
bsp_analog_i2c_send_byte(salve_address_write);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_send_byte(WriteAddr);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_send_byte(DataToWrite);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_stop();
}
uint8_t ReadOneByte(uint8_t ReadAddr)
{
uint8_t temp=0;
bsp_analog_i2c_start();
bsp_analog_i2c_send_byte(salve_address_write);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_send_byte(ReadAddr);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_start();
bsp_analog_i2c_send_byte(salve_address_read);
bsp_analog_i2c_wait_ack();
temp= bsp_analog_i2c_read_byte();
bsp_analog_i2c_nack();
bsp_analog_i2c_stop();
return temp;
}
/*连续写*/
void sequence_write(uint8_t WriteAddr,uint8_t* data,int length)
{
bsp_analog_i2c_start();
bsp_analog_i2c_send_byte(salve_address_write);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_send_byte(WriteAddr);
bsp_analog_i2c_wait_ack();
for (int i = 0; i < length; i++)
{
bsp_analog_i2c_send_byte(*(data+i));
bsp_analog_i2c_wait_ack();
}
bsp_analog_i2c_nack();
bsp_analog_i2c_stop();
}
/*连续读*/
void sequence_read(uint8_t ReadAddr,uint8_t *data,int length)
{
bsp_analog_i2c_start();
bsp_analog_i2c_send_byte(salve_address_write);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_send_byte(ReadAddr);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_start();
bsp_analog_i2c_send_byte(salve_address_read);
bsp_analog_i2c_wait_ack();
for (int i = 0; i < length; i++)
{
*(data+i)= bsp_analog_i2c_read_byte();
bsp_analog_i2c_ack();
}
bsp_analog_i2c_stop();
}
IIC.H
/*
* softiic.h
*
* Created on: 2024年6月12日
* Author: Administrator
*/
#ifndef __SOFTIIC_H_
#define __SOFTIIC_H_
#include "main.h"
//使用IICX PD6,PC1
#define salve_address_write 0xC0
#define salve_address_read 0xC1
#define SDA_IN() {GPIOC->MODER &= ~(3 << 1 * 2);GPIOC->MODER = (0 << 1 * 2);}
#define SDA_OUT() {GPIOC->MODER &= ~(3 << 1 * 2);GPIOC->MODER = (1 << 1 * 2);}
//void SDAIN(void);
//IO操作函数
#define i2c_scl_low() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_RESET)
#define i2c_scl_high() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_SET)
#define i2c_sda_low() HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET)
#define i2c_sda_high() HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET)
#define i2c_read_sda() HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1)
extern uint32_t delay1us;
void delay_1us(uint32_t delay_1us);
void analog_i2c_delay(void);
void bsp_analog_i2c_init(void);
void bsp_analog_i2c_start(void);
void bsp_analog_i2c_stop(void);
uint8_t bsp_analog_i2c_wait_ack(void);
void bsp_analog_i2c_ack(void);
void bsp_analog_i2c_nack(void);
void bsp_analog_i2c_send_byte(uint8_t data);
uint8_t bsp_analog_i2c_read_byte(void);
void WriteOneByte(uint8_t WriteAddr,uint8_t DataToWrite);
uint8_t ReadOneByte(uint8_t ReadAddr);
void sequence_write(uint8_t WriteAddr,uint8_t* data,int length);
void sequence_read(uint8_t ReadAddr,uint8_t data[],int length);
#endif