PCA9685使用笔记[16路PWM拓展芯片]

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);								//怕出意外,休息哈
}

03-15
### PCA9685 使用说明及驱动 PWM 控制器 #### 1. 技术规格概述 PCA9685 是一款基于 I²C 接口的 16 通道 PWM 控制器,支持高达 1kHz 的频率设置[^2]。每一输出可以独立配置占空比,分辨率为 12 位(即 4096 步)。这使得它非常适合用于 LED 调光以及伺服电机控制。 该芯片通过 I²C 协议与主机通信,默认地址为 `0x40`,可以通过修改引脚 A0-A5 设置多达 62 个不同的设备地址[^3]。其工作电压范围为 2.3V 至 5.5V,能够提供稳定的电流输出以驱动外部负载。 --- #### 2. Linux 下的 DTS 文件配置 在 Linux 系统中,为了使 PCA9685 工作正常,通常需要编写 Device Tree Source (DTS) 文件来定义硬件资源。具体来说: - **PWM 控制器节点** pca9685pw0 定义的是基础的 PWM 功能模块,仅限于初始化和基本功能绑定[^1]。 - **LED 驱动节点** 如果目标是实现背光或其他类型的 LED 控制,则需额外增加一个专门针对 LED 的子节点信息。例如,在树莓派上可能如下所示: ```dts pwm-leds { compatible = "gpio-leds"; led@0 { label = "led0"; gpios = <&pca9685 0>; }; }; ``` 上述代码片段表明如何关联特定 GPIO 到指定通道上的 LED 输出。 --- #### 3. C/C++ 编程接口示例 以下是利用标准库操作 PCA9685 的简单例子,展示如何设定频率并调整单个通道的亮度水平: ```c #include <wiringPiI2C.h> #include <stdio.h> #define PCA9685_ADDR 0x40 // 默认 I2C 地址 #define MODE1 0x00 // 寄存器模式寄存器 1 #define PRESCALE 0xFE // 设定预分频值位置 #define LED0_ON_L 0x06 // 第一盏灯开启时间低位字节偏移量 int main(void){ int fd; if ((fd=wiringPiI2CSetup(PCA9685_ADDR))<0){ printf("Failed to open the i2c bus\n"); return -1; } wiringPiI2CI2CWriteReg8(fd,MODE1,0x01); // 启用自动增量写入 float freq=50; // 目标频率(Hz) double prescaleval=(25e6)/(4096*freq)-1;// 计算所需预缩放因子 uint8_t prescale=floor(prescaleval+0.5); wiringPiI2CWriteReg8(fd,PRESCALE,prescale); delay(5); // 等待更新生效 wiringPiI2CWriteReg16(fd,LED0_ON_L,0); // 清零起始时刻 wiringPiI2CWriteReg16(fd,(LED0_ON_L)+4,3072); // 设置结束时间为最大周期的一半 while(1){}; } ``` 以上程序展示了如何计算合适的预分频数值,并将其应用于实际场景之中。 --- #### 4. Python 库应用案例 对于更高级别的抽象层面上的操作,推荐使用 Adafruit 提供的官方 CircuitPython 驱动包。下面是一个简单的演示样例,用来改变某个通道内的脉宽调制参数: ```python import board import adafruit_pca9685 i2c_bus = board.I2C() pca = adafruit_pca9685.PCA9685(i2c_bus) pca.frequency = 60 # 设置全局刷新率至 60Hz channel_number = 1 # 假设我们想操控第二个端口 max_value = 4095 # 对应完全打开状态下的量化等级 min_value = max_value * .3 # 只允许达到总强度的大约三成 while True: for value in range(int(min_value), int(max_value)): pca.channels[channel_number].duty_cycle=value<<4 # 移位运算符确保格式匹配要求 ``` 这里需要注意的是,由于内部协议限制,最终传递给硬件的数据必须左移四位才能正确解析。 --- ####
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

余十三_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值