PCA9685引脚图
引脚功能
A0~A5:用于IIC地址选择,上图
默认情况下A0~A5都接地,即地址为0x40(0b01000000),由于IIC的最低位是读写位所以需要左移一位即0x80(0b10000000)
#OE:使能位,低电平有效
extclk:外部时钟引脚
vdd:器件内部的工作电压 支持2.5 V~5.5 V
vss:公共接地端
LED0~LED15:输出引脚
SDA/SCL:IIC通信引脚
寄存器配置
MODE1寄存器(0x00)
需要注意的就下面这几位
bit7->RESTART:重启
bit6->EXTCLK:选择是否使用外部时钟
bit5->AI:设置是否自增,要输出PWM波形这位肯定得是1了
bit0->ALLCALL:未级联多块芯片就不管,级联多个且需要同时控制时才置1
PRE_SCALE寄存器(0xFE)
用于设置工作频率,计算公式
内部系统时钟为25MHz即osc_clock = 25MHz
update_rate:想要设置的频率,可设置范围为24~1526Hz对应寄存器值为(0xff-0x03)
注意:需要向上取整
LEDx_ON_L/LEDx_ON_H/LEDx_OFF_L/LEDx_OFF_H 寄存器(LED0->0x06-0x09 LED15->0x06+(154)-0x09+(154))
用于设置对应引脚的占空比,PCA9685是12位分辨率即0~4095
不需要两个一起设置,只需要设置其中一个即LEDx_ON_L/LEDx_ON_H或者LEDx_OFF_L/LEDx_OFF_H
写懵了,上代码
/******************************
* 函数名:PCA9685_Init
* 参数:无
* 作用:PCA9685初始化
******************************/
void PCA9685_Init(void)
{
DEV_IIC_Init(0x00,400000); //初始化IIC
delay_ms(2); //怕出意外,休息一下
IIC_SendData(PCA9685_adrr, PCA9685_MODE1, 0x00);//退出SLEEP模式
delay_ms(2);
IIC_SendData(PCA9685_adrr, PCA9685_MODE1, 0x80);//复位MODE1寄存器
delay_ms(2);
setPWMFreq(1000); //设置频率
}
/******************************
* 函数名:setPWMFreq
* 参数:freq 频率范围->24-1526(Hz)
* 作用:设置工作频率 prescaleval=round(25M/4096/freq)-1;
******************************/
void setPWMFreq(float freq)
{
uint8_t prescale;
float prescaleval;
freq *= 0.95f; //纠正频率设置中的过冲,进行校准
//prescaleval=round(25M/4096/freq)-1;
prescaleval = 25000000.0f;
prescaleval /= 4096;
prescaleval /= freq;
prescaleval -= 1;
prescale = (uint8_t)(prescaleval + 0.5f);//向上取整
PCA9685_SendData(PCA9685_MODE1, 0x10); //进入SLEEP模式
delay_ms(2);
PCA9685_SendData(PCA9685_PRESCALE, prescale); //设置频率
PCA9685_SendData(PCA9685_MODE1, 0x00); //退出SLEEP模式
delay_ms(2);
PCA9685_SendData(PCA9685_MODE1, 0xA0); //RESTART、AI 置1
delay_ms(500);//一定得延时 否则修改不了
}
/******************************
* 函数名:Set_Duty
* 参数:channel 通道范围->1~16
* on 高电平时间范围->0~4095
* 作用:设置占空比
******************************/
void Set_Duty(uint8_t channel, uint16_t on)
{
uint8_t data[4];
on = on > 4095 ? 4095 : on; //设置为4096理论来说是没什么问题的,但实际测试不得行
on = 4095 - on; //实际设置的是低电平的时间,之前设置高电平的时间有点小问题
data[0] = 0; //这点是LEDx_ON_L寄存器的值
data[1] = 0; //这点是LEDx_ON_L寄存器的值
data[2] = on&0xff; //这点是LEDx_OFF_L寄存器的值
data[3] = on>>8; //这点是LEDx_OFF_H寄存器的值
PCA9685_SendDatas(LED0_ON_L+4*channel, data, 4);//因为每通道的地址相差4,所以+4*channel
delay_ms(1); //怕出意外,休息哈
}