#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; 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.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 }