123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- #include "iic.h"
- // 宏定义
- #define SDA_HIGH() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET)
- #define SDA_LOW() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET)
- #define SCL_HIGH() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET)
- #define SCL_LOW() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET)
- #define SDA_READ() HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_10)
- void I2C_Delay(uint8_t us)
- {
- for (volatile int i = 0; i < 5 * us; i++); // MSI_16MHZ下1对应0.188us,5为0.93us
- }
- void I2C_Start(void) {
- SDA_HIGH();
- SCL_HIGH();
- I2C_Delay(3);//
- SDA_LOW();// 当SCL为高电平时,SDA从高变低表示开始信号
- I2C_Delay(3);//
- SCL_LOW();// 开始信号传送完毕,拉低SCL准备数据传输
- }
- void I2C_Stop(void) {
- SDA_LOW();
- SCL_HIGH();// 当SCL为高电平时,SDA从低变高表示停止信号
- I2C_Delay(2);//
- SDA_HIGH();
- I2C_Delay(3);//
- }
- void I2C_SendByte(uint8_t byte) {
- for (uint8_t i = 0; i < 8; i++) {
- if (byte & 0x80) {
- SDA_HIGH();
- } else {
- SDA_LOW();
- }
- SCL_HIGH();// 在SCL上升沿时,数据稳定在SDA线上
- I2C_Delay(2);
- SCL_LOW();// 在SCL下降沿时,SDA可以改变状态
- I2C_Delay(3);
- byte <<= 1;
- }
- }
- uint8_t I2C_ReadByte(void) {
- uint8_t byte = 0;
- SDA_InputMode(); // 切换SDA为输入模式
- for (uint8_t i = 0; i < 8; i++) {
- SCL_HIGH();
- I2C_Delay(2);
- byte = (byte << 1) | SDA_READ();// 从MSB开始读取
- SCL_LOW();
- I2C_Delay(3);
- }
- SDA_OutputMode(); // 恢复SDA为输出模式
- return byte;
- }
- uint8_t I2C_WaitAck(void) {
- uint8_t ack;
- SDA_HIGH(); // 释放 SDA 线,准备接收ACK
- SDA_InputMode(); // 切换为输入模式,接收ACK
- SCL_HIGH();
- I2C_Delay(6);//
- ack = SDA_READ(); // 读取ACK信号
- SCL_LOW();
- SDA_OutputMode(); // 恢复 SDA 为输出模式
- return (ack == GPIO_PIN_RESET); // 返回ACK状态
- }
- void Soft_I2C_Write(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
- I2C_Start();
- I2C_SendByte(devAddr << 1); // 发送设备地址+写位
- if (!I2C_WaitAck()) return; // 等待ACK
- I2C_SendByte(regAddr); // 发送寄存器地址
- if (!I2C_WaitAck()) return; // 等待ACK
- I2C_SendByte(data); // 发送数据
- if (!I2C_WaitAck()) return; // 等待ACK
- I2C_Stop();
- }
- void Soft_I2C_Read(uint8_t devAddr, uint8_t regAddr, uint8_t *data) {
- I2C_Start();
- I2C_SendByte(devAddr << 1); // 发送设备地址+写位
- if (!I2C_WaitAck()) return; // 等待ACK
- I2C_SendByte(regAddr); // 发送寄存器地址
- if (!I2C_WaitAck()) return; // 等待ACK
- I2C_Start(); // 重启总线
- I2C_SendByte((devAddr << 1) | 1); // 发送设备地址+读位
- if (!I2C_WaitAck()) return; // 等待ACK
- *data = I2C_ReadByte(); // 读取数据
- I2C_Stop();
- }
- void Soft_I2C_ReadMulti(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t count) {
- I2C_Start();
- I2C_SendByte(devAddr << 1); // 发送设备地址+写位
- if (!I2C_WaitAck()) return; // 等待ACK
- I2C_SendByte(regAddr); // 发送寄存器地址
- if (!I2C_WaitAck()) return; // 等待ACK
- I2C_Start(); // 重启总线
- I2C_SendByte((devAddr << 1) | 1); // 发送设备地址+读位
- if (!I2C_WaitAck()) return; // 等待ACK
- while (count--) {
- *data++ = I2C_ReadByte(); // 读取多字节数据
- }
- I2C_Stop();
- }
- void SDA_InputMode(void) {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- GPIO_InitStruct.Pin = GPIO_PIN_10;
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
- void SDA_OutputMode(void) {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- GPIO_InitStruct.Pin = GPIO_PIN_10;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
|