找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1797|回复: 0
打印 上一主题 下一主题
收起左侧

stm32f013 dma pwm ws2812源程序

[复制链接]
跳转到指定楼层
楼主
ID:8173 发表于 2020-9-27 17:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include "WS2812B.h"
  2. /* Buffer that holds one complete DMA transmission
  3. *
  4. * Ensure that this buffer is big enough to hold
  5. * all data bytes that need to be sent
  6. *
  7. * The buffer size can be calculated as follows:
  8. * number of LEDs * 24 bytes + 42 bytes
  9. *
  10. * This leaves us with a maximum string length of
  11. * (2^16 bytes per DMA stream - 42 bytes)/24 bytes per LED = 2728 LEDs
  12. */
  13. //#define TIM2_CCR1_Address 0x40000034         // physical memory address of Timer 2 CCR1 register
  14. //#define TIM3_CCR1_Address 0x40000434        // physical memory address of Timer 3 CCR1 register
  15. #define TIM2_CCR1_Address 0x40000034
  16. #define TIM2_CCR2_Address 0x40000038
  17. #define TIM2_CCR3_Address 0x4000003C
  18. #define TIM2_CCR4_Address 0x40000040
  19.         
  20. #define TIMING_ONE  50
  21. #define TIMING_ZERO 25
  22. uint16_t LED1_BYTE_Buffer[5000];
  23. uint16_t LED2_BYTE_Buffer[5000];
  24. uint16_t LED3_BYTE_Buffer[5000];
  25. uint16_t LED4_BYTE_Buffer[5000];
  26. //uint16_t LED5_BYTE_Buffer[300];
  27. //uint16_t LED6_BYTE_Buffer[300];
  28. //uint16_t LED7_BYTE_Buffer[300];
  29. //uint16_t LED8_BYTE_Buffer[300];
  30. //---------------------------------------------------------------//

  31. void Timer2_init(void)
  32. {
  33.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  34.   TIM_OCInitTypeDef  TIM_OCInitStructure;
  35.   GPIO_InitTypeDef GPIO_InitStructure;
  36.   DMA_InitTypeDef DMA_InitStructure;
  37.         
  38.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  39.         /* GPIOA Configuration: TIM2 Channel 1 as alternate function push-pull */
  40.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
  41.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  42.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  43.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  44.         
  45.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  46.         /* Compute the prescaler value */
  47.         //PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
  48.         /* Time base configuration */
  49.         TIM_TimeBaseStructure.TIM_Period = 90-1; // 800kHz
  50.         TIM_TimeBaseStructure.TIM_Prescaler = 0;
  51.         TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  52.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  53.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  54.         /* PWM1 Mode configuration: Channel1 */
  55.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  56.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  57.         TIM_OCInitStructure.TIM_Pulse = 0;
  58.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  59.         TIM_OC1Init(TIM2, &TIM_OCInitStructure);
  60.                
  61.         /* PWM2 Mode configuration: Channel1 */
  62.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  63.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  64.         TIM_OCInitStructure.TIM_Pulse = 0;
  65.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  66.         TIM_OC2Init(TIM2, &TIM_OCInitStructure);
  67.         
  68.         /* PWM3 Mode configuration: Channel1 */
  69.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  70.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  71.         TIM_OCInitStructure.TIM_Pulse = 0;
  72.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  73.         TIM_OC3Init(TIM2, &TIM_OCInitStructure);
  74.         
  75.         /* PWM4 Mode configuration: Channel1 */
  76. /*        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  77.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  78.         TIM_OCInitStructure.TIM_Pulse = 0;
  79.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  80.         TIM_OC4Init(TIM2, &TIM_OCInitStructure);
  81. */        
  82.         
  83.         /* configure DMA */
  84.         /* DMA clock enable */
  85.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  86.         
  87.         /* DMA1 Channel2 Config for PWM1 by TIM2_CH1*/
  88.         DMA_DeInit(DMA1_Channel2);

  89.         DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM2_CCR1_Address;        // physical address of Timer 3 CCR1
  90.         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)LED1_BYTE_Buffer;                // this is the buffer memory
  91.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                                                // data shifted from memory to peripheral
  92.         DMA_InitStructure.DMA_BufferSize = 42;
  93.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  94.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                        // automatically increase buffer index
  95.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  96.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  97.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                        // stop DMA feed after buffer size is reached
  98.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  99.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  100.         
  101.         DMA_Init(DMA1_Channel2, &DMA_InitStructure);
  102.         
  103.         /* DMA1 Channel7 Config for PWM2 by TIM2_CH2*/
  104.         DMA_DeInit(DMA1_Channel7);

  105.         DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM2_CCR2_Address;        // physical address of Timer 3 CCR1
  106.         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)LED2_BYTE_Buffer;                // this is the buffer memory
  107.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                                                // data shifted from memory to peripheral
  108.         DMA_InitStructure.DMA_BufferSize = 42;
  109.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  110.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                        // automatically increase buffer index
  111.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  112.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  113.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                        // stop DMA feed after buffer size is reached
  114.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  115.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  116.         
  117.         DMA_Init(DMA1_Channel7, &DMA_InitStructure);
  118.         
  119.         /* DMA1 Channel1 Config for PWM3 by TIM2_CH3*/
  120.         DMA_DeInit(DMA1_Channel1);

  121.         DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM2_CCR3_Address;        // physical address of Timer 3 CCR1
  122.         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)LED3_BYTE_Buffer;                // this is the buffer memory
  123.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                                                // data shifted from memory to peripheral
  124.         DMA_InitStructure.DMA_BufferSize = 42;
  125.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  126.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                        // automatically increase buffer index
  127.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  128.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  129.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                        // stop DMA feed after buffer size is reached
  130.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  131.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  132.         
  133.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  134.         
  135.         /* DMA1 Channel7 Config for PWM4 by TIM2_CH4*/
  136. /*        DMA_DeInit(DMA1_Channel7);

  137.         DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM2_CCR4_Address;        // physical address of Timer 3 CCR1
  138.         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)LED4_BYTE_Buffer;                // this is the buffer memory
  139.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                                                // data shifted from memory to peripheral
  140.         DMA_InitStructure.DMA_BufferSize = 42;
  141.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  142.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                        // automatically increase buffer index
  143.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  144.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  145.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                        // stop DMA feed after buffer size is reached
  146.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  147.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  148.         
  149.         DMA_Init(DMA1_Channel7, &DMA_InitStructure);
  150. */
  151.         /* TIM2 DMA Request enable */
  152.         TIM_DMACmd(TIM2, TIM_DMA_CC1, ENABLE);
  153.         TIM_DMACmd(TIM2, TIM_DMA_CC2, ENABLE);
  154.         TIM_DMACmd(TIM2, TIM_DMA_CC3, ENABLE);
  155. //        TIM_DMACmd(TIM2, TIM_DMA_CC4, ENABLE);
  156.         TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);
  157. }

  158. /* This function sends data bytes out to a string of WS2812s
  159. * The first argument is a pointer to the first RGB triplet to be sent
  160. * The seconds argument is the number of LEDs in the chain
  161. *
  162. * This will result in the RGB triplet passed by argument 1 being sent to
  163. * the LED that is the furthest away from the controller (the point where
  164. * data is injected into the chain)
  165. */
  166. void WS2812_led1_send(uint8_t (*color)[3], uint16_t len)
  167. {
  168.         uint8_t i;
  169.         uint16_t memaddr;
  170.         uint16_t buffersize;
  171.         buffersize = (len*24)+43;        // number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes
  172.         memaddr = 0;                                // reset buffer memory index

  173.         while (len)
  174.         {        
  175.                 for(i=0; i<8; i++) // GREEN data
  176.                 {
  177.                         LED1_BYTE_Buffer[memaddr] = ((color[0][1]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
  178.                         memaddr++;
  179.                 }
  180.                 for(i=0; i<8; i++) // RED
  181.                 {
  182.                         LED1_BYTE_Buffer[memaddr] = ((color[0][0]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
  183.                         memaddr++;
  184.                 }
  185.                 for(i=0; i<8; i++) // BLUE
  186.                 {
  187.                         LED1_BYTE_Buffer[memaddr] = ((color[0][2]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
  188.                         memaddr++;
  189.                 }
  190.                 len--;
  191.         }
  192. //===================================================================//        
  193. //bug:最后一个周期波形不知道为什么全是高电平,故增加一个波形
  194.           LED1_BYTE_Buffer[memaddr] = ((color[0][2]<<8) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
  195. //===================================================================//        
  196.           memaddr++;        
  197.                 while(memaddr < buffersize)
  198.                 {
  199.                         LED1_BYTE_Buffer[memaddr] = 0;
  200.                         memaddr++;
  201.                 }

  202.                 DMA_SetCurrDataCounter(DMA1_Channel2, buffersize);         // load number of bytes to be transferred
  203.                 DMA_Cmd(DMA1_Channel2, ENABLE);                         // enable DMA channel 2
  204.                 TIM_Cmd(TIM2, ENABLE);                                                 // enable Timer 2
  205.                 while(!DMA_GetFlagStatus(DMA1_FLAG_TC2)) ;         // wait until transfer complete
  206.                 TIM_Cmd(TIM2, DISABLE);         // disable Timer 2
  207.                 DMA_Cmd(DMA1_Channel2, DISABLE);                         // disable DMA channel 2
  208.                 DMA_ClearFlag(DMA1_FLAG_TC2);                                 // clear DMA1 Channel 2 transfer complete flag
  209. }

  210. /* This function sends data bytes out to a string of WS2812s
  211. * The first argument is a pointer to the first RGB triplet to be sent
  212. * The seconds argument is the number of LEDs in the chain
  213. *
  214. * This will result in the RGB triplet passed by argument 1 being sent to
  215. * the LED that is the furthest away from the controller (the point where
  216. * data is injected into the chain)
  217. */
  218. void WS2812_led2_send(uint8_t (*color)[3], uint16_t len)
  219. {
  220.         uint8_t i;
  221.         uint16_t memaddr;
  222.         uint16_t buffersize;
  223.         buffersize = (len*24)+43;        // number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes
  224.         memaddr = 0;                                // reset buffer memory index

  225.         while (len)
  226.         {        
  227.                 for(i=0; i<8; i++) // GREEN data
  228.                 {
  229.                         LED2_BYTE_Buffer[memaddr] = ((color[0][1]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
  230.                         memaddr++;
  231.                 }
  232.                 for(i=0; i<8; i++) // RED
  233.                 {
  234.                         LED2_BYTE_Buffer[memaddr] = ((color[0][0]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
  235.                         memaddr++;
  236.                 }
  237.                 for(i=0; i<8; i++) // BLUE
  238.                 {
  239.                         LED2_BYTE_Buffer[memaddr] = ((color[0][2]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
  240.                         memaddr++;
  241.                 }
  242.                 len--;
  243.         }
  244. //===================================================================//        
  245. ……………………

  246. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

Keil代码51hei下载地址:
STM32F1_DMA_PWM_WS2813E_2018_05_06-TIM2_CH123.7z (185.79 KB, 下载次数: 53)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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