cancel
Showing results for 
Search instead for 
Did you mean: 

Looking for simple low-level code to toggle a pin

Randy Nelson
Associate III
Posted on November 01, 2017 at 16:01

I'm not having any success in simply toggling a pin on a STM32F303 Nucleo-32 evaluation board. I'm using Keil uVision V5.24.2.0. Also I'm trying to do this at a level below the HAL interface. With the community's help I am able to do an simple ADC->DAC project that runs off the HSI as the system clock. Then I tried to toggle a pin to monitor the sampling rate with no luck. To learn about GPIO digital output pins I have created the simple project below. I'm looking for someone experience with the lower level programming to take a look and hopefully find my problem. Using my ADC->DAC program AND the data sheet, the STM32F303K8 part comes up with the clock defaulted to HSI so a clock setup for my test should not be needed (???). As seen, after the brief setup I'm trying various methods to toggle PA0 but with no success. Any ideas? What am I missing? Thanks... Randy

#include <stdint.h>

#define BIT0 (1 << 0)

#define BIT1 (1 << 1)

#define BIT16 (1 << 16)

#define BIT17 (1 << 17)

#define REGISTER_32(ADDRESS) (*((volatile uint32_t *)(ADDRESS)))

#define REGISTER_16(ADDRESS) (*((volatile uint16_t *)(ADDRESS)))

#define REGISTER_8(ADDRESS) (*((volatile uint8_t *)(ADDRESS)))

#define GPIOA_BASE 0x48000000

#define GPIOA_MODER REGISTER_32(GPIOA_BASE + 0)

#define PERIPH_BASE ((uint32_t)0x40000000)

#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)

#define RCC_BASE (AHB1PERIPH_BASE + 0x00001000)

#define RCC_AHBENR REGISTER_32(RCC_BASE + 0x14)

#define GPIOA_ODR REGISTER_32(GPIOA_BASE + 0x14)

#define GPIOA_BSRR REGISTER_32(GPIOA_BASE + 0x18)

#define GPIOA_BRR REGISTER_32(GPIOA_BASE + 0x28)

int main()

{

GPIOA_MODER |= BIT0; //set PA0 to digital. other setting default

GPIOA_MODER &= ~BIT1;

RCC_AHBENR |= BIT17; //Enable portA clock

while(1) {

GPIOA_ODR |= BIT0; //set

GPIOA_ODR &= ~BIT0; //reset

GPIOA_BSRR |= BIT0; //set

GPIOA_BRR |= BIT0; //reset

GPIOA_BSRR |= BIT16; //another type reset

}

return 0;

}
3 REPLIES 3
Posted on November 01, 2017 at 16:23

Probably want to enable the clock *before* you program synchronous registers...

Keil has a peripheral viewer, you should perhaps use that as you step your code.

>>

I'm looking for someone experience with the lower level programming to take a look and hopefully find my problem.

8th RULE:

If this is your first night at FIGHT CLUB, you HAVE to fight.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Randy Nelson
Associate III
Posted on November 01, 2017 at 17:56

Great catch!

The below change allows the pin to toggle.

RCC_AHBENR |= BIT17; //Enable portA clock

GPIOA_MODER |= BIT0; //set PA0 to digital. other setting default

GPIOA_MODER &= ~BIT1;

Thanks! Is the ordering of setting registers defined somewhere or is this just experience?

I'm looking through the RM0316 'STM32F303xB/C/D/E, STM32F303x6/8, STM32F328x8, STM32F358xC, STM32F398xE advanced ARM®-based MCUs' and cannot find a suggested ordering of register setups for GPIO pins.

Also any idea why these lines will toggle the pin:

GPIOA_ODR |= BIT0; //set

GPIOA_ODR &= ~BIT0; //reset

but these lines do not:

GPIOA_BSRR |= BIT0; //set

GPIOA_BRR |= BIT0; //reset

GPIOA_BSRR |= BIT16; //another type reset

Thanks...

Randy

Posted on November 01, 2017 at 18:58

Found in RM0316 where 'Before using a peripheral user has to enable its clock in the RCC_AHBENR, RCC_APB2ENR or RCC_APB1ENR register.' 

Now to better understand the GPIOx_BSRR and GPIOx_BSR.