2014-06-17 04:45 AM
Hello everyone. I am creating a hexapod with 18 independent servos, using 18 channels on General - Purpose timers. I have problem with few timers, simply servo is not responding to new compare value. I am using timers:
TIM2 - 4 channels working TIM3 - 4 channels working TIM4 - 4 channels working TIM5 - chanel 2 and 3 not working TIM12 - not working Do I have some conflicts with alternative configuration ? My init for timers/pwm:
void initTimer()
{
RCC_TIMCLKPresConfig(RCC_TIMPrescActivated);
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* TIM4 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
/* TIM5 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
/* TIM12 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Compute the prescaler value */
uint16_t u16PrescalerValue = (uint16_t) ((SystemCoreClock) / 1000000)- 1;
TIM_TimeBaseStructure.TIM_Prescaler = u16PrescalerValue; // 1MHz
TIM_TimeBaseStructure.TIM_Period = 20000 - 1; // 1 MHz / 20000 = 50 Hz (20ms)
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
TIM_TimeBaseInit(TIM12, &TIM_TimeBaseStructure);
}
void initPWM()
{
/*
* Servo min(1ms) = 1000
* Servo neutral (1,5ms) = 1500
* Servo max(2ms) = 2000
*
*/
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;
/*********************TIM2**************************/
/* PWM1 Mode configuration: Channel1 (GPIOA Pin 15)*/
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel2 (GPIOB Pin 3)*/
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel3 (GPIOB Pin 10)*/
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel4 (GPIOB Pin 11)*/
TIM_OC4Init(TIM2, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable );
/*********************TIM3**************************/
/* PWM1 Mode configuration: Channel1 (GPIOB Pin 4)*/
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel2 (GPIOB Pin 5)*/
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel3 (GPIOB Pin 0)*/
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel4 (GPIOB Pin 1)*/
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable );
/*********************TIM4**************************/
/* PWM1 Mode configuration: Channel1 (GPIOD Pin 12)*/
TIM_OC1Init(TIM4, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel2 (GPIOD Pin 13)*/
TIM_OC2Init(TIM4, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel3 (GPIOD Pin 14)*/
TIM_OC3Init(TIM4, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel4 (GPIOD Pin 15)*/
TIM_OC4Init(TIM4, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable );
/*********************TIM5**************************/
/* PWM1 Mode configuration: Channel1 (GPIOA Pin 0)*/
TIM_OC1Init(TIM5, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel2 (GPIOA Pin 1)*/
TIM_OC2Init(TIM5, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM5, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel3 (GPIOA Pin 2)*/
TIM_OC3Init(TIM5, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM5, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel4 (GPIOA Pin 3)*/
TIM_OC4Init(TIM5, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM5, TIM_OCPreload_Enable );
/*********************TIM12*************************/
/* PWM1 Mode configuration: Channel1 (GPIOB Pin 14)*/
TIM_OC1Init(TIM12, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM12, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel2 (GPIOB Pin 15)*/
TIM_OC2Init(TIM12, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM12, TIM_OCPreload_Enable );
/*********************TIM9*************************/
/* PWM1 Mode configuration: Channel1 (GPIOE Pin 5)*/
TIM_OC1Init(TIM9, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM9, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel2 (GPIOE Pin 6)*/
TIM_OC2Init(TIM9, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM9, TIM_OCPreload_Enable );
//enable timers
TIM_Cmd(TIM2, ENABLE);
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM4, ENABLE);
TIM_Cmd(TIM5, ENABLE);
TIM_Cmd(TIM9, ENABLE);
TIM_Cmd(TIM12, ENABLE);
}
void initServos()
{
GPIO_InitTypeDef GPIO_PWM;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
GPIO_PWM.GPIO_Mode = GPIO_Mode_AF;
GPIO_PWM.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_PWM.GPIO_OType = GPIO_OType_PP;
GPIO_PWM.GPIO_PuPd = GPIO_PuPd_UP;
//PORT A
GPIO_PWM.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_15;
GPIO_Init(GPIOA, &GPIO_PWM);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM5 );
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM5 );
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM5 );
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM5 );
GPIO_PinAFConfig(GPIOA, GPIO_PinSource15,GPIO_AF_TIM2 );
//PORT B
GPIO_PWM.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_PWM);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM3 );
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_TIM3 );
GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_TIM2 );
GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_TIM3 );
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_TIM3 );
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10,GPIO_AF_TIM2 );
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11,GPIO_AF_TIM2 );
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14,GPIO_AF_TIM12 );
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15,GPIO_AF_TIM12 );
//PORT D
GPIO_PWM.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOD, &GPIO_PWM);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4 );
GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4 );
GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_TIM4 );
GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_TIM4 );
}
#pwm #stm32f4 #discovery #output
2014-06-17 05:20 AM
Unless you've addressed them, there are a number of physical pin conflicts on the STM32F429I-DISCO
Line numbers make it undesirable to test the code.2014-06-17 09:49 AM
2014-06-17 11:10 AM
Consider configuring all the fields of the
TIM_OCInitStructure
/**
* @brief Fills each TIM_OCInitStruct member with its default value.
* @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure which will
* be initialized.
* @retval None
*/
void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct)
{
/* Set the default configuration */
TIM_OCInitStruct->TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStruct->TIM_OutputState = TIM_OutputState_Disable;
TIM_OCInitStruct->TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStruct->TIM_Pulse = 0x00000000;
TIM_OCInitStruct->TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct->TIM_OCNPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct->TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStruct->TIM_OCNIdleState = TIM_OCNIdleState_Reset;
}
2014-06-17 11:53 AM
/**
* @brief Fills each TIM_OCInitStruct member with its default value.
* @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure which will
* be initialized.
* @retval None
*/
void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct)
{
/* Set the default configuration */
TIM_OCInitStruct->TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStruct->TIM_OutputState = TIM_OutputState_Disable;
TIM_OCInitStruct->TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStruct->TIM_Pulse = 0x00000000;
TIM_OCInitStruct->TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct->TIM_OCNPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct->TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStruct->TIM_OCNIdleState = TIM_OCNIdleState_Reset;
}
TIM_OCInitStruct->TIM_OCMode = TIM_OCMode_Timing; for PWM?
2014-06-17 12:04 PM
I have used this default initialization and then changed only mode to PWM1 but didn't help :\
2014-06-17 12:05 PM
I'm suggesting that you initialize all the fields, either explicitly in your code, with your values, or by using the library function and then setting your subset.
2014-06-17 01:13 PM
Do you have any examples with PWM for TIM5 and TIM12 ?
2014-06-17 04:46 PM
I have created little test app for TIM5. Channel 1 and 4 are working, Channelse 2 and 3 not. Source code:
void initUSART1(uint32_t baudrate);
void initPWM();
uint8_t g_u8DataReceived = 0;
char g_u8Character = '0';
int main(void)
{
initUSART1(9600);
initPWM();
/* Infinite loop */
while (1)
{
if(g_u8DataReceived)
{
//reset flag
g_u8DataReceived = 0;
switch(g_u8Character)
{
case '1':
{
TIM_SetCompare1(TIM5, NEUTRAL);
TIM_SetCompare2(TIM5, NEUTRAL);
TIM_SetCompare3(TIM5, NEUTRAL);
TIM_SetCompare4(TIM5, NEUTRAL);
}
break;
case '2':
{
TIM_SetCompare1(TIM5, DEGREE0);
TIM_SetCompare2(TIM5, DEGREE0);
TIM_SetCompare3(TIM5, DEGREE0);
TIM_SetCompare4(TIM5, DEGREE0);
}
break;
case '3':
{
TIM_SetCompare1(TIM5, DEGREE180);
TIM_SetCompare2(TIM5, DEGREE180);
TIM_SetCompare3(TIM5, DEGREE180);
TIM_SetCompare4(TIM5, DEGREE180);
}
break;
}
}
}
}
void initPWM()
{
/* TIM5 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Compute the prescaler value */
uint16_t u16PrescalerValue = (uint16_t) ((SystemCoreClock) / 1000000)- 1;
TIM_TimeBaseStructure.TIM_Prescaler = u16PrescalerValue; // 1MHz
TIM_TimeBaseStructure.TIM_Period = 20000 - 1; // 1 MHz / 20000 = 50 Hz (20ms)
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
/*
* Servo min(1ms) = 1000
* Servo neutral (1,5ms) = 1500
* Servo max(2ms) = 2000
*
*/
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;
/*********************TIM5**************************/
/* PWM1 Mode configuration: Channel1 (GPIOA Pin 0)*/
TIM_OC1Init(TIM5, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel2 (GPIOA Pin 1)*/
TIM_OC2Init(TIM5, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM5, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel3 (GPIOA Pin 2)*/
TIM_OC3Init(TIM5, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM5, TIM_OCPreload_Enable );
/* PWM1 Mode configuration: Channel4 (GPIOA Pin 3)*/
TIM_OC4Init(TIM5, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM5, TIM_OCPreload_Enable );
TIM_Cmd(TIM5, ENABLE);
///////////////GPIO CONFIGURATION///////////////
GPIO_InitTypeDef GPIO_PWM;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_PWM.GPIO_Mode = GPIO_Mode_AF;
GPIO_PWM.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_PWM.GPIO_OType = GPIO_OType_PP;
GPIO_PWM.GPIO_PuPd = GPIO_PuPd_UP;
//PORT A
GPIO_PWM.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_Init(GPIOA, &GPIO_PWM);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM5 );
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM5 );
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM5 );
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM5 );
}
// this is the interrupt request handler (IRQ) for ALL USART1 interrupts
void USART1_IRQHandler(void)
{
if( USART_GetITStatus(USART1, USART_IT_RXNE) != RESET )
{
g_u8Character = USART_ReceiveData(USART1);
g_u8DataReceived = 1;
}
}
void initUSART1(uint32_t baudrate)
{
GPIO_InitTypeDef GPIO_InitStruct; // this is for the GPIO pins used as TX and RX
USART_InitTypeDef USART_InitStruct; // this is for the USART1 initilization
NVIC_InitTypeDef NVIC_InitStructure; // this is used to configure the NVIC (nested vector interrupt controller)
/* enable APB2 peripheral clock for USART1
* note that only USART1 and USART6 are connected to APB2
* the other USARTs are connected to APB1
*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* enable the peripheral clock for the pins used by
* USART1, PB6 for TX and PB7 for RX
*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* This sequence sets up the TX and RX pins
* so they work correctly with the USART1 peripheral
*/
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // Pins 6 (TX) and 7 (RX) are used
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; // the pins are configured as alternate function so the USART peripheral has access to them
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // this defines the IO speed and has nothing to do with the baudrate!
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; // this defines the output type as push pull mode (as opposed to open drain)
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // this activates the pullup resistors on the IO pins
GPIO_Init(GPIOB, &GPIO_InitStruct); // now all the values are passed to the GPIO_Init() function which sets the GPIO registers
/* The RX and TX pins are now connected to their AF
* so that the USART1 can take over control of the
* pins
*/
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1 );
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1 );
/* Now the USART_InitStruct is used to define the
* properties of USART1
*/
USART_InitStruct.USART_BaudRate = baudrate; // the baudrate is set to the value we passed into this init function
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // we want the data frame size to be 8 bits (standard)
USART_InitStruct.USART_StopBits = USART_StopBits_1; // we want 1 stop bit (standard)
USART_InitStruct.USART_Parity = USART_Parity_No; // we don't want a parity bit (standard)
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // we don't want flow control (standard)
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // we want to enable the transmitter and the receiver
USART_Init(USART1, &USART_InitStruct); // again all the properties are passed to the USART_Init function which takes care of all the bit setting
/* Here the USART1 receive interrupt is enabled
* and the interrupt controller is configured
* to jump to the USART1_IRQHandler() function
* if the USART1 receive interrupt occurs
*/
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // enable the USART1 receive interrupt
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // we want to configure the USART1 interrupts
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // this sets the priority group of the USART1 interrupts
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // this sets the subpriority inside the group
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // the USART1 interrupts are globally enabled
NVIC_Init(&NVIC_InitStructure); // the properties are passed to the NVIC_Init function which takes care of the low level stuff
// finally this enables the complete USART1 peripheral
USART_Cmd(USART1, ENABLE);
}
2014-06-17 05:04 PM
Isn't there just a pin conflict you aren't dealing with?