吽吽吽 发表于 2022-12-29 23:02:16

求助:DMA_SPI驱动WS2812B

芯片:STC8H4K64TLCD
功能:DMA_SPI模拟WS2812B数据

MOSI口:P3.4,外接2K下拉电阻

程序:

#include<STC8H.H>
#include<absacc.h>
#include<stdio.h>
#include<math.h>
#include <intrins.h>

//多次测试得不到想要验收,全部置零,5颗WS2818B驱动的全彩LED。
unsigned char xdata LED_DATA={0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
                                                      0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
                                                      0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
                                                      0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
                                                      0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,};      
char *LED=&LED_DATA;
char (*R)=&RGB;
int xdata ENSPI=0;    //DMA_SPI开始标志

/*------------------延时,WS2812B归零---------------*/
void Delay50us()                //@32MHz
{
      unsigned char i, j;

      i = 3;
      j = 17;
      do
      {
                while (--j);
      } while (--i);
}


/*------------------------------------------------------
DMA_SPI输出
SPIIF SPI中断 用于判断SPI是否完成
输出完成关闭SPI,P3.4输出低电平
--------------------------------------------------------*/
void SPI()
{
ENSPI=DMA_SPI_CR;
ENSPI&=0xC0;
if(ENSPI==0)
{
      P34=0;
      Delay50us();               
      DMA_SPI_AMT=119;   //传输168字节。24*5=120字节
      DMA_SPI_TXA=LED_DATA;//数据起始位。
      SPCTL=0xD7;//1101 01116.使能SPI5主机模式,4空闲时钟线低电平,3前沿写 2后沿读 1:0主时钟2分频 16Mhz”         
      DMA_SPI_CR=0xC0;    //11000000 开始DMA_SPI
}
}
//DM_SPI中断
void DMA_SPI_Routine(void)interrupt 49
{
SPCTL=0x00;//关闭SPI
P34=0;
DMA_SPI_CR=0x00; //关闭SPI_DMA
DMA_SPI_STA=0x00;//中断标志位清零      
}



void main()
{
CLKSEL=0;               //内部高速时钟 下载设置25.6MHZ
EA=1;                     //打开总中断
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x7f;
P3M0 = 0x10; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;               
/*---------------------SPI设置-----------------------------------------*/
P_SW2|=128;         //1000 0000 允许访问片内SFR0FA00H~0FFFFHFB50-FB6F 触摸阈值寄存器      
P_SW1=12;             //00-- **0- MOSI输出设置P3.4 **=11
AUXR=0;            //允许访问内部扩展RAM      
DMA_SPI_CFG2=4;    //00000100 不使用SS脚 SS脚P1.2”
DMA_SPI_CFG=0xCF;    //1100 1111,允许DMA_SPI中断,允许发送禁止接收数据,中断优先最高 访问级最大

while(1)
{      
SPI();      
}
}


SCLK与MOSI脚波形


DMA_SPI传输时,每两个数据有500ns的时间间隙,间隙期间MOSI为高电平。
请问:在MOSI脚外部增加三极管反向电路能否行得通。是否有其他办法使得2个数据间隙MOSI为低电平

吽吽吽 发表于 2022-12-30 21:41:38

外加反向电路,问题解决了,能得到需要的延时了,另外如果外加三极管的话,要注意三极管截止时间问题。另外需要注意归零延时,短了会导致前面几颗LED不亮

神农鼎 发表于 2022-12-31 08:01:35

MOSI口:P3.4,外接2K下拉电阻===为何 2K 下拉电阻,一般是加10K 上拉,加下拉的目的 ? 非要加 ? 10K ?

吽吽吽 发表于 2022-12-31 16:41:15

神农鼎 发表于 2022-12-31 08:01
MOSI口:P3.4,外接2K下拉电阻===为何 2K 下拉电阻,一般是加10K 上拉,加下拉的目的 ? 非要加 ? 10K ? ...

最初未考虑外部反向电路,WS2812B需要50us以上的低电平才能按接收到的数据点亮LED。下拉的目的是考虑DMA_SPI发送完成,关闭SPI后 P3.4自动输出低电平。思路没错,能点亮LED,但是因为DMA_SPI传输2个字节之间有500ns的间隙,这个时间MOSI是高电平。导致LED不能显示设置的颜色。所以最终是取消这个下拉电阻外加反向电路解决这个问题的。

Hssa 发表于 2023-8-12 17:38:26

您好,硬件原理图能给一份嘛

神农鼎 发表于 2024-1-9 08:48:21

SPI方案:
只用到MOSI驱动WS2812,但由于SPI的3个信号是捆绑在一起的,MISO、SCLK不能做它用。本例使用P1.3-MOSI输出驱动信号,用户可以切换到别的脚。
===将 MISO 不做其他用途;
===将 MISO管脚 先设置为对外输出0;
===MOSI 发送完成后,对外停止时输出的是 MISO 读到的状态, 0 ,这 STC-R&D 留了这么个绝活支持 WS2812B !!!

页: [1]
查看完整版本: 求助:DMA_SPI驱动WS2812B