找回密码
 立即注册
查看: 248|回复: 2

点个幻彩灯 何必单恋WS2812可以看看APA102@2线制,标准SPI

[复制链接]
  • 打卡等级:以坛为家III
  • 打卡总天数:702
  • 最近打卡:2026-03-31 09:53:17
已绑定手机

49

主题

2648

回帖

2895

积分

荣誉版主

积分
2895
发表于 2026-1-16 16:20:56 | 显示全部楼层 |阅读模式
说到幻彩灯,大家似乎只有WS2812一种选择,其实不然
今天说说APA102,兼容型号为SK9822,一款同步二线驱动的幻彩LED,
先说它的缺点:
  • 比WS2812多占一条口线
  • 成本略高

再说它的优点:
  • 双线同步传输,非异步操作,不挑单片机IO速度,代码不必严格时序,不必担心中断影响时序,稳如老狗,完全没有单总线的硬伤
  • CLK时钟速度高达20MHz,远超WS2812的800kHz,刷新速率30帧/秒时,级联数超过25600,远超WS2812的1024点
  • 原生支持硬件SPI和SPI DMA,,单个LED对应32bit数据,正好4字节,单片机资源占用超小,速度快到飞起
  • 5位全局亮度,高频PWM调光,物理不闪,WS2812只能缩放RGB调光
  • 支持增加缓冲门用作远传中继,

截图202601161607393444.jpg
测试电路如下:
截图202601161617341204.jpg

~~~
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:702
  • 最近打卡:2026-03-31 09:53:17
已绑定手机

49

主题

2648

回帖

2895

积分

荣誉版主

积分
2895
发表于 2026-1-16 16:29:41 | 显示全部楼层
  1. #include "def.h"
  2. #include <intrins.h>
  3. #include "AI8G.h"
  4. #define SCL_H P54 = 1  //APA102C的时钟输入SCK  
  5. #define SCL_L P54 = 0
  6. #define DIN_H P55 = 1  //APA102C的串口数据输入DI
  7. #define DIN_L P55 = 0
  8. #define NUM_LEDS 1                //灯串的规模
  9. #define BRIGHTNESS 10  //0~31
  10. struct CRGB {
  11.         u8 r,g,b;
  12. };
  13. bit flag;
  14. struct CRGB leds[NUM_LEDS];  //显存
  15. void APA_send(u8 dat)  //IO模拟方式
  16. {
  17.         u8 i;
  18.         for(i=0;i<8;i++){
  19.                 if(dat & 0x80)  DIN_H;
  20.                 else               DIN_L;
  21.                 //NOP1();        //实测主频35MHz时都不需要NOP,
  22.                 SCL_H;
  23.                 //NOP1();          //实测主频35MHz时都不需要NOP,
  24.                 SCL_L;
  25.                 dat <<= 1;
  26.         }
  27. }
  28. void APA_send(u8 dat)  //硬件SPI方式
  29. {
  30.         SPDAT = dat;                           //发送测试数据
  31.         while (!(SPSTAT & 0x80));               //查询完成标志
  32.         SPSTAT = 0xc0;                          //清中断标志
  33. }
  34. void set_color(u16 index,u8 r,u8 g,u8 b){                //设置灯串中第index个灯的颜色
  35.         if(index >= 0 && index <NUM_LEDS){
  36.                 leds[index].r = r;
  37.                 leds[index].g = g;
  38.                 leds[index].b = b;
  39.         }
  40. }
  41. void show_led(void){
  42.         u8 i,ctrl;
  43.         for(i=0;i<4;i++)  APA_send(0x00);  //发送32bit前导 否则首灯不亮
  44.         for(i=0;i<NUM_LEDS;i++){
  45.                 ctrl = 0xE0 | (BRIGHTNESS & 0x1F);
  46.                 APA_send(ctrl);                        //填充亮度
  47.                 APA_send(leds[i].b);        //填充蓝色
  48.                 APA_send(leds[i].g);        //填充绿色
  49.                 APA_send(leds[i].r);        //填充红色
  50.         }
  51.         APA_send(0xFF);                //填充结束帧
  52.         APA_send(0xFF);                //填充结束帧
  53. }
  54. void Timer0_Isr(void) interrupt 1
  55. {
  56.         static u8 i,j;
  57.         switch (i)
  58.         {
  59.                 case 0:
  60.                         set_color(0,j,0,0);//红色渐变
  61.                         if(j++ > 250)        {j = 0;        i++;}
  62.                         break;
  63.                 case 1:
  64.                         set_color(0,0,j,0);//绿色渐变
  65.                         if(j++ > 250)        {j = 0;        i++;}
  66.                         break;                        
  67.                 case 2:
  68.                         set_color(0,0,0,j);//蓝色渐变
  69.                         if(j++ > 250)        {j = 0;        i++;}
  70.                         break;
  71.                 case 3:
  72.                         set_color(0,j,j,0);//黄色渐变
  73.                         if(j++ > 250)        {j = 0;        i++;}
  74.                         break;
  75.                 case 4:
  76.                         set_color(0,0,j,j);//靛色渐变
  77.                         if(j++ > 250)        {j = 0;        i++;}
  78.                         break;                        
  79.                 case 5:
  80.                         set_color(0,j,0,j);//紫色渐变
  81.                         if(j++ > 250)        {j = 0;        i++;}
  82.                         break;
  83.                 case 6:
  84.                         set_color(0,j,j,j);//白色渐变
  85.                         if(j++ > 250)        {j = 0;        i = 0;}
  86.                         break;
  87.                 default:
  88.                         break;        
  89.         }
  90.         show_led();        //刷新显示
  91. }
  92. void Timer0_Init(void)                //10毫秒@12.000MHz
  93. {
  94.         AUXR &= 0x7F;                        //定时器时钟12T模式
  95.         TMOD &= 0xF0;                        //设置定时器模式
  96.         TL0 = 0xF0;                                //设置定时初始值
  97.         TH0 = 0xD8;                                //设置定时初始值
  98.         TF0 = 0;                                //清除TF0标志
  99.         TR0 = 1;                                //定时器0开始计时
  100.         ET0 = 1;                                //使能定时器0中断
  101. }
  102. void main()
  103. {
  104.     P_SW2 = 0x80;
  105.     P3M0 = 0x00; P3M1 = 0x00;
  106.     P5M0 = 0x30; P5M1 = 0x00; //CLK & DI PP_OUT
  107.     SPCTL = 0x50;           //SPI Master CLK = SYS/4
  108.     SPSTAT = 0xc0;          //Clear Flag
  109.    Timer0_Init();   
  110.    EA = 1;
  111.    while(1);               
  112. }
复制代码



~~~
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:280
  • 最近打卡:2026-03-31 08:02:14
已绑定手机

4

主题

87

回帖

405

积分

中级会员

积分
405
发表于 2026-1-29 19:12:56 | 显示全部楼层
点赞
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-4-1 08:57 , Processed in 0.493948 second(s), 52 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表