This program outputs a 50Hz complimentary Sinusoidal PWM signal on PA8 and PB13 on the STM32 Nucleo F103 board. The switching speed is 10kHz. The program uses a mix of mbed functions and/ direct register writes. It makes use of a lookup table generated in Octave (Thanks Richard Hayes) and interrupts to update the duty cycle.

Dependencies:   mbed

main.cpp

Committer:
f3d
Date:
2015-12-07
Revision:
0:d2382fd0cc1a

File content as of revision 0:d2382fd0cc1a:

// This program outputs a 50Hz complimentary Sinusoidal PWM signal on PA8 and PB13.
// The switching speed is 10kHz.  The program uses a mix of mbed functions and
// direct register writes.  It makes use of a lookup table generated in Octave (Thanks Richard Hayes)
// and interrupts to update the duty cycle.
#include "mbed.h"
// Define some bitmasks
#define BIT0 (1 << 0)
#define BIT1 (1 << 1)
#define BIT2 (1 << 2)
#define BIT3 (1 << 3)
#define BIT4 (1 << 4)
#define BIT5 (1 << 5)
#define BIT6 (1 << 6)
#define BIT7 (1 << 7)
#define BIT8 (1 << 8)
#define BIT9 (1 << 9)
#define BIT10 (1 << 10)
#define BIT11 (1 << 11)
#define BIT12 (1 << 12)
#define BIT13 (1 << 13)
#define BIT14 (1 << 14)
#define BIT15 (1 << 15)
#define BIT16 (1 << 16)
#define BIT17 (1 << 17)
#define BIT18 (1 << 18)
#define BIT19 (1 << 19)
#define BIT20 (1 << 20)
#define BIT21 (1 << 21)
#define BIT22 (1 << 22)
#define BIT23 (1 << 23)
#define BIT24 (1 << 24)
#define BIT25 (1 << 25)
#define BIT26 (1 << 26)
#define BIT27 (1 << 27)
#define BIT28 (1 << 28)
#define BIT29 (1 << 29)
#define BIT30 (1 << 30)
#define BIT31 (1 << 31)
DigitalOut myled(LED1);
const int duties[]={\
    50,51,53,54,56,57,59,60,62,63,65,66,68,69,71,72,74, \
    75,76,78,79,80,81,83,84,85,86,87,88,89,90,91,92,93,\
    93,94,95,95,96,97,97,98,98,98,99,99,99,99,99,99,100,\
    99,99,99,99,99,99,98,98,98,97,97,96,95,95,94,93,93,\
    92,91,90,89,88,87,86,85,84,83,81,80,79,78,76,75,74,\
    72,71,69,68,66,65,63,62,60,59,57,56,54,53,51,49,48,\
    46,45,43,42,40,39,37,36,34,33,31,30,28,27,25,24,23,\
    21,20,19,18,16,15,14,13,12,11,10,9,8,7,6,6,5,4,4,3,\
    2,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,3,4,4,\
    5,6,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,23,24,\
    25,27,28,30,31,33,34,36,37,39,40,42,43,45,46,48\    
};
/*
Pin mappings for Timer 1 (the advanced timer with deadtime)
From: https://developer.mbed.org/users/mbed_official/code/mbed-src/file/a11c0372f0ba/targets/hal/TARGET_STM/TARGET_STM32F1/TARGET_NUCLEO_F103RB/PeripheralPins.c
    {PA_8,  PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH1 - Default
    {PA_9,  PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH2 - Default
    {PA_10, PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH3 - Default
    {PB_13, PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH1N - Default
    {PB_14, PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH2N - Default
    {PB_15, PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH3N - Default
 
*/
// Use mbed to configure the relevant pins as PWM outputs;
PwmOut      PhaATop(PA_8);    
PwmOut      PhaABtm(PB_13);  // This should be the complement of PA_8  
AnalogIn    Pot(A0);
volatile float PotValue;
void init(void);
int main() {    

    init();
    while(1) {
        myled = 1; // LED is ON
        wait(0.1); // 200 ms
        myled = 0; // LED is OFF
        wait(0.1); // 1 sec        
        PotValue = Pot;
    }
}
int index=0;
void TimerISR()
{       
    TIM1->SR &= ~0x3f; // ack the interrupt    
    TIM1->CCR1=duties[index++]; // get the next duty
    if (index > 199)
        index = 0;   
}
void init()
{
    
    RCC->APB2ENR |= BIT2+BIT3;  // enable GPIOA and GPIOB    
    RCC->APB2ENR |= BIT11;      // enable TIM1
    
    GPIOA->CRH |= BIT3+BIT0;    // PA8 output, alternate function
    GPIOB->CRH |= BIT23+BIT20;  // PB13 output, alternate function
    
    TIM1->CR2 = 0;
    TIM1->DIER = BIT0; // Want update interrupt
    NVIC_SetVector(TIM1_UP_IRQn,(uint32_t) TimerISR);   
    NVIC_EnableIRQ(TIM1_UP_IRQn);
    TIM1->SR = 0;      // Clear flags.
    TIM1->CCMR1= BIT6+BIT5+BIT4;
    TIM1->CCER = BIT2+BIT0;
    TIM1->ARR = 100;  // 1MHz = base clock freq.  Divide by 100 to get 10kHz.
    TIM1->CCR1 = 10;  // Low inital duty
    TIM1->CR1 |= BIT0; //enable counter
     __enable_irq();   // enable interrupts

}