一、P9813 是什么?
P9813 是一颗专门用来控制 RGB LED灯珠 的芯片,也就是说,它能控制红色、绿色、蓝色三种灯光的亮度,从而调出各种颜色。它最常见的用途就是在各种“会变色”的灯带中。
它的通信方式非常简单,只需要两根线就能控制——一根叫 时钟线(CLK),一根叫 数据线(DI)。
二、芯片的14个管脚(引脚)都干嘛用?
芯片的“脚”就像人的手脚,是用来输入输出电信号的。我们来一个个看看:
引脚编号 | 名称 | 功能描述 | 通俗解释 |
---|---|---|---|
1 | DO | 数据输出 | 把“指令”传给下一个芯片 |
2 | GND | 地线 | 电子的“回家路”,所有电路的基准点 |
3 | DI | 数据输入 | 接收“主控”来的控制指令 |
4 | VDD | 电源正极 | 给芯片“吃饭”的地方(通常是5V) |
5 | GND | 地线 | 同上,多个GND是为了更稳定 |
6 | GND | 地线 | 同上 |
7 | GND | 地线 | 同上 |
8 | GND | 地线 | 同上 |
9 | GND | 地线 | 同上 |
10 | GND | 地线 | 同上 |
11 | GND | 地线 | 同上 |
12 | GND | 地线 | 同上 |
13 | CLK | 时钟输入 | 像是节拍器,告诉数据什么时候该“走” |
14 | CO | 时钟输出 | 把时钟信号继续传给下一个芯片 |
💬 小贴士:
DI 和 CLK 是输入引脚:接收主控的“命令”和“节奏”,我们配置IO口 推挽输出。
DO 和 CO 是输出引脚:把命令和节奏“接力”给下一个芯片。
GND 是地线,VDD 是电源,少了它们芯片就“饿死”了。
三、内部结构框图:P9813 的“工作原理图
我们可以把 P9813 看成一个“信号处理站”,它接收来自上一级控制器(比如 Arduino、ESP32,STM32)的指令,然后根据这些指令控制LED的颜色亮度。
下面是简化版的功能框图(我可以提供视觉图,你要不要配图?):
控制器(比如Arduino)
↓
┌────────────┐
│ P9813芯片 │
│ │
SDI ──▶│ 接收数据 │──▶ SDO
CKI ──▶│ 接收时钟 │──▶ CKO
│ │
│ 解码命令 │
│ 控制RGB输出 │
└────────────┘
↓ ↓ ↓
OUTR OUTG OUTB
四、通信协议和时序:芯片之间怎么“对话”?
P9813 使用一种叫 串行同步通信协议 的方式工作,只用两根线:数据线(SDI) 和 时钟线(CKI),非常节省资源。
通信规则简单说就是:
-
控制器按照一定格式发出 32位的数据包(包含颜色值和校验信息);
-
每来一个时钟脉冲,芯片就“读入”一位数据;
-
数据读取完毕后,芯片自动处理颜色并输出给LED;
注意
标志位:默认为 1 1
B7 B6:是蓝色数据八位取前二位取反
G7 G6 R7 R6:同理
后面24位就是蓝色 绿色 红色的24位数据,
将些数据全部储存到一个32位数据,32位数据包
软件配置
rgb.h
#ifndef _RGB_H_
#define _RGB_H_
#include "stm32f10x.h"
void RGB_Init();
void RGB_Contral(u8 r,u8 g,u8 b);
#define RGB_CCLK_H GPIO_SetBits(GPIOB,GPIO_Pin_8);
#define RGB_CCLK_L GPIO_ResetBits(GPIOB,GPIO_Pin_8);
#define RGB_DATE_H GPIO_SetBits(GPIOB,GPIO_Pin_9);
#define RGB_DATE_L GPIO_ResetBits(GPIOB,GPIO_Pin_9);
#endif
rgb.c
#include "rgb.h"
#include "delay.h"
//初始化
void RGB_Init()
{
//打开GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//初始化GPIO口为推挽输出
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 ;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init (GPIOB, &GPIO_InitStruct);
RGB_CCLK_H;
}
//标志位:默认为 1 1
//B7 B6:是蓝色数据八位取前二位取反
//G7 G6 R7 R6:同理
//后面24位就是蓝色 绿色 红色的24位数据,
//将些数据全部储存到一个32位数据,32位数据包
u32 color_mer(u8 r,u8 g,u8 b)
{
u32 color = 0;
color |= (0x3u << 30); // 标志位
color |= (~((u8)b >> 6) << 28); //将蓝色前两位进行取反,放到color的29 28位
color |= (~((u8)g >> 6) << 26); //将蓝色前两位进行取反,放到color的27 26位
color |= (~((u8)r >> 6) << 24); //将蓝色前两位进行取反,放到color的25 24位
color |= (b<<16);
color |= (g<<8);
color |= r;
return color;
}
//根据协议发送数据
//上升沿采集数据 RGB芯片可以接收数据
//下降沿准备数据 就是MCU可以发送数据了
//用IO口模拟
void send_date(u32 word)
{
u32 i ;
for(i = 0; i<32; i++)
{
RGB_CCLK_L;
if(word & (0x80000000 >> i))
{
RGB_DATE_H;
}
else
RGB_DATE_L;
delay_us(5);
RGB_CCLK_H;
delay_us(5);
}
}
//RGB控制函数
void RGB_Contral(u8 r,u8 g,u8 b)
{
u32 color = color_mer(r, g, b);
send_date(0x00000000);//有一个起始帧
send_date(color);
send_date(color);
}