不含stm32 底层的代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
MyStm32Code/bsp/Src/bsp_i2c_soft.c

583 lines
12 KiB

#include "bsp_i2c_soft.h"
uint32_t delay1us;
/**
* @brief: 1us延时
* @param {uint32_t} delay_1us
* @return {*}
*/
// void delay_1us(uint32_t delay_1us)
// {
// HAL_TIM_Base_Start_IT( &htim3 );
// delay1us = delay_1us;
// while (delay1us);
// HAL_TIM_Base_Stop_IT( &htim3 );
// }
void delay_1us(uint32_t delay_1us)
{
uint16_t cnt = 0;
while(delay_1us--)
{
for(cnt=168/5; cnt>0; cnt--); // TODO 168
}
}
// static void delay_us(uint32_t u_sec)
// {
// uint16_t cnt = 0;
// while(u_sec--)
// {
// for(cnt=168/5; cnt>0; cnt--);
// }
// }
/**
* @brief: IIC延时时间
* @return {*}
*/
void analog_i2c_delay(void)
{
delay_1us(2);
}
/**
* @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 SCL */
GPIO_InitStruct.Pin = SCL_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(SCL_PORT, &GPIO_InitStruct);
/*Configure GPIO pins : PC1 SDA */
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(SDA_PORT, &GPIO_InitStruct);
bsp_analog_i2c_stop();
}
/**
* @brief: I2C 开始,SCL为高电平的时候SDA产生一个下降沿信号
* @return {*}
*/
void bsp_analog_i2c_start(void)
{
/* _____
*SDA \_____________
* __________
*SCL \________
*/
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 _____/
*/
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 > 2000)
{
return 1;
}
}
i2c_scl_low();
analog_i2c_delay();
return 0;
}
/**
* @brief: I2C 响应
* @return {*}
*/
void bsp_analog_i2c_ack(void)
{
/* ____
*SCL ______/ \______
* ____ _____
*SDA \_______/
*/
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
*/
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;
}
uint8_t bsp_i2c_test_write( uint8_t slave_addr, uint8_t reg_addr, uint8_t *buf, uint8_t len)
{
bsp_analog_i2c_start();
//发送器件地址+写命令
bsp_analog_i2c_send_byte(slave_addr & 0xFE);
if(bsp_analog_i2c_wait_ack()) //等待应答
{
bsp_analog_i2c_stop();
return -1;
}
//发送写(起始)寄存器地址
bsp_analog_i2c_send_byte(reg_addr);
if(bsp_analog_i2c_wait_ack()) //等待应答
{
bsp_analog_i2c_stop();
return -1;
}
//发送写数据
for(int i=0; i<len; i++)
{
bsp_analog_i2c_send_byte(*buf++);
if(bsp_analog_i2c_wait_ack()) //等待应答
{
bsp_analog_i2c_stop();
return -1;
}
}
//停止位
bsp_analog_i2c_stop();
}
uint8_t bsp_i2c_test_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *buf, uint8_t len)
{
//发送起始位
bsp_analog_i2c_start();
//发送器件地址+写命令
bsp_analog_i2c_send_byte(slave_addr & 0xFE);
if(bsp_analog_i2c_wait_ack()) //等待应答
{
bsp_analog_i2c_stop();
return -1;
}
//发送写(起始)寄存器地址
bsp_analog_i2c_send_byte(reg_addr);
if(bsp_analog_i2c_wait_ack()) //等待应答
{
bsp_analog_i2c_stop();
return -1;
}
//发送重复起始位
bsp_analog_i2c_start();
//发送器件地址+读命令
bsp_analog_i2c_send_byte(slave_addr | 0x01);
if(bsp_analog_i2c_wait_ack()) //等待应答
{
bsp_analog_i2c_stop();
return -1;
}
//读取数据
// for(int i=0; i<len-1; i++)
// {
// *buf++ = bsp_analog_i2c_read_byte();
// }
// *buf = bsp_analog_i2c_read_byte(); //最后一位数据发送NACK
for(int i=0; i<len-1; i++)
{
*buf++ = bsp_analog_i2c_read_byte();
bsp_analog_i2c_ack(); // 应答
}
*buf = bsp_analog_i2c_read_byte(); //最后一位数据发送NACK
bsp_analog_i2c_nack(); //非应答
//停止位
bsp_analog_i2c_stop();
}
// //IIC初始化
// void IIC_Init(void)
// {
// GPIO_InitTypeDef GPIO_Initure;
// __HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟
// //PH4,5初始化设置
// GPIO_Initure.Pin=GPIO_PIN_6|GPIO_PIN_7;
// GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
// GPIO_Initure.Pull=GPIO_PULLUP; //上拉
// GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
// HAL_GPIO_Init(GPIOB,&GPIO_Initure);
// IIC_SDA=1;
// IIC_SCL=1;
// }
// //产生IIC起始信号
// void IIC_Start(void)
// {
// SDA_OUT(); //sda线输出
// IIC_SDA=1;
// IIC_SCL=1;
// delay_us(4);
// IIC_SDA=0;//START:when CLK is high,DATA change form high to low
// delay_us(4);
// IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
// }
// //产生IIC停止信号
// void IIC_Stop(void)
// {
// SDA_OUT();//sda线输出
// IIC_SCL=0;
// IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
// delay_us(4);
// IIC_SCL=1;
// IIC_SDA=1;//发送I2C总线结束信号
// delay_us(4);
// }
// //等待应答信号到来
// //返回值:1,接收应答失败
// // 0,接收应答成功
// uint8_t IIC_Wait_Ack(void)
// {
// uint8_t ucErrTime=0;
// SDA_IN(); //SDA设置为输入
// IIC_SDA=1;delay_us(1);
// IIC_SCL=1;delay_us(1);
// while(READ_SDA)
// {
// ucErrTime++;
// if(ucErrTime>250)
// {
// IIC_Stop();
// return 1;
// }
// }
// IIC_SCL=0;//时钟输出0
// return 0;
// }
// //产生ACK应答
// void IIC_Ack(void)
// {
// IIC_SCL=0;
// SDA_OUT();
// IIC_SDA=0;
// delay_us(2);
// IIC_SCL=1;
// delay_us(2);
// IIC_SCL=0;
// }
// //不产生ACK应答
// void IIC_NAck(void)
// {
// IIC_SCL=0;
// SDA_OUT();
// IIC_SDA=1;
// delay_us(2);
// IIC_SCL=1;
// delay_us(2);
// IIC_SCL=0;
// }
// //IIC发送一个字节
// //返回从机有无应答
// //1,有应答
// //0,无应答
// void IIC_Send_Byte(uint8_t txd)
// {
// uint8_t t;
// SDA_OUT();
// IIC_SCL=0;//拉低时钟开始数据传输
// for(t=0;t<8;t++)
// {
// IIC_SDA=(txd&0x80)>>7;
// txd<<=1;
// delay_us(2); //对TEA5767这三个延时都是必须的
// IIC_SCL=1;
// delay_us(2);
// IIC_SCL=0;
// delay_us(2);
// }
// }
// //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
// uint8_t IIC_Read_Byte(unsigned char ack)
// {
// unsigned char i,receive=0;
// SDA_IN();//SDA设置为输入
// for(i=0;i<8;i++ )
// {
// IIC_SCL=0;
// delay_us(2);
// IIC_SCL=1;
// receive<<=1;
// if(READ_SDA)receive++;
// delay_us(1);
// }
// if (!ack)
// IIC_NAck();//发送nACK
// else
// IIC_Ack(); //发送ACK
// return receive;
// }
// 兼容软硬i2c
// /*
// * 函数功能:I2C1写寄存器,这是提供给上层的接口
// * 输入参数:slave_addr:从机地址
// * reg_addr:寄存器地址
// * len:写入的长度
// * data_ptr:指向要写入的数据
// * 返回值 :正常为0,不正常为非0
// * 说明 :无
// */
// int Sensors_I2C1_WriteRegister(unsigned char slave_addr, unsigned char reg_addr, unsigned short len, unsigned char *data_ptr)
// {
// #ifdef HARDWARE_I2C //硬件I2C
// HAL_StatusTypeDef status = HAL_OK;
// status = HAL_I2C_Mem_Write(&hi2c1, slave_addr, reg_addr, I2C_MEMADD_SIZE_8BIT, data_ptr, len, I2Cx_FLAG_TIMEOUT);
// //检查通讯状态
// if(status != HAL_OK)
// {
// //总线出错处理
// I2C1_Error();
// }
// while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
// {
// }
// //检查SENSOR是否就绪进行下一次读写操作
// while (HAL_I2C_IsDeviceReady(&hi2c1, slave_addr, I2Cx_FLAG_TIMEOUT, I2Cx_FLAG_TIMEOUT) == HAL_TIMEOUT);
// //等待传输结束
// while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
// {
// }
// return status;
// #else //软件I2C1
// //发送起始位
// IIC1_Start();
// //发送器件地址+写命令
// IIC1_Write_Byte(slave_addr & 0xFE);
// if(IIC1_Wait_Ack()) //等待应答
// {
// IIC1_Stop();
// return -1;
// }
// //发送写(起始)寄存器地址
// IIC1_Write_Byte(reg_addr);
// if(IIC1_Wait_Ack()) //等待应答
// {
// IIC1_Stop();
// return -1;
// }
// //发送写数据
// for(int i=0; i<len; i++)
// {
// IIC1_Write_Byte(*data_ptr++);
// if(IIC1_Wait_Ack()) //等待应答
// {
// IIC1_Stop();
// return -1;
// }
// }
// //停止位
// IIC1_Stop();
// return 0;
// #endif
// }
// /*
// * 函数功能:I2C1读寄存器,这是提供给上层的接口
// * 输入参数:slave_addr:从机地址
// * reg_addr:寄存器地址
// * len:要读取的长度
// * data_ptr:指向要存储数据的指针
// * 返回值 :正常为0,不正常为非0
// * 说明 :无
// */
// int Sensors_I2C1_ReadRegister(unsigned char slave_addr, unsigned char reg_addr, unsigned short len, unsigned char *data_ptr)
// {
// #ifdef HARDWARE_I2C //硬件I2C
// HAL_StatusTypeDef status = HAL_OK;
// status = HAL_I2C_Mem_Read(&hi2c1, slave_addr, reg_addr, I2C_MEMADD_SIZE_8BIT, data_ptr, len, I2Cx_FLAG_TIMEOUT);
// //检查通讯状态
// if(status != HAL_OK)
// {
// //总线出错处理
// I2C1_Error();
// }
// while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
// {
// }
// //检查SENSOR是否就绪进行下一次读写操作
// while (HAL_I2C_IsDeviceReady(&hi2c1, slave_addr, I2Cx_FLAG_TIMEOUT, I2Cx_FLAG_TIMEOUT) == HAL_TIMEOUT);
// //等待传输结束
// while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
// {
// }
// return status;
// #else //软件I2C
// //发送起始位
// IIC1_Start();
// //发送器件地址+写命令
// IIC1_Write_Byte(slave_addr & 0xFE);
// if(IIC1_Wait_Ack()) //等待应答
// {
// IIC1_Stop();
// return -1;
// }
// //发送写(起始)寄存器地址
// IIC1_Write_Byte(reg_addr);
// if(IIC1_Wait_Ack()) //等待应答
// {
// IIC1_Stop();
// return -1;
// }
// //发送重复起始位
// IIC1_Start();
// //发送器件地址+读命令
// IIC1_Write_Byte(slave_addr | 0x01);
// if(IIC1_Wait_Ack()) //等待应答
// {
// IIC1_Stop();
// return -1;
// }
// //读取数据
// for(int i=0; i<len-1; i++)
// {
// *data_ptr++ = IIC1_Read_Byte(1);
// }
// *data_ptr = IIC1_Read_Byte(0); //最后一位数据发送NACK
// //停止位
// IIC1_Stop();
// return 0;
// #endif
// }