Tone:

   Let's move on now to some hardware features of the Stm32 Cortex M3, namely one of the many timers on board ... Timer2!

And let's attempt to generate a 1000 Hz fixed frequency tone using Timer2, Channel_1 and Channel_2 in Anti-Phase Output mode!

Speaking as an ex-AVR Assembler freak, the major difference between such a routine in ARM assembly to one in AVR assembly,

lies in the fact that the ARM Timer has 14 * 16/32-Bit registers which one has to learn. This compares with 6 * 8-Bit registers in

a typical AVR-Mega timer! However the good news for AVR freaks is, that it's just more of the same! In addition, the fact, that one has

learned to program in assembly with an AVR Risc processor, provides a secure basis for learning to program an ARM Risc processor!

The formula for calculating the Frequency to be output is as follows:

Frequency = 72,000,000 /2 / (PreScaler * Period)

PreScaler * Period = 36,000,000 / Frequency

Let PreScaler  = 1

Let Frequency = 1000 Hz

Period = 36,000,000  /  (1000 * 1)

Period = 36,000

You can try out the formula using different values for Frequency, PreScaler and Period.

To listen to the tone, you can connect a small Earphone speaker ( > 16 Ohms) between Pins 11 + 12 on Header P2 onboard the Stm32 Mini!

" Get wise, digitise! "

Download

__asm void Tone() {
//********************************************************************************* 
TIM2_CR1         equ     0x40000000          ; Timer2 Base 
GPIOA_CRL     equ     0x40010800           ; Gpio_A Base
RCC_CR            equ     0x40021000          ; Rcc Base
PreScl                 equ     1                             ; PreScaler           = 1
Period                 equ     36000                     ; Period = 500uS
;------ 
Start
    ldr      r1,        =RCC_CR                         ; R1 > RCC_CR Base
    movw r0,        #0x0005                             ; 1 > PortA + AF 
    str r0,             [r1,#0x18]                          ; R0 > @RCC_APB2ENR 
    movw r0,       #0x0001                              ; 1 > Timer2 
    str r0,           [r1,#0x1c]                            ; R0 > @RCC_APB1ENR 

    ldr r1,            =GPIOA_CRL                   ; R1 > GPIOA_CRL Base 
    ldr r0,            =0x444443bb                      ; PortA_2= General Push_Pull:PortA_0_1=Alternative Push_Pull 
    str r0,            [r1,#0x00]                           ; R0 > @GPIOA_CRL 

    ldr r1,            =TIM2_CR1                     ; R1 > TIM2_CR1 Base
    movw r0,        #0x0013                            ; 1 > Chs 1+2 AntiPhase Ouputs
    str r0,            [r1,#0x20]                          ; R0 > @TIM2_CCER 

    movw r0,       #0x3838                            ; R0 > @TIM2_CCMR1 
    str r0,            [r1,#0x18]                         ; Toggle Mode Ch1+Ch2 > @TIM2_CCMR1

    movw r0,      #0x0081                             ; R0 < ARPE+CEN 
    str r0,          [r1,#0x00]                           ; R1 > @TIM2_CR1

    movw r0,     #PreScl                               ; R0 > @TIM2_CCER
    str r0,          [r1,#0x28]                           ; Prescaler > @TIM2_PSC

    movw r0,     #Period                               ; R0 < ARPE+CEN @TIM2_CR1 
    str r0,          [r1,#0x2c]                           ; Period > @TIM2_ARR

    bal              .                                           ; < Here forever!

    ALIGN                                                  ; Pad out evenly 
//******************************************************************************** 
// Main C Routine
//********************************************************************************
} int main() { Tone(); }