0

I'm running some tests on STM32L152 by trying to control a DC motor speed by selecting 3 different speeds using a push button, as following:

  1. ideal mode, motor is off.
  2. push button pressed, motor runs at speed-1
  3. push button pressed again, motor runs at speed-2
  4. push button pressed again, motor stops.

I've already tried to run the motor directly by setting CCR1 (TIM4), and it works perfectly. so I believe the only issue is with the push button part. here's the code:

#include <stdio.h>
#include "stm32l1xx.h"                  // Keil::Device:Startup

// initialization of GPIOB, GPIOA & PWM/TIM4
void GPIO_Init()
{
// initialization of GPIOB
    RCC->AHBRSTR |= RCC_AHBRSTR_GPIOBRST; /* Reset GPIOB clock */
    RCC->AHBENR |= RCC_AHBENR_GPIOBEN; /* Enable GPIOB clock*/
    GPIOB->MODER &= ~(0x03 << (2 * 6)); /* Clear bit 12 & 13 Output mode*/
    GPIOB->MODER |= 0x01 << (2 * 6); /* set as Output mode*/
    GPIOB->OSPEEDR &= ~(0x03 << (2 * 6)); /* 40 MHz  speed */
    GPIOB->OSPEEDR |= 0x03 << (2 * 6); /* 40 MHz  speed*/
    GPIOB->PUPDR &= ~(1 << 6); /* NO PULL-UP PULL-DOWN*/
    GPIOB->OTYPER &= ~(1 << 6); /* PUSH-PULL*/
    GPIOB->AFR[0] |= 0x2 << (4 * 6);

// initialization of GPIOA
    RCC->AHBRSTR |= RCC_AHBRSTR_GPIOARST; /* Reset GPIOA clock*/
    RCC->AHBENR |= RCC_AHBENR_GPIOAEN; /* Enable GPIOA clock*/
    GPIOA->MODER &= ~(0x03); /* Clear & set as input*/
    GPIOA->OSPEEDR &= ~(0x03); /* 2 MHz  speed */
    GPIOA->OSPEEDR |= 0x01; /* 2 MHz  speed */
    GPIOA->PUPDR &= ~(0x03); /* No PULL-UP/DOWN */
    GPIOA->OTYPER &= ~(0x1); /* PUSH-PULL */

//initialization of PWM & TIM4 
    RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
    TIM4->PSC = 100;
    TIM4->ARR = 414; // F=2.097MHz , Fck= 2097000/(100+1)= 20.762KHz, Tpwm = 0.02, ARR= (Fck x Tpwm)-1

    TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;   // 111: PWM mode 1 
    TIM4->CCMR1 |= TIM_CCMR1_OC1PE;
    TIM4->CR1 |= TIM_CR1_ARPE;
    TIM4->CCER |= TIM_CCER_CC1E;
    TIM4->EGR |= TIM_EGR_UG;
    TIM4->SR &= ~TIM_SR_UIF;
    TIM4->DIER |= TIM_DIER_UIE;
    TIM4->CR1 |= TIM_CR1_CEN;
}

// Delay conf

void setSysTick(void)
{
// ---------- SysTick timer (1ms) -------- //
    if (SysTick_Config(SystemCoreClock / 1000))
    {
        // Capture error
        while (1)
        {
        };
    }
}

volatile uint32_t msTicks;      //counts 1ms timeTicks
void SysTick_Handler(void)
{
    msTicks++;
}

static void Delay(__IO uint32_t dlyTicks)
{
    uint32_t curTicks = msTicks;
    while ((msTicks - curTicks) < dlyTicks);
}

int returnVal = 0;
int updatedpress = 0;

int buttonpress()   // function to check & add, if the pushbutton is pressed
{

    if (GPIOA->IDR & GPIO_IDR_IDR_0)    //condition: if PA0 is set
    {
        Delay(500);   // avoid debouncing
        if (GPIOA->IDR & GPIO_IDR_IDR_0)   //confirm condition: if PA0 is set
        {
            returnVal = 1 + updatedpress;
            while (GPIOA->IDR & GPIO_IDR_IDR_0)
            {
            }
        }

    }

    return returnVal;
}

int main(void)
{

    GPIO_Init();
    setSysTick();

    while (1)
    {

        int buttonpress();

        updatedpress = returnVal;

        if (updatedpress == 1)
            TIM4->CCR1 = 30;

        else if (updatedpress == 2)
            TIM4->CCR1 = 37;

        else if (updatedpress == 3)
            TIM4->CCR1 = 46;

        else if (updatedpress > 3)
            returnVal = 0;

    }

}

When I run the code, nothing works physiclly. I tried to run the debugger and I found that it exits the buttonpress function immedtialy after reaching

 if(GPIOA->IDR & GPIO_IDR_IDR_0)

Any idea why it doesn't work as it should?

LPs
  • 16,045
  • 8
  • 30
  • 61
lightworks
  • 21
  • 1
  • 9
  • Why are you redeclaring buttonpress in your while loop? – stark May 09 '17 at 21:58
  • I'm trying to get the function buttonpress updated in every loop repetition. I agree with you, I removed the ' int ' but it still doesn't work. – lightworks May 10 '17 at 04:41
  • `int returnVal = 0;` should be local in main function and call to `buttonpress` should be `returnVal = buttonpress();` – LPs May 10 '17 at 06:10
  • but in this case, 'returnVal' and 'updatepress' must be declared again within the function 'buttonpress', otherwise, I'll just get an error saying that 'returnVal' and 'updatepress' are not declared (inside the function). Is it ok to declare a variable twice? – lightworks May 11 '17 at 06:40

2 Answers2

1

The GPIO peripherals are held in reset, you should clear the reset bits:

RCC->AHBRSTR |= RCC_AHBRSTR_GPIOBRST
RCC->AHBRSTR &= ~RCC_AHBRSTR_GPIOBRST

/* ... */

RCC->AHBRSTR |= RCC_AHBRSTR_GPIOARST;
RCC->AHBRSTR &= ~RCC_AHBRSTR_GPIOARST;
0

Ok it worked, and here are the corrections made:

1/ PB6 (which is connected to the DC motor) was mistakenly set as output. changed to Alternate Function.

2/ If-Conditions used for comparing the number of button-press and select motor speed is shifted to a separate function called runmotor

3/ The read instruction if(GPIOA->IDR & 0x0001) is moved into the while loop within the main function to ensure a continuous check of the pushbutton condition.

4/ Reset of GPIOs are cleared, as advised by @berendi

here's the updated code:

#include <stdio.h>
#include "stm32l1xx.h"                  // Keil::Device:Startup


// initialization of GPIOB, GPIOA & PWM/TIM4
void GPIO_Init(){
    // initialization of GPIOB
    RCC->AHBRSTR |= RCC_AHBRSTR_GPIOBRST;     /* Reset GPIOB clock*/
    RCC->AHBRSTR &= ~RCC_AHBRSTR_GPIOBRST;   /* Clear Reset */
    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;      /* Enable GPIOB clock*/
    GPIOB->MODER   &=   ~(0x03 << (2*6));  /* Clear bit 12 & 13 */
    GPIOB->MODER   |=   0x02 << (2*6);    /* set as Alternate function*/
    GPIOB->OSPEEDR &=   ~(0x03<< (2*6)); /* 40 MHz  speed*/
    GPIOB->OSPEEDR |=   0x03<< (2*6);   /* 40 MHz  speed */
    GPIOB->PUPDR &=         ~(1<<6);   /* NO PULL-UP PULL-DOWN*/
    GPIOB->OTYPER &=        ~(1<<6);  /* PUSH-PULL*/
    GPIOB->AFR[0] |=        0x2 << (4*6);

    // initialization of GPIOA
    RCC->AHBRSTR |= RCC_AHBRSTR_GPIOARST;    /* Reset GPIOA clock */
    RCC->AHBRSTR &= ~RCC_AHBRSTR_GPIOARST;  /* Clear Reset  */
    RCC->AHBENR |= RCC_AHBENR_GPIOAEN;     /* Enable GPIOA clock  */
    GPIOA->MODER   &=   ~(0x03);          /* Clear & set as input */
    GPIOA->OSPEEDR &=   ~(0x03);         /* 2 MHz  speed  */
    GPIOA->OSPEEDR |=   0x01;           /* 2 MHz  speed   */
    GPIOA->PUPDR &=         ~(0x03);   /* reset PULL-DOWN  */
    GPIOA->OTYPER &=        ~(0x1);   /* PUSH-PULL  */

    //initialization of PWM & TIM4 
    RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
    TIM4->PSC = 100; 
    TIM4->ARR = 414; // F=2.097MHz , Fck= 2097000/(100+1)= 20.762KHz, Tpwm = 0.02, ARR= (Fck x Tpwm)-1

    TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; // 111: PWM mode 1 
    TIM4->CCMR1 |= TIM_CCMR1_OC1PE;
    TIM4->CR1 |= TIM_CR1_ARPE;
    TIM4->CCER |= TIM_CCER_CC1E;
    TIM4->EGR |= TIM_EGR_UG;
    TIM4->SR &= ~TIM_SR_UIF;
    TIM4->DIER |= TIM_DIER_UIE;
    TIM4->CR1 |= TIM_CR1_CEN;
    }

    void setSysTick(void){
    // ---------- SysTick timer (1ms) -------- //
    if (SysTick_Config(SystemCoreClock / 1000)) {
        // Capture error
        while (1){};
    }
}


    volatile uint32_t msTicks;      //counts 1ms timeTicks
void SysTick_Handler(void) {
    msTicks++;
}

static void Delay(__IO uint32_t dlyTicks){                                              
  uint32_t curTicks = msTicks;
  while ((msTicks - curTicks) < dlyTicks);
}

    int buttonpress=0; 

     static void runmotor(void)
{
    if (buttonpress ==1){
            TIM4->CCR1 = 30;
    return;
        }
         if (buttonpress ==2){
            TIM4->CCR1 = 37;
    return;
         }
         if (buttonpress ==3){
            TIM4->CCR1 = 46;
    return;
         }
        if (buttonpress > 3){
            TIM4->CCR1 = 0;
            buttonpress = 0;
    return;
         }

}


int main(void){

    GPIO_Init();
    setSysTick();

while (1){  

      if(GPIOA->IDR & 0x0001)
    {
        Delay(5);
            if(GPIOA->IDR & 0x0001) 
                buttonpress = buttonpress + 1;
      runmotor();

}   
        }

    }
lightworks
  • 21
  • 1
  • 9