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.
583 lines
12 KiB
583 lines
12 KiB
2 years ago
|
#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
|
||
|
// }
|