STM32 PWM+DMA

1.学习一下STM32的PWM+DMA方式输出脉冲信号,最典型的应该就是驱动WS2812B灯带了,用这个方式很方便,也很容易理解。本次实验用的主控MCU是STM32C8T6,模块使用WS2812B灯带,5V-30颗灯珠。

2

.STM32C8T6基本的资源介绍:

STM32F103x8和STM32F103xB增强型系列使用高性能的ARM® Cortex™-M3 32位的RISC内核,工

作频率为72MHz,内置高速存储器(高达128K字节的闪存和20K字节的SRAM),丰富的增强I/O端口

和联接到两条APB总线的外设。所有型号的器件都包含2个12位的ADC、3个通用16位定时器和1个

PWM定时器,还包含标准和先进的通信接口:多达2个I

2

C接口和SPI接口、3个USART接口、一个

USB接口和一个CAN接口。

3.

WS2812B:就是一个RGB灯带,只给信号,就量相应的颜色,理论上像素255*255*255种颜色,主要实验3原色显示。

4.下面是STM32F103配置PWM+DMA的方式,使用的标准库。我使用的是PA1,定时器2通道2.再看一下DMA的配置,TIM2_CH2对应的DMA1通道是7.在确认主控硬件资源之后,先别急着敲代码,先了解一下WS2812的驱动方式。

第1个WS2812B灯珠接收到了第1个24bit的数据,做出响应(发光);第N个WS2812B灯珠接收到了第N个24bit的数据,

再收到第二个24bit的数据后,直接转发给第二个WS2812B灯珠,由第二个WS2812B灯珠做出响应;依次类推

要想RGB灯亮,必须发送24位的800khz方波才行。

void Ws2812b_Pwm_Dma_GpioConfig(void)

{

 GPIO_InitTypeDef GPIO_InitStruct;

 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

 TIM_OCInitTypeDef TIM_OCInitStruct;

 DMA_InitTypeDef DMA_InitStruct;

 /* 开启GPIO TIM DMA 外设时钟 */

 RCC_APB2PeriphClockCmd(WS2812B_TIMx_GPIO_CLK, ENABLE);//GPIO时钟

 RCC_APB1PeriphClockCmd(WS2812B_TIMx_CLK, ENABLE);//TIM2_CH2

 RCC_AHBPeriphClockCmd(WS2812B_DMAx_CLK, ENABLE);//DMA1

 /* GPIO端口配置 */

 GPIO_InitStruct.GPIO_Pin = WS2812B_TIMx_PIN;

 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;

 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_Init(WS2812B_TIMx_PORT, &GPIO_InitStruct);

 /* 定时器时基配置 */

 TIM_TimeBaseInitStruct.TIM_Prescaler = WS2812B_TIMx_Prescaler-1;

 TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;

 TIM_TimeBaseInitStruct.TIM_Period = WS2812B_TIMx_Period-1;  //72M / 90 = 800K

 TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;

 TIM_TimeBaseInit(WS2812B_TIMx, &TIM_TimeBaseInitStruct);

 /* 定时器输出比较配置 */

 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_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;

 TIM_OC2Init(WS2812B_TIMx, &TIM_OCInitStruct);//通道2初始化化

 TIM_CtrlPWMOutputs(WS2812B_TIMx, ENABLE);  //PWM输出使能   

 TIM_Cmd(WS2812B_TIMx, DISABLE);

 TIM_DMACmd(WS2812B_TIMx, WS2812B_DMAx_Source, ENABLE);

 /* DMA配置 */

 DMA_InitStruct.DMA_PeripheralBaseAddr =  (uint32_t)&(TIM2->CCR2) ;

 DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)Pixel_Buff;

 DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;

 DMA_InitStruct.DMA_BufferSize = PIXEL_NUM * RGB;

 DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

 DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;

 DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

 DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

 DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;

 DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;

 DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;

 DMA_Init(WS2812B_DMAx_Channelx, &DMA_InitStruct);

   

 DMA_Cmd(WS2812B_DMAx_Channelx, DISABLE);

}

定时器2在APB1中线上,系统时钟是72M,TIM_Prescaler=0,.TIM_Period=89,一个周期就是1.25us,符合WS2812的时序,一个时钟时间是1/72=14ns,25*14ns=350ns符合0码,45*14=630ns符合1码时序。只需要发送pwm(25)代表0码,pwm(45)代表1码。

//缓存数据

u16 Pixel_Buff[PIXEL_NUM][RGB]={0};

void Ws281b_Show(void)

{

  DMA_SetCurrDataCounter(WS2812B_DMAx_Channelx, (u16)(PIXEL_NUM * RGB));  //设定DMA要传输数据的大小 

  DMA_Cmd(WS2812B_DMAx_Channelx, ENABLE);

  TIM_OC2PreloadConfig(WS2812B_TIMx, TIM_OCPreload_Enable);   //CH1预装载器使能

  TIM_Cmd(WS2812B_TIMx, ENABLE);

  while(DMA_GetFlagStatus(WS2812B_DMA_FLAG) != SET);    //等待传输完成

  DMA_Cmd(WS2812B_DMAx_Channelx, DISABLE);

  TIM_OC2PreloadConfig(WS2812B_TIMx, TIM_OCPreload_Disable); //关闭CH1预装载器

  TIM_Cmd(WS2812B_TIMx, DISABLE);

  DMA_ClearFlag(WS2812B_DMA_FLAG);

  WS2812B_PIN_L;

Delay_us(350);

}

void Ws2812b_CloseAll(void)//熄灭

{

  u16 i;

  u8 j;

  

  for(i = 0; i < PIXEL_NUM; ++i)

  {

    for(j = 0; j < 24; ++j)

    {

      Pixel_Buff[i][j] = T0H;

    }

  }

  Ws281b_Show(); //传输数据

}

往数组填充数据就能使灯带亮起来了,WS2812灯珠自带有芯片的,所以只需要发送一个次数据就能亮起来


  • 13
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值