124 lines
4.1 KiB
C
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
|
|
} |