历史上的今天
返回首页

历史上的今天

今天是:2024年12月28日(星期六)

2018年12月28日 | STM32用PWM +DMA驱动 WS2812

2018-12-28 来源:eefocus

参考的代码:


------------------------------------WS2812B.c------------------------------------

#include "WS2812B.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 TIM2_CCR4_Address 0x40000040

#define TIMING_ONE  61

#define TIMING_ZERO 29

 uint16_t LED_BYTE_Buffer[300];

 uint16_t testcount = 0;

  uint16_t testcount1 = 0;

//---------------------------------------------------------------//

 

void Timer2_init(void)

{

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

  TIM_OCInitTypeDef  TIM_OCInitStructure;

  GPIO_InitTypeDef GPIO_InitStructure;

  DMA_InitTypeDef DMA_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

/* GPIOA Configuration: TIM2 Channel 1 as alternate function push-pull */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

  

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

/* Compute the prescaler value */

//PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;

/* Time base configuration */

TIM_TimeBaseStructure.TIM_Period = 90-1; // 800kHz 

TIM_TimeBaseStructure.TIM_Prescaler = 0;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

 

/* PWM1 Mode configuration: Channel1 */

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_Pulse = 0;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OC1Init(TIM2, &TIM_OCInitStructure);

  TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);

//  TIM_ARRPreloadConfig(TIM3, ENABLE);

//GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);

/* configure DMA */

/* DMA clock enable */

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

/* DMA1 Channel6 Config */

DMA_DeInit(DMA1_Channel2);

 

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&TIM2->CCR1);// physical address of Timer 3 CCR1

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)LED_BYTE_Buffer;// this is the buffer memory 

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;// data shifted from memory to peripheral

DMA_InitStructure.DMA_BufferSize = 42;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// automatically increase buffer index

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// stop DMA feed after buffer size is reached

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel2, &DMA_InitStructure);

 

/* TIM3 CC1 DMA Request enable */

TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);

}

 

/* 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)

 */

void WS2812_send(uint8_t (*color)[3], uint16_t len)

{

uint8_t i;

uint16_t memaddr;

uint16_t buffersize;

buffersize = (len*24)+10;// 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] = ((color[0][1]<

memaddr++;

}

for(i=0; i<8; i++) // RED

{

LED_BYTE_Buffer[memaddr] = ((color[0][0]<

memaddr++;

}

for(i=0; i<8; i++) // BLUE

{

LED_BYTE_Buffer[memaddr] = ((color[0][2]<

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++;

}

 

DMA_SetCurrDataCounter(DMA1_Channel2, memaddr); // load number of bytes to be transferred

    DMA_Cmd(DMA1_Channel2, ENABLE); // enable DMA channel 6

TIM_Cmd(TIM2, ENABLE); // enable Timer 3

 

while(!DMA_GetFlagStatus(DMA1_FLAG_TC2)) 

    {

//      testcount1 = DMA_GetCurrDataCounter(DMA1_Channel2);

//      if(DMA_GetFlagStatus(DMA1_FLAG_TE2))

//      {

//        testcount++;

//      }

    }; // wait until transfer complete

//  testcount++;

    TIM_Cmd(TIM2, DISABLE); // disable Timer 3

DMA_Cmd(DMA1_Channel2, DISABLE); // disable DMA channel 6

DMA_ClearFlag(DMA1_FLAG_TC2); // clear DMA1 Channel 6 transfer complete flag

}

 

 

----------------------------------------Main.c---------------------------------------------

uint8_t r[][3] = {255,0,0};

uint8_t g[][3] = {0,255,0};

uint8_t b[][3] = {0,0,255};

uint8_t cheng[][3] = {255,128,0};

uint8_t huang[][3] = {255,255,0};

uint8_t qing[][3] = {0,255,255};

uint8_t zi[][3] = {128,0,255};

uint32_t testt = (uint32_t)(&TIM3->CCR3);

 

 

 int main(void)

 {

    //RCC_Configuration();

   

    delay_init();    //延时函数初始化  

    //LED_Init();  //初始化与LED连接的硬件接口

    Timer2_init();

while(1)

{

WS2812_send(r,8);

delay_ms(1000);

WS2812_send(g,8);

delay_ms(1000);

WS2812_send(b,8);

delay_ms(1000);

    WS2812_send(cheng,8);

delay_ms(1000);

WS2812_send(huang,8);

delay_ms(1000);

WS2812_send(qing,8);

delay_ms(1000);

    WS2812_send(zi,8);

delay_ms(1000);

}

 }

需要注意以下几点:


1)采用的是TIM2->CH1,用的是TIM_DMA_Update触发,如果改用其他的通道需要更改触发方式


2)代码中---bug:最后一个周期波形不知道为什么全是高电平,故增加一个波形


可以注销此句代码,主要是  buffersize = (len*24)+10;不知道为什么需要加上10,加上1就不行,不知道什么原因,那位知道可以探讨下。


推荐阅读

史海拾趣

问答坊 | AI 解惑

电机的控制

用的是直流电机,信号由PWM来控制,采用H桥驱动,经过齿轮箱,把旋转运动转化为直线运动,负载是控制弹簧的开度。 有人告诉我,电机的电压越大,电流越小,这是为什么? 当电机扭矩不够大,带不动负载时,电机是什么状态,转还是不转? 当电机把 ...…

查看全部问答>

中兴通讯电源输入端口的电磁兼容设计

中兴通讯电源输入端口的电磁兼容设计…

查看全部问答>

电路板新手问一些电路板上的基础问题

不知道发在什么版合适,看来看去还是发在这个版块了~ 现在我在学习电路板、电路图的知识。以前在学校虽然学习过模电数电但是毕竟没有怎么接触过真东西,只是理论知识。 现在手头有一块电路板,我需要画出它的电路图来。面临的问题是,我不懂电路 ...…

查看全部问答>

qt串口编程的问题

make后提示 serialthread.h 语法错误,但没发现serialthread.h中的语法错误。为什么编译不成功呢?? [root@localhost qt-1]# make g++ -c -pipe -DQWS -fno-exceptions -fno-rtti -Wall -W -O2 -fno-default-inline -DNO_DEBUG -I/working/qt/q ...…

查看全部问答>

WinCE 3G卡 USB驱动 求救

dear all: 小弟最近做一个HW的3G卡,WinCE下的USB虚拟串口驱动,在USB中,有8组接口,用了其它的一组有2个端点,8号端点OUT写数据,88号端点IN读取数据,为什么能写成功,IN不到数据呢,望大家指教, 代码如下: dw = IssueBulkTransfer( pDrv-> ...…

查看全部问答>

wince下能调通的程序不能执行!

我通过#pragma 引入了几个lib文件,还需要在项目属性中手动输入那些文件吗? 我生成exe文件后运行的时候显示0x8007007e错误  我又把那些lib文件手工复制到模拟器中,放在exe文件的目录下还是不能执行 请问这是怎么回事? …

查看全部问答>

刚完成了一个CycloneIII fpga开发板,将CycloneIII设计中的问题分享一下,持续更新

我所使用的芯片是Cyclone III EP3C5E144,与ep3c10e144是引脚兼容,没有去兼容ep3c16和25,因为用户IO相差太大, 本来qfp144的封装io就不太多,ep3c16和25就没有考虑。 ep3c5有5136个逻辑资源,跑普通的Verilog代码和niosII 完全 ...…

查看全部问答>

恩智浦充分挖掘多功能汽车钥匙的潜能

推出市场就绪型NFC“智能”汽车钥匙 中国上海,2011年6月15日 --\" 智能\"汽车钥匙市场的先驱--恩智浦半导体NXP Semiconductors N.V. (NASDAQ:NXPI) 今日宣布推出针对多功能汽车钥匙的生产就绪单芯片解决方案--NCF2970 (KEyLink L ...…

查看全部问答>

g729编解码 感谢cl 教一个从没有学过信号处理相关的计算机白痴

  目前在做16位芯片上的g729解码算法。我一个连语音编解码算法最基础的课程都没有学过的计算机白痴,在项目组长CL的帮助下,对g729,有了一个大概的了解。  g729将80bits参数重构成一帧语音,最重要的一个公式是:   80位的比特流分 ...…

查看全部问答>

STM32发送显示数据给串口工业屏的问题,麻烦各位大大来给指导下,万分感谢。。

其实就是用STM32和串口工业屏通信,我写好了数据接收函数,现在是要写发送函数。 但是他给的协议表是这样的: void Uart1_PutStr1(u8 *p,u8 len) { extern UART_TypeDef Uart1_Structure; if(Uart1_Structure.TxStatus) //如果串口正在发 ...…

查看全部问答>