2014-05-02 04:23 AM
I'm stuck on figuring out how to set a PWM output with the F4 Nucleo board.
Could a kind and gentle soul please walk me through all of the code needed for a simple 10kHz 20% duty PWM on PA5, which is connected to LD2 on the F4 Nucleo.I've tried CubeMX, but I don't fully understand all of the parameters. With a single non-mbed example, I believe I'll be set.Thank you2014-05-02 07:01 AM
Here are a couple of blind ports from the STM32F401C-DISCO which should work,
// STM32 TIM2_CH1 PA.5 LED 10 KHz 20% NUCLEO-401C - sourcer32@gmail.com
#include ''stm32f4xx.h''
/**************************************************************************************/
void RCC_Configuration(void)
{
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*-------------------------- GPIO Configuration ----------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect TIM2 pins to AF */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_TIM2);
}
/**************************************************************************************/
void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
uint32_t Period;
Period = (SystemCoreClock / 10000); // 10 KHz tick
TIM_TimeBaseStructure.TIM_Prescaler = 0; // DIV1
TIM_TimeBaseStructure.TIM_Period = Period - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 1;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// channel 1 configuration (PA.5)
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = Period / 5; // 20%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
// turning on TIM2 and PWM outputs
TIM_Cmd(TIM2, ENABLE);
}
/**************************************************************************************/
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
TIM2_Configuration();
while(1);
}
/**************************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d
'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**************************************************************************************/
// STM32 TIM2_CH1 PA.5 LED DMA PWM Phaser NUCLEO-401C - sourcer32@gmail.com
#include ''stm32f4xx.h''
#define PWM_ELEMENTS 100
#define INIT
#ifdef INIT
u32 PWM_Buffer[PWM_ELEMENTS]; // TIM2 is 32-bit!
#else
const u32 PWM_Buffer[PWM_ELEMENTS] = { // Sine Table
0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 50, 53, 56,
58, 61, 63, 66, 68, 70, 72, 75, 77, 79, 80, 82, 84, 86, 87, 89, 90, 91, 92, 94,
95, 96, 96, 97, 98, 98, 99, 99, 99, 99,100, 99, 99, 99, 99, 98, 98, 97, 96, 96,
95, 94, 92, 91, 90, 89, 87, 86, 84, 82, 80, 79, 77, 75, 72, 70, 68, 66, 63, 61,
58, 56, 53, 50, 48, 45, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3 };
#endif
/**************************************************************************************/
void RCC_Configuration(void)
{
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* DMA1 clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*-------------------------- GPIO Configuration ----------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect TIM2 pins to AF */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_TIM2);
}
/**************************************************************************************/
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStruct;
// TIM2_UP - DMA1, Channel 3, Stream 1
DMA_InitStruct.DMA_Channel = DMA_Channel_3;
DMA_InitStruct.DMA_BufferSize = PWM_ELEMENTS;
DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&PWM_Buffer[0];
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&TIM2->CCR1;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
DMA_Init(DMA1_Stream1, &DMA_InitStruct);
// turning DMA on
DMA_Cmd(DMA1_Stream1, ENABLE);
}
/**************************************************************************************/
void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / 10000) - 1; // 10 KHz tick
TIM_TimeBaseStructure.TIM_Period = 100-1; // 100 0..99 ON DUTY (100 Hz) Phases over 1 Second
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 1;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// channel 1 configuration (PA.5)
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(TIM2, &TIM_OCInitStructure);
// ''connecting'' DMA and TIM2 (DMA1 Channel 3, Stream 1)
TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);
// turning on TIM2 and PWM outputs
TIM_Cmd(TIM2, ENABLE);
}
/**************************************************************************************/
int main(void)
{
#ifdef INIT
int i;
for(i=0 ; i < PWM_ELEMENTS ; i++) PWM_Buffer[i] = i / (PWM_ELEMENTS / 100);
#endif
RCC_Configuration();
GPIO_Configuration();
DMA_Configuration();
TIM2_Configuration();
while(1);
}
/**************************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d
'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**************************************************************************************/