找回密码
 立即注册
查看: 540|回复: 10

【SPI操纵WS2812】基于擎天柱的RGB驱动方案,纯走硬件,杜绝软件延时卡顿占用空间

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:402
  • 最近打卡:2025-05-01 11:09:19
已绑定手机

51

主题

138

回帖

1494

积分

金牌会员

积分
1494
发表于 2025-1-12 23:36:18 | 显示全部楼层 |阅读模式
/****************************************************************
本次实验的SPI分组为P14  P15  P16  P17
                                                                         SS  MOSI MISO  SCK
请将RGB的DIN引脚接到AI8051U的P15引脚进行实验

重头戏在时钟配置函数(Sys.c中)将SPI转到高速SPI达到了刚好的3.2MHZ,
因为高速SPI(HSPI)通过PLL锁相环时钟,输出96MHZ给高速IO时钟,然后高速
SPI的时钟源是高速IO时钟,然后经过15分频后,在SPI配置中又进行了2分频,
所以最后的SPI工作频率是15分频和2分频叠加成了30MHZ,然后就有了SPI时钟
频率为:96/15/2=3.2MHZ,这个是非常合适的时钟频率,接下来就是考虑RGB的
1个时序该多久了,WS2812的时序是800K码率,也就是1个时序需要1250ns的时
间,那么0码是1/4的高电平和3/4的低电平;1码是3/4高电平和1/4低电平.那么
就是总共是1250ns,1/4时长是312.5ns,3/4时长是937.5ns,那我是不是SPI写
1个位就是(1000000/3.2MHZ)=312.5ns,刚好是1/4的占空比,那么我SPI写3个
位就是937.5ns了,通过这个原理,我们就可以通过SPI写4个位来实现0码/1码,
那么SPI一次性写8个位(1个字节)就是可以写2个0码/1码了
那么我们将G、R、B分别提取出来,8位的数据我们1次SPI的操作就可以判断2
位该写0还是写1,这样子1次SPI操作就可以写掉2位的RGB值了,1个颜色用4次
SPI操作来写,那么SPI的字节数总共就是4*3=12了

至于高速SPI,需要将SPI的输出口(MOSI和SCK)引脚设置为高速模式,在本次实
验中,需要将P14 P15 P17加内部上拉电阻,P16加内部下拉电阻,并且设置P15
和P17为推挽输出,P16为高阻输入+下拉电阻,这样MOSI输出完成后才会是低
电平

至此,龙场悟道!!!!

****************************************************************/

3、RGB实验.zip

393.06 KB, 下载次数: 40

用尽STC单片机的资源是我的梦想
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-1-13 10:05:23 | 显示全部楼层
  1. #include <AI8051U.H>
  2. #include <intrins.h>
  3. #include <absacc.h>
  4. #include <string.h>
  5. #include <stdarg.h>
  6. #include <stdio.h>
  7. #include <math.h>
  8. #define                FOSC                        40000000UL                                        //主时钟
  9. unsigned char Poi;
  10. //void delay_ms(unsigned char ms)
  11. //{
  12. //        unsigned int i;
  13. //        do
  14. //        {
  15. //                i=FOSC/6000;
  16. //                while(--i);        //6T per loop
  17. //        }
  18. //        while(--ms);
  19. //}
  20. void SPI_T(unsigned char x)
  21. {
  22.         unsigned char temp;
  23.         temp=(SBUF<<(x*2))&0xC0;
  24.         SPDAT=((temp&0x80)?0xE0:0x80)|((temp&0x40)?0x0E:0x08);
  25. }
  26. void Init(void)
  27. {
  28.         WTST=0;                                        //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  29.         EAXFR=1;                                //扩展寄存器(XFR)访问打开
  30.         CKCON=0;                                //提高访问XRAM速度
  31.         IAP_TPS=40;
  32.         IRCDB=128;
  33.        
  34.         P0M1=0x00;        P0M0=0x00;        //设置为准双向口
  35.         P1M1=0x00;        P1M0=0x00;        //设置为准双向口
  36.         P2M1=0x00;        P2M0=0x00;        //设置为准双向口
  37.         P3M1=0x00;        P3M0=0x00;        //设置为准双向口
  38.         P4M1=0x00;        P4M0=0x00;        //设置为准双向口
  39.         P5M1=0x00;        P5M0=0x00;        //设置为准双向口
  40.         P6M1=0x00;        P6M0=0x00;        //设置为准双向口
  41.         P7M1=0x00;        P7M0=0x00;        //设置为准双向口
  42.        
  43.         S1_S1=0;                //UART1_2
  44.         S1_S0=1;                //UART1_2
  45.         S1BRT=0;                //选择TMR1作为UART1波特率发生器
  46.         T1x12=1;                //设置TMR1为1T模式
  47.         TH1=0xFF;                //设置UART1波特率(250Kbps@40MHz)
  48.         TL1=0xD8;                //设置UART1波特率(250Kbps@40MHz)
  49.         SMOD0=1;                //打开帧错误检测
  50.         SM1=1;                        //设置UART1模式为9位数据可变波特率
  51.         REN=1;                        //允许UART1接收数据
  52.         TR1=1;                        //打开定时器1
  53.         ES=1;                        //打开UART1中断
  54.        
  55.         SPI_S1=1;                //SPI_3
  56.         SPI_S0=0;                //SPI_3
  57.         SPI_CLKDIV=3;        //SPI时钟3分频
  58.         SPR1=1;                        //SPI输入时钟/2
  59.         SPR0=1;                        //SPI输入时钟/2
  60.         SSIG=1;                        //忽略SS引脚功能,使用MSTR确定器件是主机还是从机
  61.         DORD=0;                        //先发送/接收数据的高位(MSB)
  62.         MSTR=1;                        //设置主机模式
  63.         CPOL=0;                        //SCLK空闲时为低电平,SCLK的前时钟沿为上升沿,后时钟沿为下降沿
  64.         CPHA=1;                        //数据在SCLK的前时钟沿驱动,后时钟沿采样
  65.         SPSTAT=0xC0;        //清除SPI中断标志、清除SPI写冲突标志
  66.         SPEN=1;                        //打开SPI功能
  67.         ESPI=1;                        //打开SPI中断
  68.        
  69.         EA=1;
  70. }
  71. void main(void)
  72. {
  73.         Init();
  74.         while(1)
  75.         {
  76.                
  77.         }
  78. }
  79. void UART1_Isr(void) interrupt UART1_VECTOR
  80. {
  81.         bit sync;
  82.         if(RI)
  83.         {
  84.                 RI=0;
  85.                 if(SM0)
  86.                 {
  87.                         SM0=0;
  88.                         sync=1;
  89.                 }
  90.                 else
  91.                 {
  92.                         if(sync)
  93.                         {
  94.                                 sync=0;
  95.                         }
  96.                         else
  97.                         {
  98.                                 Poi=0;
  99.                                 SPI_T(Poi);
  100.                         }
  101.                 }
  102.         }
  103.         if(TI)
  104.         {
  105.                 TI=0;
  106.         }
  107. }
  108. void SPI_Isr(void) interrupt SPI_VECTOR
  109. {
  110.         SPSTAT|=0x80;
  111.         if(Poi<3)
  112.         {
  113.                 SPI_T(++Poi);
  114.         }
  115. }
复制代码


点评

我直接用40M分频 40/12=3.3333333  详情 回复 发表于 2025-1-13 10:07
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-1-13 10:07:34 | 显示全部楼层

我直接用40M分频
40/12=3.3333333
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:402
  • 最近打卡:2025-05-01 11:09:19
已绑定手机

51

主题

138

回帖

1494

积分

金牌会员

积分
1494
发表于 2025-1-13 13:50:59 | 显示全部楼层
Debu*** 发表于 2025-1-13 08:07
我直接用40M分频
40/12=3.3333333

欧欧欧大佬还是牛,我不确定是不是SPI_CLKDIV可以控制普通SPI,因为那里写的是高速SPI分频,所以我还得启用高速SPI

点评

[attachimg]80403[/attachimg]  详情 回复 发表于 2025-1-13 14:15
用尽STC单片机的资源是我的梦想
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:402
  • 最近打卡:2025-05-01 11:09:19
已绑定手机

51

主题

138

回帖

1494

积分

金牌会员

积分
1494
发表于 2025-1-13 13:51:41 | 显示全部楼层
Debu*** 发表于 2025-1-13 08:07
我直接用40M分频
40/12=3.3333333

就是这玩意吧挺严格的,分频不好分,要不就是直接,48/15=3.2MHZ

点评

8051U跑不了48M  详情 回复 发表于 2025-1-13 14:13
用尽STC单片机的资源是我的梦想
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:402
  • 最近打卡:2025-05-01 11:09:19
已绑定手机

51

主题

138

回帖

1494

积分

金牌会员

积分
1494
发表于 2025-1-13 13:52:21 | 显示全部楼层
Debu*** 发表于 2025-1-13 08:07
我直接用40M分频
40/12=3.3333333

但是主频无法跟STC32F比,那个主频比较低,这个分频也是不好分,STC单片机也没有倍频器,所以很难搞
用尽STC单片机的资源是我的梦想
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-1-13 14:13:13 | 显示全部楼层
陈*** 发表于 2025-1-13 13:51
就是这玩意吧挺严格的,分频不好分,要不就是直接,48/15=3.2MHZ

8051U跑不了48M
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-1-13 14:15:11 | 显示全部楼层
陈*** 发表于 2025-1-13 13:50
欧欧欧大佬还是牛,我不确定是不是SPI_CLKDIV可以控制普通SPI,因为那里写的是高速SPI分频,所以我还得启 ...

截图202501131415013973.jpg
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:402
  • 最近打卡:2025-05-01 11:09:19
已绑定手机

51

主题

138

回帖

1494

积分

金牌会员

积分
1494
发表于 2025-1-13 14:44:43 | 显示全部楼层

最高42MHZ,有时候限制了发挥,还是得高主频才不用掉头发
用尽STC单片机的资源是我的梦想
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:402
  • 最近打卡:2025-05-01 11:09:19
已绑定手机

51

主题

138

回帖

1494

积分

金牌会员

积分
1494
发表于 2025-1-13 14:45:14 | 显示全部楼层

以前的SPI我拿来就用,现在折腾了这个时钟,理解更深刻了
用尽STC单片机的资源是我的梦想
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-1 22:04 , Processed in 0.122002 second(s), 115 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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