问题描述如下:
我要驱动大约30个WS2812灯珠,通过TIM3+DMA的方式已经正常点亮灯珠,现在我初始化TIM1,通过指示灯闪烁可以看到定时器1正常跑起来了。
现在把TIM3+DMA和TIM1一起跑的时候,TIM1正常跑,DMA却熄火了,有点奇怪,请教各位大佬有什么解决办法,谢谢!
最近编辑记录 hzqlz (2024-03-29 23:12:42)
离线
timer3.c内容
#include "main.h"
#include "timer3.h"
#include "air001xx_ll_tim.h"
#include "air001xx_ll_bus.h"
#include "air001xx_ll_gpio.h"
#include "air001xx_ll_rcc.h"
#include "air001xx_ll_dma.h"
#include "led.h"
#define TIM_ARR_VALUE (60-1)
void timer3_ch2_gpio_init(void)
{
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Alternate = LL_GPIO_AF1_TIM3;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void timer3_ch2_init(void)
{
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
LL_TIM_InitTypeDef TIM_InitStruct = {0};
LL_TIM_StructInit(&TIM_InitStruct);
TIM_InitStruct.Prescaler = 0;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = TIM_ARR_VALUE;//周期
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;//
LL_TIM_Init(TIM3, &TIM_InitStruct);
LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
LL_TIM_OC_StructInit(&TIM_OC_InitStruct);
TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
TIM_OC_InitStruct.CompareValue = 0;
TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStruct);
LL_TIM_EnableARRPreload(TIM3);
LL_TIM_EnableDMAReq_UPDATE(TIM3);
LL_TIM_CC_SetDMAReqTrigger(TIM3,LL_TIM_CCDMAREQUEST_UPDATE);
}
//16位定时器
static uint16_t dma_buffer[128]= {0};
void timer3_dma_config(void)
{
LL_DMA_InitTypeDef dma_initstruct;
/* 使能DMA时钟 */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG);
LL_SYSCFG_SetDMARemap_CH1(LL_SYSCFG_DMA_MAP_TIM3_UP);
/* 配置DMA功能参数 */
dma_initstruct.PeriphOrM2MSrcAddress = (uint32_t)&(TIM3->CCR2); /* ????? */
dma_initstruct.MemoryOrM2MDstAddress = (uint32_t)dma_buffer; /* ?????? */
dma_initstruct.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; /* M2M ?? */
dma_initstruct.Mode = LL_DMA_MODE_NORMAL; /* DMA?????? */
dma_initstruct.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; /* ?????????? */
dma_initstruct.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; /* ??????????? */
dma_initstruct.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD; /* ???????32? */
dma_initstruct.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD; /* ????????32? */
dma_initstruct.NbData = 0x00000000U;
dma_initstruct.Priority = LL_DMA_PRIORITY_VERYHIGH; /* ??????? */
/* ???DMA */
if (LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_initstruct) != SUCCESS)
{
Error_Handler();
}
}
void timer3_dma_send_data(uint16_t *pbuf,uint16_t len)
{
LL_DMA_SetMemoryAddress(DMA1,LL_DMA_CHANNEL_1,(uint32_t)pbuf);
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, len);
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
LL_TIM_SetCounter(TIM3,TIM_ARR_VALUE);
LL_TIM_EnableCounter(TIM3);
while(!LL_DMA_IsActiveFlag_TC1(DMA1));
LL_TIM_DisableCounter(TIM3);
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
LL_DMA_ClearFlag_TC1(DMA1);
}
static uint32_t counter= 0;
void TIM3_IRQHandler(void)
{
counter++;
if(counter >= 500000)
{
counter = 0;
led_toggle();
}
}
void DMA1_Channel1_IRQHandler(void)
{
if(LL_DMA_IsActiveFlag_TC1(DMA1) == 1)
{
LL_DMA_ClearFlag_GI1(DMA1);
}
else if(LL_DMA_IsActiveFlag_TE1(DMA1) == 1)
{
}
}
timer1.c内容
#include "timer1.h"
#include "air001xx_ll_tim.h"
#include "air001xx_ll_bus.h"
#include "air001xx_ll_gpio.h"
#include "air001xx_ll_rcc.h"
#include "led.h"
void pwm_gpio_config(void)
{
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Alternate = LL_GPIO_AF13_TIM1;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void timer1_ch3_config(void)
{
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_TIM1);
LL_TIM_InitTypeDef TIM_InitStruct = {0};
LL_TIM_StructInit(&TIM_InitStruct);
TIM_InitStruct.Prescaler = 48-1;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 1000-1;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM1, &TIM_InitStruct);
NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
LL_TIM_EnableIT_UPDATE(TIM1);
LL_TIM_EnableCounter(TIM1);
}
static uint32_t counter= 0;
void TIM1_BRK_UP_TRG_COM_IRQHandler(void)
{
counter++;
if(counter >= 500000)
{
counter = 0;
led_toggle();
}
}
最近编辑记录 hzqlz (2024-03-29 21:33:17)
离线
主频48M,本来想用SPI+DMA的方式,结果分频到不了8M,所以就用DMA+PWM的方式驱动,虽然浪费内存
离线
以前用其他单片机没遇到这种问题,新出来的单片机还是慎用啊,这次疏忽了(能力问题)
最近编辑记录 hzqlz (2024-03-29 23:06:23)
离线
来来来,结帖,问题找到了,附上新的代码
timer1.c
#include "timer1.h"
#include "air001xx_ll_tim.h"
#include "air001xx_ll_bus.h"
#include "air001xx_ll_gpio.h"
#include "air001xx_ll_rcc.h"
#include "led.h"
void pwm_gpio_config(void)
{
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Alternate = LL_GPIO_AF13_TIM1;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void timer1_ch3_config(void)
{
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_TIM1);
LL_TIM_InitTypeDef TIM_InitStruct = {0};
LL_TIM_StructInit(&TIM_InitStruct);
TIM_InitStruct.Prescaler = 48-1;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 1000-1;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM1, &TIM_InitStruct);
NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn,1);
LL_TIM_ClearFlag_UPDATE(TIM1);
LL_TIM_EnableIT_UPDATE(TIM1);
LL_TIM_EnableCounter(TIM1);
}
static uint32_t counter= 0;
void TIM1_BRK_UP_TRG_COM_IRQHandler(void)
{
if(LL_TIM_IsActiveFlag_UPDATE(TIM1))
{
LL_TIM_ClearFlag_UPDATE(TIM1);
counter++;
if(counter >= 500)
{
counter = 0;
led_toggle();
}
}
}
最近编辑记录 hzqlz (2024-03-29 23:12:10)
离线
看样子是忘了清除TIM1中断标志,导致一直卡在TIM1中断里,从而TIM3中断无法正常处理
离线
看样子是忘了清除TIM1中断标志,导致一直卡在TIM1中断里,从而TIM3中断无法正常处理
按道理定时器中断不应该会影响到DMA传输,以前用其他芯片没有遇到这么奇怪的问题。
经过反复大量测试,这个芯片还是存在一些其他的坑,及时止损,我已经把这个项目停了,赶紧换其他芯片,先给大家试试水。
离线
air001是 py32f002a的马甲,现在合宙的芯片等全线涨价了。。。
离线
的用正常的mcu。国产的单一用用还可以
离线