Files
DTU-LCD/Drivers/BSP/IIC/iic.c
2026-01-24 20:03:14 +08:00

176 lines
3.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
******************************************************************************
* @文件 iic.c
* @作者 阜阳师范大学物电学院
* @版本 V0.1
* @日期 2025-03-27
* @简介 软件 IIC 驱动程序
******************************************************************************
**/
#include "iic.h"
/**
* @brief IIC初始化函数
* @note 初始化IIC通信所需的GPIO引脚配置为开漏输出模式
* @retval 无
*/
void iic_init()
{
GPIO_InitTypeDef gpio_init_struct;
IIC_SCL_GPIO_CLK_ENABLE();
IIC_SDA_GPIO_CLK_ENABLE();
gpio_init_struct.Pin = IIC_SCL_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(IIC_SCL_GPIO_PORT,&gpio_init_struct);
gpio_init_struct.Pin = IIC_SDA_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD;
HAL_GPIO_Init(IIC_SDA_GPIO_PORT,&gpio_init_struct);
IIC_SDA(1);
IIC_SCL(1);
}
/**
* @brief IIC总线延时函数
* @note 提供固定2微秒的延时满足IIC通信时序要求
* @retval 无
*/
static void iic_delay(void)
{
delay_us(2);
}
/**
* @brief 产生IIC起始信号
* @note 起始信号时序SCL高电平时SDA由高变低
* @retval 无
*/
void iic_start(void)
{
IIC_SCL(1);
IIC_SDA(1);
iic_delay();
IIC_SDA(0);
iic_delay();
IIC_SCL(0);
iic_delay();
}
/**
* @brief 向IIC总线发送一个字节数据
* @param data待发送的8位数据
* @retval 无
*/
void iic_send_byte(uint8_t data)
{
uint8_t t;
for(t = 0;t<8;t++)
{
IIC_SDA((data&0x80)>>7);
iic_delay();
IIC_SCL(1);
iic_delay();
IIC_SCL(0);
data<<=1;
}
IIC_SDA(1);
}
/**
* @brief 产生IIC停止信号
* @note 停止信号时序SCL高电平时SDA由低变高
* @retval 无
*/
void iic_stop(void)
{
IIC_SDA(0);
iic_delay();
IIC_SCL(1);
iic_delay();
IIC_SDA(1);
iic_delay();
}
/**
* @brief 等待IIC从机应答信号
* @note 从机应答信号为SDA低电平超时自动释放总线
* @retval 1未接收到应答0接收到应答
*/
uint8_t iic_wait_ack(void)//返回1失败0成功
{
IIC_SDA(1);
iic_delay();
IIC_SCL(1);
iic_delay();
if(IIC_READ_SDA)
{
iic_stop();
return 1;
}
IIC_SCL(0);
iic_delay();
return 0;
}
/**
* @brief 主机发送应答信号
* @note 应答信号时序SCL高电平时SDA保持低电平
* @retval 无
*/
void iic_ack(void)
{
IIC_SCL(0);
iic_delay();
IIC_SDA(0);
iic_delay();
IIC_SCL(1);
iic_delay();
}
/**
* @brief 主机发送非应答信号
* @note 非应答信号时序SCL高电平时SDA保持高电平
* @retval 无
*/
void iic_nack(void)
{
IIC_SCL(0); /* 产生一个时钟 */
iic_delay();
IIC_SDA(1);
iic_delay();
IIC_SCL(1); /* 主机释放SDA线 */
iic_delay();
}
/**
* @brief 从IIC总线读取一个字节数据
* @param ack应答控制0=发送非应答1=发送应答
* @retval 读取到的8位数据
*/
uint8_t iic_read_byte(uint8_t ack)
{
uint8_t i,receive = 0;
for(i=0;i<8;i++)
{
receive<<=1;
IIC_SCL(1);
iic_delay();
if(IIC_READ_SDA) receive++;
IIC_SCL(0);
iic_delay();
}
if(!ack) iic_nack();
else iic_ack();
return receive;
}