newPtz/drivers/drv_i2c.c

171 lines
4.9 KiB
C
Raw Permalink 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.

/*************************************************
Copyright (c) 2025, 成都赛联科技有限责任公司
All rights reserved.
@file drv_i2c.C
@brief drv_i2c驱动程序
@details
@note
@author dufresne
@date 2025/09/24
@version v1.0 2025/09/24 初始版本
*************************************************/
#include "drv_i2c.h"
void i2c_init(void)
{
i2c_gpio_config();
#ifdef HARDWARE_I2C
i2c_config();
#endif
}
/*
@ brief 初始化i2c的GPIO引脚
@ param
@ return
@ note 2025-09-15
*/
void i2c_gpio_config(void)
{
// 配置引脚时钟
rcu_periph_clock_enable(RCU_GPIOB);
#ifdef HARDWARE_I2C
gpio_af_set(GPIOB, GPIO_AF_4, I2C_SCL_PIN | I2C_SDA_PIN);
/* 初始化GPIO复用功能模式 */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SCL_PIN | I2C_SDA_PIN);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN | I2C_SDA_PIN);
#endif
#ifdef SOFTWARE_I2C
// 设置引脚为输出模式:PB6
gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, I2C_SCL_PIN | I2C_SDA_PIN);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, I2C_SCL_PIN | I2C_SDA_PIN);
I2C_SCL_HIGH;
I2C_SDA_HIGH;
#endif
}
#ifdef HARDWARE_I2C
void i2c_config(void)
{
// 启用 I2C 外设的时钟
rcu_periph_clock_enable(RCU_I2C0);
i2c_deinit(I2C_PERIPH);
// 配置 I2C 的时钟参数:
// I2C_PERIPH这里使用的I2C1
// I2C_SPEED通信速率单位为 Hz常用为 100000 或 400000这里使用100000
i2c_clock_config(I2C_PERIPH, I2C_SPEED, I2C_DTCY_2);
// 配置 I2C 工作模式和地址:
// I2C_ADDFORMAT_7BITS使用 7 位地址模式
i2c_mode_addr_config(I2C_PERIPH, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00);//作为从机时的地址,随意设置即可
// 使能 ACK 应答功能,确保在接收数据后自动发送 ACK
i2c_ack_config(I2C_PERIPH, I2C_ACK_ENABLE);
// 启用 I2C 外设
i2c_enable(I2C_PERIPH);
}
void i2c_write(uint8_t *buff, int len, uint8_t device_address)
{
/* 等待总线空闲 */
while(i2c_flag_get(I2C_PERIPH, I2C_FLAG_I2CBSY));
/* 发送起始条件 */
i2c_start_on_bus(I2C_PERIPH);
/* 等待起始条件已发送标志 */
while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_SBSEND));
/* 发送从机地址(写模式) */
i2c_master_addressing(I2C_PERIPH, device_address << 1, I2C_TRANSMITTER);
/* 等待地址已发送标志 */
while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_ADDSEND));
/* 清除地址发送标志 */
i2c_flag_clear(I2C_PERIPH, I2C_FLAG_ADDSEND);
for(int i = 0; i < len; i++)
{
/* 等待发送数据缓冲区为空 */
while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE));
/* 发送一个字节数据 */
i2c_data_transmit(I2C_PERIPH, buff[i]);
}
/* 等待数据传输完成 */
while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE));
/* 发送停止条件 */
i2c_stop_on_bus(I2C_PERIPH);
/* 等待停止条件发送完成 */
while(I2C_CTL0(I2C_PERIPH) & I2C_CTL0_STOP); // 检查STPDET位或类似标志
}
//接收1字节数据
void i2c_read(uint8_t *buff, uint16_t len, uint8_t device_address)
{
/* 等待I2C总线空闲 */
while(i2c_flag_get(I2C_PERIPH, I2C_FLAG_I2CBSY));
/* 向I2C总线发送启动信号 */
i2c_start_on_bus(I2C_PERIPH);
/* 等待直到设置SBSEND位 */
while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_SBSEND));//设置主机发送启动条件
/* 将从机地址发送到I2C总线 */
i2c_master_addressing(I2C_PERIPH, device_address << 1, I2C_RECEIVER);//设置主机接收
/* 等待地址位被设置 */
while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_ADDSEND));
/* 清除地址位 */
i2c_flag_clear(I2C_PERIPH, I2C_FLAG_ADDSEND);
/* 使能ACK多个字节接收时需要应答 */
i2c_ack_config(I2C_PERIPH, I2C_ACK_ENABLE);
/* 5. 接收数据 */
if(len > 1)
{
/* 使能ACK多个字节接收时需要应答 */
i2c_ack_config(I2C_PERIPH, I2C_ACK_ENABLE);
for(int i = 0; i < len; i++)
{
if(i == (len - 1))
{
/* 最后一个字节前禁用ACK */
i2c_ack_config(I2C_PERIPH, I2C_ACK_DISABLE);
}
/* 等待RBNE标志接收缓冲区非空 */
while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_RBNE));
/* 读取数据 */
buff[i] = i2c_data_receive(I2C_PERIPH);
}
}
else
{
/* 单字节接收直接禁用ACK */
i2c_ack_config(I2C_PERIPH, I2C_ACK_DISABLE);
/* 等待RBNE标志 */
while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_RBNE));
/* 读取数据 */
buff[0] = i2c_data_receive(I2C_PERIPH);
}
/* 发送停止信号 */
i2c_stop_on_bus(I2C_PERIPH);
/* 等待停止信号完成 */
while(I2C_CTL0(I2C_PERIPH) & I2C_CTL0_STOP);
}
#endif