Files
STC32G_Power_Monitor/Source/PCA9685_driver.c
2025-09-01 22:43:03 +08:00

124 lines
4.1 KiB
C

#include "PCA9685_driver.h"
#include "delay.h"
#if PCA9685_USE_SOFT_IIC == 1
#include "iic_soft.h"
static IIC_Soft_Config config;
#else
#include "iic.h"
#endif
static uint8 has_init = 0;
#if (1==PCA9685_USE_SOFT_IIC)
void pca9685_scl_set()
{
PCA9685_SCL_LEVEL(1);
}
void pca9685_sda_set()
{
PCA9685_SDA_LEVEL(1);
}
void pca9685_sda_clr()
{
PCA9685_SDA_LEVEL(0);
}
void pca9685_scl_clr()
{
PCA9685_SCL_LEVEL(0);
}
uint8 pca9685_sda_read()
{
return PCA9685_SDA_READ();
}
#endif
void pca9685_init()
{
if(has_init) return; // 如果已经初始化过,则直接返回
#if PCA9685_USE_SOFT_IIC == 1
// config.scl_pin = PCA9685_SOFT_IIC_SCL_PIN;
// config.sda_pin = PCA9685_SOFT_IIC_SDA_PIN;
config.SCL_SET = pca9685_scl_set;
config.SCL_CLR = pca9685_scl_clr;
config.SDA_SET = pca9685_sda_set;
config.SDA_CLR = pca9685_sda_clr;
config.SDA_READ = pca9685_sda_read;
config.wait_time = 10;
soft_iic_init(&config); // 初始化软件IIC
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, PCA9685_MODE1, 0x00); // 设置PCA9685模式寄存器为正常模式
#else
// 初始化I2C接口
iic_init(IIC_1, 20);
iic_write_reg(PCA9685_I2C_ADDR, PCA9685_MODE1, 0x00); // 设置为正常模式
#endif
pca9685_set_frequency(PCA9685_DEF_FREQ); // 设置默认频率
has_init = 1;
}
void pca9685_deinit()
{
if(!has_init) return; // 如果没有初始化过,则直接返回
has_init = 0; // 标记为未初始化
}
void pca9685_set_frequency(uint16 frequency)
{
// 计算预分频器值
uint8 prescale = 0;
uint8 old_mode1 = 0;
double prescale_value = 0.0;
prescale_value = 6103.515625 / frequency;
if (prescale_value < 3.0) {
prescale = 3; // 最小预分频器值
} else if (prescale_value > 255.0) {
prescale = 255; // 最大预分频器值
} else {
prescale = (uint8)prescale_value; // 正常预分频器值
if (prescale_value - prescale >= 0.5) {
prescale += 1; // 四舍五入
}
}
#if PCA9685_USE_SOFT_IIC == 1
// soft_iic_read_reg(&config, PCA9685_I2C_ADDR, PCA9685_MODE1, &old_mode1); // 读取当前模式寄存器
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, PCA9685_MODE1, (old_mode1 & 0x7F) | 0x10); // 进入睡眠模式
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, PCA9685_PRESCALE, prescale); // 设置预分频器
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, PCA9685_MODE1, old_mode1); // 恢复正常模式
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, PCA9685_MODE1, old_mode1 | 0x80); // 重启PCA9685
#else
// P05 = 0;
// 设置预分频器
// iic_read_reg(PCA9685_I2C_ADDR, PCA9685_MODE1, &old_mode1);
iic_write_reg(PCA9685_I2C_ADDR, PCA9685_MODE1, (old_mode1 & 0x7F) | 0x10); // 进入睡眠模式
iic_write_reg(PCA9685_I2C_ADDR, PCA9685_PRESCALE, prescale);
// 恢复模式寄存器
iic_write_reg(PCA9685_I2C_ADDR, PCA9685_MODE1, old_mode1); // 恢复正常模式
delay_ms(5); // 等待模式寄存器更新
iic_write_reg(PCA9685_I2C_ADDR, PCA9685_MODE1, old_mode1 | 0x80); // 重启PCA9685
// P05 = 1;
#endif
}
void pca9685_set_pwm(uint8 channel, uint16 on, uint16 off)
{
// P05 = 0; // 开始I2C通信
// 设置指定通道的PWM值
#if PCA9685_USE_SOFT_IIC == 1
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, (PCA9685_LED0_ON_L + 4 * channel) & 0xFF, on & 0xFF);
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, (PCA9685_LED0_ON_H + 4 * channel) & 0xFF, (on >> 8) & 0xFF);
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, (PCA9685_LED0_OFF_L + 4 * channel) & 0xFF, off & 0xFF);
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, (PCA9685_LED0_OFF_H + 4 * channel) & 0xFF, (off >> 8) & 0xFF);
#else
iic_write_reg(PCA9685_I2C_ADDR, (PCA9685_LED0_ON_L + 4 * channel) & 0xFF, on & 0xFF);
iic_write_reg(PCA9685_I2C_ADDR, (PCA9685_LED0_ON_H + 4 * channel) & 0xFF, (on >> 8) & 0xFF);
iic_write_reg(PCA9685_I2C_ADDR, (PCA9685_LED0_OFF_L + 4 * channel) & 0xFF, off & 0xFF);
iic_write_reg(PCA9685_I2C_ADDR, (PCA9685_LED0_OFF_H + 4 * channel) & 0xFF, (off >> 8) & 0xFF);
// P05 = 1; // 结束I2C通信
#endif
}