AnsweredAssumed Answered

PB8/9 interfering with each other when using timer/AF

Question asked by jordan.john on Oct 16, 2014
Latest reply on Oct 17, 2014 by jordan.john
Hi,

I have an STM32F103-based board and am trying to drive one GPIO pin (PB8) using the timer and another pin (PB9) under software control (set/reset). What I'm finding is that the config for PB8 appears to be interfering with PB9, and vice-versa. If I disable the timer for PB9, then PB8 functions as expected (I can toggle it using set/reset), but if I enable the timer, and select AF for PB8, then PB9 appears to get the timer output as well (or at least it measures half-voltage on my multimeter, at least). Also, writing the PB9 seems to stop the timer output on PB8. I'm stumped as to why this is happening.

Any insight would be much appreciated.

Here is the code:

#include <math.h>
#include <stdlib.h>

#include "stm32f10x_lib.h"

#include "sys.h"
#include "uart.h"
#include "rtc.h"

#define BATTERY_CHECK_TICK 1000

// stepper STEP
#define PORT_SIG_MOT6P      GPIOB
#define PIN_SIG_MOT6P       GPIO_Pin_8

// stepper SLEEP (supposedly)
#define PORT_SIG_MOT6M      GPIOB
#define PIN_SIG_MOT6M       GPIO_Pin_9

#define TIMER_PRESCALER     ((72 / 2) - 1)     // 72 MHz clock source, 0.5 us ticks
#define TIMER_PERIOD        5000 - 1;         // 2.5 msec STEP update (micro-stepping!... 400/scan)

void processCommand(void);

void gpioInit(void);
void timerInit(void);

void init(void);

/*******************************************************************************
* Function Name  : main
*******************************************************************************/

int main(void)
{
    u32 currTime;
    u32 batteryCheckTime;

    init();

    Sys_PrintString("Welcome to simple_gpio!\n");

    currTime = Rtc_GetTime();
    batteryCheckTime = (currTime + BATTERY_CHECK_TICK);

    while(1) {
        currTime = Rtc_GetTime();

        processCommand();

        if(currTime >= batteryCheckTime) {
            batteryCheckTime = (currTime + BATTERY_CHECK_TICK);
            Sys_CheckBatteryVoltage();
// re-test PB9: why does this cause the STEP to cease?... AND see '// re-test PB9' below!!!
#if 1
            {
                static bool on = FALSE;

                if (on==TRUE) {
                    on = FALSE;
                    GPIO_SetBits(PORT_SIG_MOT6M, PIN_SIG_MOT6M);
                }
                else {
                    on = TRUE;
                    GPIO_ResetBits(PORT_SIG_MOT6M, PIN_SIG_MOT6M);
                }
            }
#endif
    
        }
    }

    Sys_PrintString("Exiting!\n");

    return 0;
}

u32 intCount = 0;

void Timer4_Interrupt(void)
{
    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) {
        TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
    }

    intCount++;
}

void init(void)
{
    Sys_Init();

    GPIO_ResetBits(PORT_LED_AUX, PIN_LED_AUX);
    
    gpioInit();
    timerInit();
}

void gpioInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_StructInit(&GPIO_InitStructure);

    // stepper STEP / GPIO AF init
    GPIO_InitStructure.GPIO_Pin =  PIN_SIG_MOT6P;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
#if 0
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
#else
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
#endif
    GPIO_Init(PORT_SIG_MOT6P, &GPIO_InitStructure);

    // stepper SLEEP GPIO init
    GPIO_InitStructure.GPIO_Pin =      PIN_SIG_MOT6M;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// re-test PB9
#if 0
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
#else    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
#endif
    GPIO_Init(PORT_SIG_MOT6M, &GPIO_InitStructure);
}

void timerInit(void)
{
    TIM_OCInitTypeDef TIM_OC_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    /* Enable the TIM4 gloabal Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQChannel;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* TIM4 clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

    TIM_TimeBaseStructure.TIM_Prescaler = TIMER_PRESCALER;
    TIM_TimeBaseStructure.TIM_Period = TIMER_PERIOD;
    TIM_TimeBaseStructure.TIM_ClockDivision = 1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
 
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
 
    // TIM4 enable counter
    TIM_Cmd(TIM4, ENABLE);
    
    // Clear pending update interrupt
    TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
 
    // Enable interrupt on update
    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);

    TIM_OCStructInit (&TIM_OC_InitStructure);
//    TIM_OC_InitStructure.TIM_OCMode = TIM_OCMode_Toggle;
    TIM_OC_InitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OC_InitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
    TIM_OC_InitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC_InitStructure.TIM_OutputState = TIM_OutputState_Enable;
//    TIM_OC_InitStructure.TIM_Pulse = 0;
    TIM_OC_InitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period / 2;
// re-test PB9
#if 0
//    TIM_OC4Init(TIM4, &TIM_OC_InitStructure);    
#else
    TIM_OC3Init(TIM4, &TIM_OC_InitStructure);    
#endif
}

void processCommand(void)
{
    u8 rxData;
    
    if(Sys_IsCharWaiting()) {
        rxData = Sys_GetChar();

        switch (rxData) {
        case 'q':
            {
                u32 startTime = Rtc_GetTime();
                u32 endTime = startTime;

                while ((intCount%400) != 0) {
                    endTime = Rtc_GetTime();
                    if ((endTime-startTime) > 2000) {
                        Sys_PrintString("Timed out waiting for scanner to park!\n");
                        Sys_PrintString("start: ");
                        Sys_Printu32d(startTime);
                        Sys_PrintString(", end: ");
                        Sys_Printu32d(endTime);
                        Sys_PrintString("\n");
                        break;
                    }
                };
                // scanner (TIM4) disable clock
                RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, DISABLE);
                if ((endTime-startTime) < 2000) {
                    Sys_PrintString("Scanner is parked!\n");
                }
            }

            NVIC_GenerateSystemReset();
            break;
        }
    }
}

Outcomes