Practical STM32 differences compared to AVR

I’ve been playing with the STM32 header board for a while now, so today I’d like to write about some practical differences between the STM32 and AVR. At first I wanted to use Cortex-M3 instead of STM32, but that wouldn’t be correct since the Cortex-M3 is only the core, while the peripherals is where most of the practical differences lie. Also note I’m talking about programming using C/C++, not assembly.

Clock signals

On an AVR you can simply set/clear a bit in the appropriate register to make a GPIO pin high or low. Not so on the STM32. While the concept of setting a bit remains the same (there are differences such as atomic write access, but you won’t notice those during normal usage), the difference is that they won’t do anything until you enable the corresponding peripheral. Before going any further take a look at the system architecture diagram:

As you can see in this diagram the STM32 has a couple of busses; an AHB and 2 APB busses. Each peripheral is connected to one of those busses and will only do something if it gets a clock signal. After a reset all clocks are disabled, including the system clock (please look up CMSIS’ SystemInit() function for info on enabling the Embedded Flash Interface, the PLL and SystemCoreClock). Before using a peripheral look up which bus it is connected to and set the corresponding bit in the RCC register to enable its clock signal. If for example you want to use GPIOA, you need to set the IOPAEN bit in the RCC_APB2ENR register. Another GPIO difference is that you must choose between 3 speeds; 2MHz, 10MHz or 50MHz.

But that’s not all concerning clock signals. Peripherals such as USARTs and SPI are mapped to the same pins as GPIO pins. Even though you can not use both at the same time, the GPIO pins have to be initialised as usual (clock enabled, input/output, speed and mode (floating/push-pull/etc)) as used by the used peripheral. On top of that you get clocks for the alternate function and the peripheral itself. That’s 3 clock signals total which all have to be enabled.

Shift registers

Another issue I ran into was the use of shift registers. Peripherals such as USART and SPI only have a data register on the AVR. Just write a byte to it and the AVR blocks until the byte is transmitted. The STM32 takes a slightly different approach. You write data to the data register which is blocking. Next the data is moved into a shift register for transmission and execution continues.

In reality this means that your code continues and for example deactivates the chip select signal of some other IC (e.g. the audio decoder in case of the music player) while data is still being transmitted. The result is a partial reception of the data and nothing happens. The solution is to wait for a status bit to clear before deactivating any chip select signal (in case of SPI; the BSY bit in the SPI_SR register as seen in the above diagram).

That’s it for now.

Comments are closed.