OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 15132|回复: 15

stm32 f407 控制ws2812问题

[复制链接]

17

主题

63

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2015-9-24
在线时间
14 小时
发表于 2016-7-5 16:05:13 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 笨鸟先飞鱼 于 2016-7-5 16:14 编辑


控制ws2812   ,单线归零协议,相同周期,不同的高低电平时间,代表“1”和“0”。

现在用stm32 f407   控制ws2812灯珠, 采用网上别人所说的,用DMA传输+PWM的方式,  就是用DMA传输,传过来不同的占空比值,也就是DMA传过来的值,控制不同的CCR1的值,
我现在最大的疑惑在于,如何实现同步?
如何恰好在pwm走完一个周期时,pwm的占空比被改变?

请大神指点下,如何用DMA+PWM的方式,来实现具体的某个波形的占空比是由自己控制的。或者谁有f407控制ws2812灯珠的程序,发一份也行。 (自己用软件延时的就不需要了)

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

87

主题

331

帖子

0

精华

高级会员

Rank: 4

积分
906
金钱
906
注册时间
2016-3-26
在线时间
116 小时
发表于 2016-7-5 16:08:43 | 显示全部楼层
回复

使用道具 举报

17

主题

63

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2015-9-24
在线时间
14 小时
 楼主| 发表于 2016-7-5 16:15:32 | 显示全部楼层

按了下回车,就发出来了。是想请教f407控制ws2812的问题。
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165377
金钱
165377
注册时间
2010-12-1
在线时间
2111 小时
发表于 2016-7-6 21:47:41 | 显示全部楼层
帮顶
回复

使用道具 举报

17

主题

63

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2015-9-24
在线时间
14 小时
 楼主| 发表于 2016-7-7 10:58:10 | 显示全部楼层
http://www.openedv.com/forum.php ... mp;highlight=ws2812

原子哥,我是按照这个思路写的程序,自己固定占空比 pwm 波输出就正常,但是一用上DMA和控制CCR1,根本就没波形输出,求解答。
回复

使用道具 举报

17

主题

63

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2015-9-24
在线时间
14 小时
 楼主| 发表于 2016-7-7 16:35:46 | 显示全部楼层
本帖最后由 笨鸟先飞鱼 于 2016-7-7 16:38 编辑

查资料,有人说 用DMA+TIM。TIM_CHx设置成PWM输出,用update中断触发DMA更新CCRx的值。

请问如何实现用update中断触发DMA更新CCRx的值
回复

使用道具 举报

17

主题

63

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2015-9-24
在线时间
14 小时
 楼主| 发表于 2016-7-7 17:11:53 | 显示全部楼层

我现在能够想到的就是 定时器计数值达到CCR的值时,产生一个中断,在中断函数里,改变下一个CCR的值。这样就实现了占空比可调的PWM波,原子哥觉得这样对吗?有什么好的建议或者查阅哪些资料?
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2017-12-29
在线时间
7 小时
发表于 2017-12-29 17:32:27 | 显示全部楼层
我用的是STM32F407ZET6,使用功能的是DMA传输+PWM的方式,我使用的是TIM3->CCR3,通道选择的是DMA1_Stream7,DMA_Channel_5,这个是stm32f407芯片内部规定好的。
下面是程序
#include  "WS2812B.h"
#include "stm32f4xx_dma.h"//#include "stm32f10x_dma.h"
//#include "stm32f10x.h"
#include "stm32f4xx_tim.h"//#include "stm32f10x_tim.h"
#include "stdio.h"
#include "dma.h"
/* Buffer that holds one complete DMA transmission
*
* Ensure that this buffer is big enough to hold
* all data bytes that need to be sent
*
* The buffer size can be calculated as follows:
* number of LEDs * 24 bytes + 42 bytes
*
* This leaves us with a maximum string length of
* (2^16 bytes per DMA stream - 42 bytes)/24 bytes per LED = 2728 LEDs
*/
#define TIM3_CCR3_Address 0x4000043c         // physical memory address of Timer 3 CCR1 register
//#define TIM3_CCR1_Address 0x40000434        // physical memory address of Timer 3 CCR1 register
       
#define TIMING_ONE  59
#define TIMING_ZERO 29
uint16_t LED_BYTE_Buffer[300];//注意  这里最多能使用10个灯,有上线
//---------------------------------------------------------------//





  void TIM_Config(void)
{
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;


        GPIO_InitTypeDef GPIO_InitStructure;
        DMA_InitTypeDef DMA_InitStructure;
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM3);  //端口B0复用为定时器3
  /* GPIOA and GPIOB clock enable */
  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB, ENABLE);

  /* GPIOA Configuration: Channel 3 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;  //
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  //复用功能
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //速度50M
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;     //推挽复用
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;  //不上拉也不下拉
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化端口
       






        MYDMA_Config(DMA1_Stream7,DMA_Channel_5,(u32)&TIM3->CCR3,(u32)LED_BYTE_Buffer,43,DMA_PeripheralDataSize_HalfWord);//DMA1,STEAM7,CH5,外设定时器3的通道3,存储器为SendBuff,长度为:SEND_BUF_SIZE.


        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

        TIM_TimeBaseStructure.TIM_Period = 105-1;   //自动重装载值  频率是800khz
        TIM_TimeBaseStructure.TIM_Prescaler = 0;   //定时器分频
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数模式
        TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;        //时钟分频
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

        /* PWM1 Mode configuration: Channel1 */
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //选择定时器模式:TIM脉冲宽度调制模式1
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  //比较输出使能
        TIM_OCInitStructure.TIM_Pulse =0;//待装入捕获比较寄存器的脉冲值  30
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //输出极性:TIM输出比较极性高
        //TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Set;
        TIM_OC3Init(TIM3, &TIM_OCInitStructure);
  TIM3->CR2=0x0008;
  /* Enable preload feature */
//  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
  
  /* TIM1 counter enable */
//  TIM_Cmd(TIM3, ENABLE);
  
  /* DMA enable*/
//  DMA_Cmd(DMA1_Stream7, ENABLE);
  
  /* TIM3 Update DMA Request enable */
  TIM_DMACmd(TIM3, TIM_DMA_CC3 , ENABLE);

  /* Main Output Enable */
// TIM_CtrlPWMOutputs(TIM3, ENABLE);//注意  这里如果是高级定时器,需要打开才能用pwm输出


}







/* This function sends data bytes out to a string of WS2812s
* The first argument is a pointer to the first RGB triplet to be sent
* The seconds argument is the number of LEDs in the chain
*
* This will result in the RGB triplet passed by argument 1 being sent to
* the LED that is the furthest away from the controller (the point where
* data is injected into the chain)
/ *此函数将数据字节发送到WS2812的字符串
*第一个参数是指向要发送的第一个RGB三元组的指针
* seconds参数是链中的LED数量
*:
*这将导致通过参数1传递的RGB三元组发送到
*离控制器最远的LED(
*数据被注入链中
*/
void WS2812_send(uint8_t (*color)[3], uint16_t len)
{
        uint8_t i;
        uint16_t memaddr;
        uint16_t buffersize;
        buffersize = (len*24)+43;        // number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes
        memaddr = 0;                                // reset buffer memory index

        while (len)
        {       
                                for(i=0; i<8; i++) // GREEN data
                        {
                                        LED_BYTE_Buffer[memaddr] = (uint32_t)( ((color[0][1]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO);
                                        memaddr++;
                        }
                        for(i=0; i<8; i++) // RED
                        {
                                        LED_BYTE_Buffer[memaddr] =(uint32_t)( ((color[0][0]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO);
                                        memaddr++;
                        }
                        for(i=0; i<8; i++) // BLUE
                        {
                                        LED_BYTE_Buffer[memaddr] =(uint32_t)( ((color[0][2]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO);
                                        memaddr++;
                        }
                       
                  len--;
        }
//===================================================================//       
//bug:最后一个周期波形不知道为什么全是高电平,故增加一个波形
          LED_BYTE_Buffer[memaddr] = ((color[0][2]<<8) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
//===================================================================//       
          memaddr++;       
                while(memaddr < buffersize)
                {
                        LED_BYTE_Buffer[memaddr] = 0;
                        memaddr++;
                }
        MYDMA_Config(DMA1_Stream7,DMA_Channel_5,(u32)&TIM3->CCR3,(u32)LED_BYTE_Buffer,43,DMA_PeripheralDataSize_HalfWord);//DMA1,STEAM7,CH5,外设定时器3的通道3,存储器为SendBuff,长度为:SEND_BUF_SIZE.

                DMA_SetCurrDataCounter(DMA1_Stream7, buffersize);         // load number of bytes to be transferred
                DMA_Cmd(DMA1_Stream7, ENABLE);                         // enable DMA channel 6
                TIM_Cmd(TIM3, ENABLE);                                                 // enable Timer 3
                while(!DMA_GetFlagStatus(DMA1_Stream7,DMA_FLAG_TCIF7)) ;         // wait until transfer complete
                TIM_Cmd(TIM3, DISABLE);         // disable Timer 3
                DMA_Cmd(DMA1_Stream7, DISABLE);                         // disable DMA channel 6
                DMA_ClearFlag(DMA1_Stream7,DMA_FLAG_TCIF7);                                 // clear DMA1 Channel 6 transfer complete flag
}



下面是DMA的初始化函数:
#include "dma.h"                                                                                                                                                     
#include "delay.h"                 
//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F407开发板
//DMA 驱动代码          
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2014/5/6
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved                                                                          
//////////////////////////////////////////////////////////////////////////////////          


//DMAx的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_StreamxMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
//chxMA通道选择,@ref DMA_channel DMA_Channel_0~DMA_Channel_7
//par:外设地址
//mar:存储器地址
//ndtr:数据传输量  
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 mar,u16 ndtr,uint32_t DataSize)
{

        DMA_InitTypeDef  DMA_InitStructure;
       
        if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
               
        }else
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
        }
  DMA_DeInit(DMA_Streamx);
       
        while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//等待DMA可配置
       
  /* 配置 DMA Stream */
  DMA_InitStructure.DMA_Channel = chx;  //通道选择
  DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址
  DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA 存储器0地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式
  DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
  DMA_InitStructure.DMA_PeripheralDataSize = DataSize;//外设数据长度:16位   注意这里的数据长度,对于高级定时器是32个位   对于普通定时器,可能是16个字节,可能是32个字节
  DMA_InitStructure.DMA_MemoryDataSize = DataSize;//存储器数据长度:16位
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular ;//使用循环模式 //DMA_Mode_Normal;// 使用普通模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
  DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream
       

}
//开启一次DMA传输
//DMA_StreamxMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
//ndtr:数据传输量  
void MYDMA_Enable(DMA_Stream_TypeDef *DMA_Streamx,u16 ndtr)
{

        DMA_Cmd(DMA_Streamx, DISABLE);                      //关闭DMA传输
       
        while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}        //确保DMA可以被设置  
               
        DMA_SetCurrDataCounter(DMA_Streamx,ndtr);          //数据传输量  

        DMA_Cmd(DMA_Streamx, ENABLE);                      //开启DMA传输
}          

我所实现的功能是:
通过DMA来更新定时器的输出pwm占空比,从而实现控制ws2812b的功能
































回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2018-1-2
在线时间
2 小时
发表于 2018-1-2 18:01:21 | 显示全部楼层
本帖最后由 zhaicool 于 2018-1-2 18:33 编辑
我有一个梦想 发表于 2017-12-29 17:32
我用的是STM32F407ZET6,使用功能的是DMA传输+PWM的方式,我使用的是TIM3->CCR3,通道选择的是DMA1_Stream7 ...

请问要点亮多个led该怎么配置呢?或者我指定点亮第几颗灯代码该怎么写呢?还望不吝赐教!
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2018-4-12
在线时间
3 小时
发表于 2018-9-19 13:13:47 | 显示全部楼层
我有一个梦想 发表于 2017-12-29 17:32
我用的是STM32F407ZET6,使用功能的是DMA传输+PWM的方式,我使用的是TIM3->CCR3,通道选择的是DMA1_Stream7 ...

number of LEDs * 24 bytes + 42 bytes
这个是有根据吗?
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2018-11-2
在线时间
7 小时
发表于 2018-11-14 10:25:11 | 显示全部楼层
后面解决了吗?我最近也在做这个,能不能指导下QQ : 634299815
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2018-11-2
在线时间
7 小时
发表于 2018-11-14 10:33:51 | 显示全部楼层
博主  你好  我也是使用407的  我现在需要对接10个灯圈(一个灯圈24颗灯珠),2根灯条(一根灯条70颗灯珠), 使用普通IO方式,使用定时器这种需要怎么控制各个定时器间的顺序呢
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2019-5-2
在线时间
10 小时
发表于 2019-5-6 21:10:35 | 显示全部楼层
是不是还差个启动时候的大于50us的低电平信号
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
19
金钱
19
注册时间
2019-6-10
在线时间
2 小时
发表于 2019-10-21 10:22:45 | 显示全部楼层

#ifndef __WS2812B_H__
#define __WS2812B_H__

#include <stdbool.h>
#include "stm32f4xx.h"



#define WS2812B_TEST                     1
#define WS2812B_GPIO_PERIF               RCC_AHB1Periph_GPIOA
#define WS2812B_TIM_PERIF                RCC_APB1Periph_TIM3
#define WS2812B_TIM                      TIM3
#define WS2812B_DMA                      RCC_AHB1Periph_DMA1
#define WS2812B_DMA_CHANNEL              DMA1_Stream4
#define WS2812B_DMA_NVIC_IRQChannel      DMA1_Stream4_IRQn
#define WS2812B_GPIO_PORT                GPIOA
#define WS2812B_GPIO_PIN                 GPIO_Pin_6

#define WS2812B_PIN_SOURCE                                                         GPIO_PinSource6
#define        WS2812B_GPIO_AF_TIMER                                     GPIO_AF_TIM3

#define WS2812B_TMI_CLOCK                56000000
#define WS2812B_TIM_PERIOD               29

#define WS2812B_NUM                      40
#define WS2812B_PULSE_BIT_SIZE           24
#define WS2812B_BUFF_SIZE                (24 * (WS2812B_NUM) + 50)   // Buffer size needs to be the number of LEDs times 24 bits plus 43 trailing bit
#define WS2812B_NVIC_PRI                 1
#define WS2812B_DMA_PeripheralBaseAddr   (uint32_t)&TIM3->CCR1;

#define WS2812B_PWM_HIGH_PULSE_WIDTH           19                    // Duty cycle of pwm signal for a logical 1 to be read by the ws2812 chip
#define WS2812B_PWM_LOW_PULSE_WIDTH            9                     // Duty cycle of pwm signal for a logical 0 to be read by the ws2812 chip
#define WS2812B_ALL_INDEX                      -1

#define WS2812B_CREATE_PULSE_BUFF() do { \
        clr = color; \
        for (j = 0; j < WS2812B_PULSE_BIT_SIZE; j++) { \
            ws2812bBuff[k++] = (clr & 0x800000 ) ? WS2812B_PWM_HIGH_PULSE_WIDTH : WS2812B_PWM_LOW_PULSE_WIDTH; \
            clr <<= 1; \
        } \
    } while(0)

void ws2812bInit(void);
bool ws2812bTest(void);
void ws2812bClear(const int index);
void ws2812bClearAll(void);
void ws2812bSet(const int index, const int color);
void ws2812bSetAll(const int32_t color);
void DMA1_Stream5_IRQHandler(void);

#endif

#include "ws2812b.h"
#include <rtthread.h>
#include <string.h>


static bool isInited = false;


static uint16_t ws2812bBuff[WS2812B_BUFF_SIZE];   // Array of data to be sent to leds.
static void ws2812bSend(void);



void ws2812bInit(void)
{
                GPIO_InitTypeDef GPIO_InitStruct;
                TIM_TimeBaseInitTypeDef  TIM_TimeBaseStruct;
                TIM_OCInitTypeDef  TIM_OCInitStruct;
                DMA_InitTypeDef DMA_InitStruct;
                NVIC_InitTypeDef NVIC_InitStructure;  
        
                RCC_AHB1PeriphClockCmd(WS2812B_GPIO_PERIF, ENABLE);
                RCC_APB1PeriphClockCmd(WS2812B_TIM_PERIF, ENABLE);
                RCC_AHB1PeriphClockCmd(WS2812B_DMA, ENABLE);
               
                GPIO_InitStruct.GPIO_Pin = WS2812B_GPIO_PIN;
                GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
                GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
                GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
                GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz;
                GPIO_Init(WS2812B_GPIO_PORT, &GPIO_InitStruct);
               
                GPIO_PinAFConfig(WS2812B_GPIO_PORT, WS2812B_PIN_SOURCE, WS2812B_GPIO_AF_TIMER);
   
    TIM_DeInit(WS2812B_TIM);
    TIM_TimeBaseStruct.TIM_Period = WS2812B_TIM_PERIOD;
    TIM_TimeBaseStruct.TIM_Prescaler = (uint16_t)(SystemCoreClock / WS2812B_TMI_CLOCK) - 1;
    TIM_TimeBaseStruct.TIM_ClockDivision = 0;
    TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
                TIM_TimeBaseStruct.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(WS2812B_TIM, &TIM_TimeBaseStruct);
   
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStruct.TIM_Pulse = 0;
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;   
                TIM_OC1Init(WS2812B_TIM, &TIM_OCInitStruct);               
                TIM_OC1PreloadConfig(WS2812B_TIM,TIM_OCPreload_Enable);
                TIM_ARRPreloadConfig(WS2812B_TIM, ENABLE);
               
                DMA_DeInit(WS2812B_DMA_CHANNEL);
                while (DMA_GetCmdStatus(WS2812B_DMA_CHANNEL) != DISABLE){}
                        
                DMA_InitStruct.DMA_BufferSize = WS2812B_BUFF_SIZE; // Specifies the buffer size
    DMA_InitStruct.DMA_Channel = DMA_Channel_5; // Deinitialize DAM1 Channel 7 to their default reset values.
                DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;                            // Data transfered from memory to peripheral
                DMA_InitStruct.DMA_FIFOMode= DMA_FIFOMode_Disable;                                                                                        //DMAμ&#196;FIFO&#196;£ê&#189;
                DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
                DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&ws2812bBuff;                // Specifies the buffer memory address
                DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
                DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;           // Specifies the memory data width
                DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;                       // Incrament the buffer index
                DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;                                 // Specifies the operation mode. Normal or Circular
                DMA_InitStruct.DMA_PeripheralBaseAddr = WS2812B_DMA_PeripheralBaseAddr;     // Specifies Physical address of the peripheral in this case Timer
                DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
                DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;   // Specifies the peripheral data width 16bit               
                DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;              // Do not incrament the peripheral address               
                DMA_InitStruct.DMA_Priority = DMA_Priority_High;                           // Specifies the software priority
                DMA_Init(WS2812B_DMA_CHANNEL, &DMA_InitStruct);                            // Initialize DAM1 Channel 2 to values specified in the DMA_InitStruct structure.               

                TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE);

                ws2812bClearAll();
   
    isInited = true;
}

bool ws2812bTest(void)
{
    #if(WS2812B_TEST == 1)
    ws2812bSet(0, 0xff0000);
    for(int i = 1000000; i > 0; i--);
    ws2812bClear(0);
    #endif
    return isInited;
}

void ws2812bClear(const int index)
{
    ws2812bSet(index, 0);
}

void ws2812bClearAll()
{
    int32_t i, j, k = 0;
   
    for (i = 0; i < WS2812B_NUM; i++)
    {
        for (j = 0; j < WS2812B_PULSE_BIT_SIZE; j++)
        {
            ws2812bBuff[k++] = WS2812B_PWM_LOW_PULSE_WIDTH;
        }
    }

    memset(&ws2812bBuff[k], 0, WS2812B_BUFF_SIZE - k);
    ws2812bSend();
}

void ws2812bSet(const int index, const int32_t color)
{
    int32_t i, j;
    int32_t k = 0;
    int32_t clr = color;
   
    if(index >= WS2812B_NUM || (index < 0 && index != WS2812B_ALL_INDEX))
    {
        return;
    }
   
    k = index * WS2812B_PULSE_BIT_SIZE;
   
    if(index != WS2812B_ALL_INDEX)
    {
        WS2812B_CREATE_PULSE_BUFF();
    }
    else
    {
        for(i = 0; i < WS2812B_NUM; i++)
            WS2812B_CREATE_PULSE_BUFF();
    }

    ws2812bSend();
}

void ws2812bSetAll(const int32_t color)
{
    ws2812bSet(WS2812B_ALL_INDEX, color);
}
static void ws2812bSend(void)
{
                DMA_SetCurrDataCounter(WS2812B_DMA_CHANNEL, WS2812B_BUFF_SIZE);                 
                DMA_Cmd(WS2812B_DMA_CHANNEL, ENABLE);        //ê1&#196;üDMA
                TIM_SetCounter(TIM3,0x0000);
                TIM_Cmd(TIM3, ENABLE);                        //ê1&#196;ü&#182;¨ê±&#198;÷
               
                while(!DMA_GetFlagStatus(WS2812B_DMA_CHANNEL,DMA_FLAG_TCIF4));        // wait until transfer complete
                DMA_Cmd(WS2812B_DMA_CHANNEL, DISABLE);        //ê1&#196;üDMA
               
        
                DMA_ClearFlag(WS2812B_DMA_CHANNEL,DMA_FLAG_TCIF4);
                TIM_Cmd(TIM3, DISABLE);                        //ê1&#196;ü&#182;¨ê±&#198;÷
}


/*2aê&#212;3ìDò2019.10.18&#198;á±&#206;*/
//uint8_t rgb0[1][3] = {0,0,0};
//uint8_t rgb1[1][3] = {0xAA, 0xAA, 0xAA};
//uint8_t r[1][3] = {255,0,0};
//uint8_t g[1][3] = {0,255,0};
//uint8_t b[1][3] = {0,0,255};
//uint8_t y[1][3] = {255,0,255};
//uint8_t cg[1][3] = {153,51,250};

//#define TIMING_ONE  68        // 0.8usμ&#231;&#198;&#189;ê±&#188;&#228;
//#define TIMING_ZERO 37        // 0.3usμ&#231;&#198;&#189;ê±&#188;&#228;

//void WS2812_send(uint8_t (*color)[3], uint16_t len)
//{
//        uint8_t i;
//        uint16_t memaddr;
//        uint16_t buffersize;
//        buffersize = (len*24)+ 50;        // number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes
//        memaddr = 0;                                // reset buffer memory index

//        while (len)
//        {        
//                for(i=0; i<8; i++) // GREEN data
//                {
//                        ws2812bBuff[memaddr] = ((color[0][1]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
//                        memaddr++;
//                }
//                for(i=0; i<8; i++) // RED
//                {
//                                ws2812bBuff[memaddr] = ((color[0][0]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
//                                memaddr++;
//                }
//                for(i=0; i<8; i++) // BLUE
//                {
//                                ws2812bBuff[memaddr] = ((color[0][2]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
//                                memaddr++;
//                }
//                len--;
//        }
////===================================================================//        
////bug£o×&#238;oóò&#187;&#184;&#246;&#214;ü&#198;ú2¨D&#206;2&#187;&#214;aμà&#206;aê2&#195;′è&#171;ê&#199;&#184;&#223;μ&#231;&#198;&#189;£&#172;1ê&#212;&#246;&#188;óò&#187;&#184;&#246;2¨D&#206;
//          ws2812bBuff[memaddr] = ((color[0][2]<<8) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
////===================================================================//        
//          memaddr++;        
//                while(memaddr < buffersize)
//                {
//                        ws2812bBuff[memaddr] = 0;
//                        memaddr++;
//                }

//                DMA_SetCurrDataCounter(WS2812B_DMA_CHANNEL, buffersize);                 
//                DMA_Cmd(WS2812B_DMA_CHANNEL, ENABLE);        //ê1&#196;üDMA
//                TIM_SetCounter(TIM3,0x0000);
//                TIM_Cmd(TIM3, ENABLE);                        //ê1&#196;ü&#182;¨ê±&#198;÷
//               
//                while(!DMA_GetFlagStatus(WS2812B_DMA_CHANNEL,DMA_FLAG_TCIF4));        // wait until transfer complete
//                DMA_Cmd(WS2812B_DMA_CHANNEL, DISABLE);        //ê1&#196;üDMA
//               
//        
//                DMA_ClearFlag(WS2812B_DMA_CHANNEL,DMA_FLAG_TCIF4);
//                TIM_Cmd(TIM3, DISABLE);                        //ê1&#196;ü&#182;¨ê±&#198;÷
//}
/*2aê&#212;3ìDò2019.10.18&#198;á±&#206;*/


ALIGN(RT_ALIGN_SIZE)
static char ws2812b_thread_stack[1024];
struct rt_thread ws2812b_thread;
static void ws2812b_thread_entry(void *param)
{
    rt_time_t        next_delay;
    ws2812bInit();
                if(!ws2812bTest()) while(1);
    next_delay = 50; //100ms
    rt_thread_delay(next_delay);

    while(1)
    {
//                        for(int i = 0;i < 31;i++)
//                        {
//                                ws2812bSet(i, 0xff0000);
//                                rt_thread_delay(next_delay);
//                        }
//                        rt_thread_delay(next_delay);
//                        ws2812bClearAll();
//                        for(int i = 0;i < 31;i++)
//                        {
//                                ws2812bSet(i, 0x00ff00);
//                                rt_thread_delay(next_delay);
//                        }
//                        rt_thread_delay(next_delay);
//                        ws2812bClearAll();
//                        for(int i = 0;i < 31;i++)
//                        {
//                                ws2812bSet(i, 0x0000ff);
//                                rt_thread_delay(next_delay);
//                        }
                        
                        ws2812bSet(5, 0xff0000);
                        rt_thread_delay(next_delay);
                        ws2812bClearAll();
                        rt_thread_delay(next_delay);
                }
}

void ws2812b_thread_init(uint8_t prio)
{
    //pulse pump thread init
    rt_thread_init(&ws2812b_thread, "ws2812b",
                   ws2812b_thread_entry, RT_NULL,
                   &ws2812b_thread_stack[0],
                   sizeof(ws2812b_thread_stack), prio, 5);
    rt_thread_startup(&ws2812b_thread);
}
回复

使用道具 举报

1

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2021-1-17
在线时间
9 小时
发表于 2021-2-5 20:39:20 | 显示全部楼层
cslovepp 发表于 2019-10-21 10:22
#ifndef __WS2812B_H__
#define __WS2812B_H__

stdbool.h是什么头文件,包含了什么呢
回复

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2020-1-13
在线时间
6 小时
发表于 2021-5-6 17:32:00 | 显示全部楼层
我做过用正点原子的探索者STM32F407来控制WS2812B灯带
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-28 00:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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