PCA9632笔记
个人学习笔记,有错漏。具体请以官方数据手册为准
I2C地址
PCA9632使用I2C通信,I2C设备地址固定
发出START后输出访问设备地址(8bit版本地址固定)
0x62(7位地址)
地址最后一位为1读 为0写
8位写地址 0xC4
8位读地址 0xC5
注:具体使用7位/8位地址需根据使用的I2C库判断
寄存器
控制寄存器
在成功确认目标地址,LED所有呼叫地址或LED子呼叫地址后,总线控制器将向PCA9632发送一个字节,该字节将存储在控制寄存器中。
最低的4位用作指针,以确定将访问哪个寄存器(D[3:0])。最高的3位被用作自动递增标志和自动递增选项(AI[2:0])。bit4是未使用的,必须置为0才能使设备正常工作。
当设置了自增标志(AI2 = 1)时,在读或写操作之后,控制寄存器的4个低位自动递增。这允许用户按顺序对寄存器进行编程。根据AI1和AI0的值,可能有四种不同类型的Auto-Increment。
大致翻译
AI2 | AI1 | AI0 | Function |
---|---|---|---|
0 | 0 | 0 | 无自增 |
1 | 0 | 0 | 所有寄存器自动递增。D3, D2, D1, D0在最后一个寄存器(1100)被访问后回到’ 0000 ’ |
1 | 0 | 1 | 仅对单个亮度寄存器进行自增。在最后一个寄存器(0101)被访问后,D3, D2, D1, D0滚到’ 0010 ’ |
1 | 1 | 0 | 自增仅适用于全局控制寄存器。在最后一个寄存器(0111)被访问后,D3, D2, D1, D0转到’ 0110 ’ |
1 | 1 | 1 | 自增仅适用于单个和全局控制寄存器。D3, D2, D1, D0 在最后一个寄存器(0111)被访问后,D1, D0滚到’ 0010 '。 |
注:表5 (AI[2:0] = 001, 010, 011)中未显示的其他组合保留,不得用于设备的正常操作。
AI[2:0] = 000,无自增 用于在单个i2c总线通信期间必须多次访问同一寄存器时,例如,改变单个LED的亮度。在写操作期间,每次访问寄存器时都会覆盖数据。
AI[2:0] = 100,所有寄存器自增 在必须顺序访问所有寄存器时使用,例如,上电编程。
AI[2:0] = 101,单个控制器自增 用于四个LED驱动器必须在同一i2c总线通信中分别编程不同的值时,例如,将颜色设置更改为另一种颜色设置。
AI[2:0] = 111,单个\全局控制器自增 用于必须在同一i2c总线通信中执行单个和全局更改时,例如,同时更改颜色和全局亮度。
D[3:0] 所表示的寄存器如下表
寄存器MODE1 【00H】
MODE1[7:5]为只读位 由前面所述的控制寄存器决定值
SLEEP位 当振荡器关闭(1:睡眠模式)时,LED输出不能打开,关闭或变暗/闪烁
ALLCALL位为1时,可通过ALLCALLADR地址进行I2C通信
寄存器MODE2 【01H】
其中要注意的是INVRT和OUTDRV,
INVRT可切换输出电平是否翻转
OUTDRV默认为开漏输出,可切换为图腾柱(totem pole)输出,需根据电路决定
LEDx的状态与MODE2的INVRT和OUTDRV有关
寄存器PWM0-3 / PWMx 【02H - 05H】
individual brightness
在单独亮度模式(LDRx = 10)下工作时,每个输出使用1.5625 kHz固定频率信号。占空比从00h开始通过256个线性步进控制(0%占空比= LED输出关闭)至FFh(99.6%占空比= LED最大亮度输出)。在这种模式下,所有的8位都被使用。(255/256=0.996)
dimming
在组调光模式下工作时,每个输出使用6.25 kHz固定频率信号。占空比从00h(0%占空比= LED输出关闭)开始通过64个线性步骤进行控制,至3Fh(98.4%占空比= LED输出在最大亮度[63/64=0.9843])。在这种模式下,只使用6个最高有效位(IDCx[7:2])。忽略2个最低有效位 IDCx[1:0]。
适用于LDRx = 11 (LEDOUT寄存器)编程的LED输出。
blink
在闪烁模式下工作时,每个输出使用1.5625 kHz固定频率信号。占空比通过256个线性步骤控制,从00h(0%占空比= LED输出关闭)到FFh(99.6%占空比= LED在最大亮度下输出)。在这种模式下,所有的8位数据都被使用。
寄存器GRPPWM 【06H】
individual brightness
当DMBLNK位(MODE2寄存器)被编程为0时,一个190 Hz固定频率信号与6.25 kHz单个亮度控制信号叠加。然后使用GRPPWM作为全局亮度控制,允许LED输出以相同的值变暗。GRPFREQ中的值无效。
group dimming mode
在组调光模式(DMBLNK = 0)中,4个输出的全局亮度通过从00h(0%占空比= LED输出关闭)到F0h的16个线性步骤进行控制(93.75%占空比=最大亮度)。在这种模式下,高4位有效,低4位未使用。
global blinking pattern
当DMBLNK位被编程为1时,GRPPWM和GRPFREQ寄存器定义了一个全局闪烁模式,其中GRPFREQ包含闪烁周期(从24hz到10.73 s)和GRPPWM占空比(开/关比,单位为%)。在这种模式下,当GRPFREQ被编程为提供24 Hz到6 Hz频率可编程的闪烁时,GRPPWM高6位被用于配置从0%到98.4%的64步占空比分辨率。GRPPWM的低2位未使用。
blink
当GRPFREQ被编程为提供频率从6 Hz到0.09 Hz (10.73 s)可编程的闪烁时,GRPPWM[7:0]被用于提供从0%到99.6%的256步占空比分辨率。在这种情况下,GRPPWM寄存器的所有8位都被使用。
寄存器GRPFREQ 【07H】
GRPFREQ用于编程DMBLNK位(MODE2寄存器)等于逻辑1时的全局闪烁周期。当DMBLNK = 0时,此寄存器中的值无效。适用于LDRx = 11 (LEDOUT寄存器)编程的LED输出。
闪烁周期通过256个线性步进控制,从00h (41 ms,频率24 Hz)到FFh(10.73秒)。
寄存器LEDOUT 【08H】
LEDOUT寄存器决定各个LED驱动的控制状态
LDRx对应状态
LDRx的值 | 状态 |
---|---|
00b[0] | LEDx 关闭(上电默认) |
01b[1] | LEDx 完全打开(不控制单个亮度和组调光/闪烁) |
10b[2] | LEDx 的单个亮度可以通过其PWMx寄存器进行控制 |
11b[3] | LEDx 单个亮度和组调光/闪烁可以通过其PWMx寄存器和GRPPWM寄存器进行控制。 |
寄存器SUBADR1-3 / SUBADRx 【09H - 0BH】
通过i2c总线可编程(易失性编程)。默认开机值为E2h,E4h, E8h。
设备在上电后默认禁用(需要设置MODE1寄存器中对应的SUBx位等于逻辑0)。
一旦子地址被编程为正确的值,为了让设备确认这些地址(MODE1寄存器),SUBx位需要设置为1。当MODE1寄存器的SUBx位设置为1时,对应的i2c总线子地址SUBADRx可以在i2c总线读或写序列中使用。
只有高7位有效。最低位保留,值为0。
寄存器LED All Call I2C-Bus address / ALLCALLADR 【0CH】
Page14
默认值1110000x[E0H],通过i2c总线可编程(易失性编程)
I2C总线上可连接多个PCA9632,通过该寄存器设置I2C设备地址。允许同时对总线上的所有pca9632进行编程(寄存器MODE1中的ALLCALL位必须等于1,上电默认启用)。这个地址可以通过i2c总线编程,并且可以在i2c总线读或写序列中使用。寄存器地址可以被编程为子调用。
7个最高有效位有效。最低位保留,值为0。
如果寄存器MODE1中的ALLCALL位= 0,设备不承认在寄存器ALLCALLADR中编程的地址。
备注:默认值E0H不可用作常规I2C目标总线地址,因为所有PCA9632上电后地址默认值一致。
I2C通讯
在START条件之后,总线控制器必须输出它正在访问的目标的地址。(8pin版本只有一个固定地址)
初始化I2C时序:写Command控制寄存器-写MODE1数据 - 写MODE2数据 - 写控制寄存器 - 写LEDOUT寄存器数据
使用默认I2C总线地址可能会干扰其他设备
向寄存器写数据
I2C时序:START - 写I2C地址 - 写寄存器地址 - 写数据
/** ************************************************************
* @brief PCA9632写寄存器数据
* @param [in] u8Reg 要写的寄存器地址 可使用enum command_reg
* @param [in] pu8Data 写数据缓冲区
* @param [in] u32Size 写数据长度
* @retval None
*************************************************************/
void PCA9632_Write(uint8_t u8Reg, uint8_t* pu8Data, uint16_t u16Len)
{
int32_t i32Ret = LL_OK;
i32Ret = I2C_Start(I2C_UNIT, I2C_TIMEOUT);
if (LL_OK == i32Ret)
{
if(u16Len > 1) u8Reg |= 0x80; // 写控制寄存器:连续写(寄存器地址自动递增)
i32Ret = I2C_TransAddr(I2C_UNIT, PCA9632_ADDR, I2C_DIR_TX, I2C_TIMEOUT); // 发设备地址
if (LL_OK == i32Ret)
{
i32Ret = I2C_TransData(I2C_UNIT, &u8Reg, 1, I2C_TIMEOUT); // 写寄存器地址
if (LL_OK == i32Ret)
{
i32Ret = I2C_TransData(I2C_UNIT, pu8Data, u16Len, I2C_TIMEOUT); // 写数据
}
}
}
( void )I2C_Stop( I2C_UNIT, I2C_TIMEOUT );
}
读寄存器数据
I2C时序:START - 写I2C写设备地址 - 写寄存器地址 - START - 写I2C读设备地址 - 读数据
/**************************************************************
* @brief PCA9632读取定长数据
* @param [in] u8Reg 指定读寄存器地址
* @param [in] pu8Buf 读数据缓冲区
* @param [in] u16Len 读取数据长度
* @retval None
**************************************************************/
void PCA9632_Read(uint8_t u8Reg, uint8_t* pu8Buf, uint8_t u8Len)
{
int32_t i32Ret;
i32Ret = I2C_Start( I2C_UNIT, I2C_TIMEOUT );
if ( LL_OK == i32Ret )
{
i32Ret = I2C_TransAddr( I2C_UNIT, PCA9632_ADDR, I2C_DIR_TX, I2C_TIMEOUT ); // 发写设备地址
if ( LL_OK == i32Ret )
{
if(u8Len > 1) u8Reg |= 0x80; // 连续读(寄存器地址自增)
i32Ret = I2C_TransData( I2C_UNIT, &u8Reg, 1, I2C_TIMEOUT ); // 写寄存器地址
if ( LL_OK == i32Ret )
{
i32Ret = I2C_Restart( I2C_UNIT, I2C_TIMEOUT ); // restart信号
if ( LL_OK == i32Ret )
{
if ( 1UL == u8Len )
{
I2C_AckConfig( I2C_UNIT, I2C_NACK ); // 读寄存器长度1 发NACK
}
i32Ret = I2C_TransAddr( I2C_UNIT, PCA9632_ADDR, I2C_DIR_RX, I2C_TIMEOUT ); // 发读设备地址
if ( LL_OK == i32Ret )
{
i32Ret = I2C_MasterReceiveDataAndStop( I2C_UNIT, pu8Buf, u8Len, I2C_TIMEOUT ); // 读取数据
}
I2C_AckConfig( I2C_UNIT, I2C_ACK );
}
}
}
}
if ( LL_OK != i32Ret )
{
( void )I2C_Stop( I2C_UNIT, I2C_TIMEOUT ); // I2C 停止
}
}
软件复位
软件复位地址如下图
I2C:向设备地址0x06【7位地址为0x03】顺序写入0xA5及0x5A
执行结果:软件复位(SWRST)寻呼允许主器件通过I²C总线对PCA9632进行复位,与上电复位(POR)完全相同,将寄存器初始化为默认状态,使输出设为高阻抗。这能方便且快速地将所有器件寄存器重新配置为相同的条件。
/**************************************************************
* @brief 软复位
* @param none
* @retval None
**************************************************************/
void PCA9632_Reset(void)
{
int32_t i32Ret;
uint8_t TxBuf[5] = {0xA5, 0x5A};
i32Ret = I2C_Start( I2C_UNIT, I2C_TIMEOUT );
if(LL_OK == i32Ret)
{
i32Ret = I2C_TransAddr( I2C_UNIT, 0x03, I2C_DIR_TX, I2C_TIMEOUT ); // 发从设备写地址
if(LL_OK == i32Ret)
{
i32Ret = I2C_TransData( I2C_UNIT, TxBuf, 2, I2C_TIMEOUT ); // 写数据
}
}
I2C_Stop( I2C_UNIT, I2C_TIMEOUT );
}