2011-04-28 09:44 AM
Hi,
I wanted to learn how to ''connect'' DMA and timers, so I am thinking about such application. App will circularly copy data from buffer to timer. Timer is set in PWM mode and in my data buffer are numbers starting from 0 to 99 (those are pulse values). I have LED connected to PA8, and my code gives no errors, however it doesn't work. LED should shine and from time to time changes it's brightness, but nothing happens, it is off all the time. Could anybody help me with this? I also have empty NVIC_Configuration function because I don't really know what should be there. Here is my code:
&sharpinclude ''stm32f10x.h''
&sharpinclude ''STM32vldiscovery.h''
void RCC_Configuration(void);
void GPIO_Configuration(void) ;
void NVIC_Configuration(void) ;
void DMA_Configuration(void) ;
void TIM1_Configuration(void) ;
int i = 0;
u16 PWM_Buffer[100];
/**************************************************************************************/
int main(void)
{
for(i=0 ; i < 100 ; i++) PWM_Buffer[i] = i;
RCC_Configuration();
GPIO_Configuration() ;
NVIC_Configuration() ;
DMA_Configuration();
TIM1_Configuration();
while(1);
}
/**************************************************************************************/
void RCC_Configuration(void)
{
// clock for GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO , ENABLE);
// clock for DMA
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// clock for TIM1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_8 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
}
/**************************************************************************************/
void DMA_Configuration(void)
{
DMA_DeInit(DMA1_Channel5);
DMA_InitTypeDef DMA_InitStructure ;
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM1_BASE;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)PWM_Buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 100;
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);
// turning DMA on
DMA_Cmd(DMA1_Channel5, ENABLE);
}
/**************************************************************************************/
void TIM1_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;
TIM_TimeBaseStructure.TIM_Period = 99;
TIM_TimeBaseStructure.TIM_Prescaler = 99;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 150;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
// channel 1 configuration
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 50;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
// ''connecting'' DMA and TIM1
TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);
// turning on TIM1 and PWM outputs
TIM_Cmd(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
/**************************************************************************************/
#dma-timers2011-04-28 02:00 PM
If you want to alter the PWM ON from 0-99% it might help to program the right register in the timer. I might tinker some more, but this seemed to be pretty fatal on a quick review.
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM1_CCR1_Address;2011-04-29 03:16 AM
I am using Atollic True Studio and I don't have this defined:
TIM1_CCR1_Address
But I found that this is equal to: 0x40012C34 so I changed that line, but it still doesn't work.
2011-04-29 09:23 AM
With TIM1_CCR1_Address 0x40012C34
The PA.08 output is 2.4 KHz (from 24 MHz core), and the on duty cycle sweeps from 0 to 99%, repetitively. Stick a scope on it, and observe. The LEDs built on the board are on PC.08 and PC.092011-04-29 11:53 AM
Here is a better example, using the on-board Blue PC.8 LED, and TIM3 CH3 with DMA1 Channel 3 shoveling PWM data on the TIM3 update (10 ms). This example uses a 10 KHz timer clock, a 100 Hz output frequency, with a 0-99% duty cycle phased over 1 second.
// PC.08, TIM3_CH3 (Remapped), DMA1 Channel 3 #define TIM3_CCR3_Address 0x4000043C void RCC_Configuration(void); void GPIO_Configuration(void) ; void NVIC_Configuration(void) ; void DMA_Configuration(void) ; void TIM3_Configuration(void) ; #define PWM_ELEMENTS 100 u16 PWM_Buffer[PWM_ELEMENTS]; /**************************************************************************************/ int main(void) { int i; for(i=0 ; i < PWM_ELEMENTS ; i++) PWM_Buffer[i] = i / (PWM_ELEMENTS / 100); RCC_Configuration(); GPIO_Configuration() ; NVIC_Configuration() ; DMA_Configuration(); TIM3_Configuration(); while(1); } /**************************************************************************************/ void RCC_Configuration(void) { // clock for GPIO (C, AFIO=REMAP) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO , ENABLE); // clock for DMA RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // clock for TIM3 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); } /**************************************************************************************/ void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure ; GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); } /**************************************************************************************/ void NVIC_Configuration(void) { } /**************************************************************************************/ void DMA_Configuration(void) { DMA_InitTypeDef DMA_InitStructure ; DMA_DeInit(DMA1_Channel3); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM3_CCR3_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)PWM_Buffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = PWM_ELEMENTS; 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_Channel3, &DMA_InitStructure); // turning DMA on DMA_Cmd(DMA1_Channel3, ENABLE); } /**************************************************************************************/ void TIM3_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_TimeBaseStructure.TIM_Period = 100-1; // 100 0..99 ON DUTY (100 Hz) Phases over 1 Second TIM_TimeBaseStructure.TIM_Prescaler = 2400-1; // 24 MHz div 2400 (10 KHz tick) TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter = 1; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); // channel 3 configuration (PC.08) Remapped TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 50; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC3Init(TIM3, &TIM_OCInitStructure); // ''connecting'' DMA and TIM3 TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE); // turning on TIM3 and PWM outputs TIM_Cmd(TIM3, ENABLE); TIM_CtrlPWMOutputs(TIM3, ENABLE); }2011-04-30 02:18 AM
Thank you very much! That solves my problem.