一、产品概述
SK9822是一种**两线制三通道传输(RGB)**驱动智能控制电路和发光 电路于一体的LED光源控制。产品包含信号解码模块、 数据缓冲器、内置恒流电路和RC振荡器;CMOS,低电压,低功耗 消耗;256级灰度PWM调节和32级亮度调节;采用双路 输出,数据与CLK信号同步,串联各晶圆输出动作 同步。
应用领域:
- 全彩LED串灯、LED全彩模组、LED超硬超软灯、LED护栏管、LED外观/场景照明
- LED点光源、LED像素屏、LED异形屏、各种电子产品、电器设备等。
顶级SMD内部集成高品质外部控制线串联级联恒流IC;5 v应用;默认开电灯;●控制电路与RGB芯片中的SMD 5050元器件,形成完全控制像素、混色的均匀性和一致性;
●采用双线同步控制 。
●三路RGB输出控制,8Bit(256)色;5Bit(32) 调节亮度;
●三路恒流驱动,特定信号自检测功能
●最高频率30MHZ串行数据输入
●双路数据传输,内置支持不间断
二、基于STM32的SK9822灯珠控制

cpp
#include "gpio.h"
#include "head.h"
#include <string.h>
// GPIO定义(PA0=CLK,PA1=DATA,和硬件连接对应)
#define SK9822_CLK_PIN GPIO_PIN_0
#define SK9822_DATA_PIN GPIO_PIN_1
#define SK9822_GPIO_PORT GPIOA
// 电平操作宏定义
#define CLK_WBit(x) HAL_GPIO_WritePin(SK9822_GPIO_PORT, SK9822_CLK_PIN, (GPIO_PinState)x)
#define DATA_WBit(x) HAL_GPIO_WritePin(SK9822_GPIO_PORT, SK9822_DATA_PIN, (GPIO_PinState)x)
//精准CPU周期延时(STM32F405 168MHz1周期=5.95ns满足SK9822时序要求)
void SK9822_DelayCycles(uint32_t cycles) {
__IO uint32_t cnt = cycles;
while (cnt--) {
__NOP(); // 空操作,纯消耗CPU周期,无额外开销
}
}
void SK9822_SendBit(uint8_t bit) {
// 把当前位的 0/1 输出到 DATA 引脚
bit ? DATA_WBit(1) : DATA_WBit(0);
// 等数据稳定(20个CPU周期,约119ns)
SK9822_DelayCycles(20);
// 拉 CLK 引脚到高电平,SK9822 会在这个时候"采样"DATA 引脚上的位
CLK_WBit(1);
SK9822_DelayCycles(20);
// 拉 CLK 引脚到低电平,准备发送下一位
CLK_WBit(0);
SK9822_DelayCycles(20);
}
void SK9822_SendByte(uint8_t byte) {
for (uint8_t i = 0; i < 8; i++) {
// 步骤1:取当前字节的"最高位"(比如第一次循环,byte=0xFF,最高位是1)
uint8_t bit = (byte >> 7) & 0x01;
// 步骤2:把这一位发送出去(调用 SK9822_SendBit)
SK9822_SendBit(bit);
// 步骤3:字节左移1位,把"下一位"变成最高位(比如 0xFF << 1 → 0xFE,下一位还是1)
byte <<= 1;
}
}
void SK9822_SendLedFrame(uint8_t red, uint8_t green, uint8_t blue) {
//uint8_t max_bright = 0x1F;
uint8_t max_bright = 0x08;
uint8_t byte1 = (0x07 << 5) | max_bright;
uint8_t byte2 = ((blue & 0x0F) << 4) | ((blue >> 4) & 0x0F);
uint8_t byte3 = ((green & 0x0F) << 4) | ((green >> 4) & 0x0F);
uint8_t byte4 = ((red & 0x0F) << 4) | ((red >> 4) & 0x0F);
uint8_t frame[4] = {byte1,byte2,byte3,byte4};
// 发送这4字节(32位)
for(uint8_t i = 0; i < 4; i++)
{
SK9822_SendByte(frame[i]);
}
}
#if 0
void spieed_test()
{
for (uint8_t i = 0; i < 4; i++) {
SK9822_SendByte(0x00);
}
for (uint8_t i = 0; i < 32; i++) {
uint8_t red = 0xFF;
uint8_t green = 0x00;
uint8_t blue = 0x00;
SK9822_SendLedFrame(red, green, blue);
}
for (uint8_t i = 0; i < 4; i++) {
SK9822_SendByte(0xFF);
}
}
#endif
// 核心更新函数
void SK9822_UpdateLeds(uint8_t led_num, uint8_t rgb_data[][3]) {
__disable_irq(); // 禁用中断,避免时序错乱
// 起始帧:4字节0x00
for (uint8_t i = 0; i < 4; i++) {
SK9822_SendByte(0x00);
}
// 发送每颗灯的数据(只给目标灯赋值,其他全0)
for (uint8_t i = 0; i < led_num; i++) {
uint8_t red = rgb_data[i][0];
uint8_t green = rgb_data[i][1];
uint8_t blue = rgb_data[i][2];
SK9822_SendLedFrame(red, green, blue);
}
// 结束帧:4字节0xFF
for (uint8_t i = 0; i < 4; i++) {
SK9822_SendByte(0xFF);
}
SK9822_DelayCycles(50);
__enable_irq(); // 恢复中断
}
void SK9822_SingleLedOn(uint8_t led_index, uint8_t red, uint8_t green, uint8_t blue) {
uint8_t rgb[TOTAL_LED][3] = {0};
rgb[led_index][0] = red;
rgb[led_index][1] = green;
rgb[led_index][2] = blue;
SK9822_UpdateLeds(TOTAL_LED, rgb);
}
void spieed_test()
{
SK9822_SingleLedOn(LED_ROW1_U11,0x00,0x00,0x00);
}
三、基于STM32的麦克风数据的提取
cpp
#include "gpio.h"
#include "head.h"
#include <math.h>
#include <stdlib.h>
#define MIC_SCK_W(x) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13,(GPIO_PinState)x);
#define MIC_SDW_W(x) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12,(GPIO_PinState)x);
#define SPIEED_MIC_D0() HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0);
#define SPIEED_MIC_D1() HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1);
#define SPIEED_MIC_D2() HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_2);
#define SPIEED_MIC_D3() HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_3);
extern void SK9822_DelayCycles(uint32_t cycles);
extern void SK9822_SingleLedOn(uint8_t led_index, uint8_t red, uint8_t green, uint8_t blue);
void Sipeed_MIC_Init(void)
{
MIC_SCK_W(1);
MIC_SDW_W(1);
}
uint32_t Sipeed_read_left(uint8_t mic)
{
uint8_t i = 0;
uint32_t data = 0;
int ret = 0;
SK9822_DelayCycles(325);
MIC_SDW_W(0);
for(i = 1; i <= 32; i++)
{
MIC_SCK_W(1);
if (i >= 2 && i <= 25)
{
if (mic == 0)
{
ret = SPIEED_MIC_D0();
data |= ret << (33-i);
}
else if (mic == 1)
{
ret = SPIEED_MIC_D1();
data |= ret << (33-i);
}
else if (mic == 2)
{
ret = SPIEED_MIC_D2();
data |= ret << (33-i);
}
}
MIC_SCK_W(0);
}
return data;
}
uint32_t Sipeed_read_right(uint8_t mic)
{
uint8_t i = 0;
uint32_t data = 0;
int ret = 0;
SK9822_DelayCycles(325);
MIC_SDW_W(1);
for(i = 1; i <= 32; i++)
{
MIC_SCK_W(1);
if (i >= 2 && i <= 25)
{
if (mic == 0)
{
ret = SPIEED_MIC_D0();
data |= ret << (33-i);
}
else if (mic == 1)
{
ret = SPIEED_MIC_D1();
data |= ret << (33-i);
}
else if (mic == 2)
{
ret = SPIEED_MIC_D2();
data |= ret << (33-i);
}
else if (mic == 3)
{
ret = SPIEED_MIC_D3();
data |= ret << (33-i);
}
}
MIC_SCK_W(0);
}
return data;
}
void qqqqqqqqq_test()
{
uint32_t data = 0;
uint32_t data2 = 0;
data = Sipeed_read_left(0);
data2 = Sipeed_read_right(0);
printf("mic0:%u\r\n",data);
printf("mic1:%u\r\n",data2);
data = Sipeed_read_left(1);
data2 = Sipeed_read_right(1);
printf("mic2:%u\r\n",data);
printf("mic3:%u\r\n",data2);
data = Sipeed_read_left(2);
data2 = Sipeed_read_right(2);
printf("mic4:%u\r\n",data);
printf("mic5:%u\r\n",data2);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 简化的数据采集函数 - 直接使用平均值
int Mic_GetAverages(int avg_buf[]) {
uint32_t temp_buf[10] = {0};
uint32_t sum = 0;
// 左声道麦克风 0,1,2
for (int mic_idx = 0; mic_idx < 3; mic_idx++) {
sum = 0;
for (int j = 0; j < 10; j++) {
temp_buf[j] = Sipeed_read_left(mic_idx);
sum += temp_buf[j];
}
// 直接使用平均值
avg_buf[mic_idx] = (int)(sum / 10000);
}
// 右声道麦克风 0,1,2
for (int mic_idx = 0; mic_idx < 3; mic_idx++) {
sum = 0;
for (int j = 0; j < 10; j++) {
temp_buf[j] = Sipeed_read_right(mic_idx);
sum += temp_buf[j];
}
// 直接使用平均值
avg_buf[mic_idx + 3] = (int)(sum / 10000);
}
return 0;
}
// 声源定位函数
int Spieed_MIC_Sample()
{
int first_averages[6] = {0};
int max_value = 0;
int max_idx = 0;
// 1. 采集数据:获取6个采样点的平均值(存入first_averages)
Mic_GetAverages(first_averages);
// 2. 调试输出:打印每个采样点的平均值
for (int i = 0; i < 6; i++) {
printf("Mic%d----first_averages=%d\r\n", i + 1, first_averages[i]);
}
// 3. 找出 first_averages 中的最大值及对应索引
max_value = first_averages[0];
max_idx = 0;
for (int i = 1; i < 6; i++) {
if (first_averages[i] > max_value) {
max_value = first_averages[i];
max_idx = i;
}
}
// 4. 打印最大值结果
printf("Max value: %d, at Mic%d\n", max_value, max_idx + 1);
return max_idx;
}
// 主控制函数
void Thr_MIC_Con_LED()
{
while(1) {
int ret = Spieed_MIC_Sample();
SK9822_SingleLedOn(ret * 2, 0x00, 0x00, 0xFF);
printf("Stable detection: Mic%d\n", ret);
HAL_Delay(500); // 缩短延迟提高响应速度
}
}
打印段可以提取出来数据,但是数据并不准确和灵敏,简单的对sipeed mic的了解,后续有继续跟进的话会及时更新代码的