stm32用pwm+DMA驱动8*32sw2812 代码
时间: 2024-05-07 17:21:54 浏览: 44
基于pwm+dma的stm32的ws2812工程
下面是一个使用 STM32 的 PWM+DMA 驱动 8*32 的 WS2812 灯条的代码。代码使用了 TIM2 的 CH1 通道作为 PWM 输出,并使用 DMA 将灯条数据发送到 TIM2。
需要注意的是,代码中的数据格式是 GRB,如果要使用 RGB 格式,请修改代码中的数据格式。
```
#include "stm32f10x.h"
#define LED_COUNT 256 // 灯条数量
#define LED_BYTES (LED_COUNT * 3) // 数据总字节数
#define PWM_PERIOD 70 // PWM 周期,根据实际情况调整
uint8_t led_data[LED_BYTES]; // 灯条数据
uint16_t pwm_data[LED_BYTES * 8]; // PWM 数据
void init_led_data(void) {
for (int i = 0; i < LED_COUNT; i++) {
led_data[i * 3] = 0x00; // G
led_data[i * 3 + 1] = 0x00; // R
led_data[i * 3 + 2] = 0x00; // B
}
}
void init_pwm_data(void) {
int pwm_index = 0;
for (int i = 0; i < LED_COUNT; i++) {
uint8_t r = led_data[i * 3 + 1];
uint8_t g = led_data[i * 3];
uint8_t b = led_data[i * 3 + 2];
for (int j = 0; j < 8; j++) {
if (g & 0x80) {
pwm_data[pwm_index++] = PWM_PERIOD;
} else {
pwm_data[pwm_index++] = 0;
}
if (r & 0x80) {
pwm_data[pwm_index++] = PWM_PERIOD;
} else {
pwm_data[pwm_index++] = 0;
}
if (b & 0x80) {
pwm_data[pwm_index++] = PWM_PERIOD;
} else {
pwm_data[pwm_index++] = 0;
}
g <<= 1;
r <<= 1;
b <<= 1;
}
}
}
void init_pwm(void) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
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_Cmd(TIM2, ENABLE);
}
void init_dma(void) {
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &TIM2->CCR1;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) pwm_data;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = LED_BYTES * 8;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
TIM_DMACmd(TIM2, TIM_DMA_CC1, ENABLE);
DMA_Cmd(DMA1_Channel5, ENABLE);
}
int main(void) {
init_led_data();
init_pwm_data();
init_pwm();
init_dma();
while (1) {
// 循环发送数据
}
}
```
阅读全文