
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@0:d2382fd0cc1a, 2015-12-07 (annotated)
- Committer:
- f3d
- Date:
- Mon Dec 07 15:38:21 2015 +0000
- Revision:
- 0:d2382fd0cc1a
First commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
f3d | 0:d2382fd0cc1a | 1 | // This program outputs a 50Hz complimentary Sinusoidal PWM signal on PA8 and PB13. |
f3d | 0:d2382fd0cc1a | 2 | // The switching speed is 10kHz. The program uses a mix of mbed functions and |
f3d | 0:d2382fd0cc1a | 3 | // direct register writes. It makes use of a lookup table generated in Octave (Thanks Richard Hayes) |
f3d | 0:d2382fd0cc1a | 4 | // and interrupts to update the duty cycle. |
f3d | 0:d2382fd0cc1a | 5 | #include "mbed.h" |
f3d | 0:d2382fd0cc1a | 6 | // Define some bitmasks |
f3d | 0:d2382fd0cc1a | 7 | #define BIT0 (1 << 0) |
f3d | 0:d2382fd0cc1a | 8 | #define BIT1 (1 << 1) |
f3d | 0:d2382fd0cc1a | 9 | #define BIT2 (1 << 2) |
f3d | 0:d2382fd0cc1a | 10 | #define BIT3 (1 << 3) |
f3d | 0:d2382fd0cc1a | 11 | #define BIT4 (1 << 4) |
f3d | 0:d2382fd0cc1a | 12 | #define BIT5 (1 << 5) |
f3d | 0:d2382fd0cc1a | 13 | #define BIT6 (1 << 6) |
f3d | 0:d2382fd0cc1a | 14 | #define BIT7 (1 << 7) |
f3d | 0:d2382fd0cc1a | 15 | #define BIT8 (1 << 8) |
f3d | 0:d2382fd0cc1a | 16 | #define BIT9 (1 << 9) |
f3d | 0:d2382fd0cc1a | 17 | #define BIT10 (1 << 10) |
f3d | 0:d2382fd0cc1a | 18 | #define BIT11 (1 << 11) |
f3d | 0:d2382fd0cc1a | 19 | #define BIT12 (1 << 12) |
f3d | 0:d2382fd0cc1a | 20 | #define BIT13 (1 << 13) |
f3d | 0:d2382fd0cc1a | 21 | #define BIT14 (1 << 14) |
f3d | 0:d2382fd0cc1a | 22 | #define BIT15 (1 << 15) |
f3d | 0:d2382fd0cc1a | 23 | #define BIT16 (1 << 16) |
f3d | 0:d2382fd0cc1a | 24 | #define BIT17 (1 << 17) |
f3d | 0:d2382fd0cc1a | 25 | #define BIT18 (1 << 18) |
f3d | 0:d2382fd0cc1a | 26 | #define BIT19 (1 << 19) |
f3d | 0:d2382fd0cc1a | 27 | #define BIT20 (1 << 20) |
f3d | 0:d2382fd0cc1a | 28 | #define BIT21 (1 << 21) |
f3d | 0:d2382fd0cc1a | 29 | #define BIT22 (1 << 22) |
f3d | 0:d2382fd0cc1a | 30 | #define BIT23 (1 << 23) |
f3d | 0:d2382fd0cc1a | 31 | #define BIT24 (1 << 24) |
f3d | 0:d2382fd0cc1a | 32 | #define BIT25 (1 << 25) |
f3d | 0:d2382fd0cc1a | 33 | #define BIT26 (1 << 26) |
f3d | 0:d2382fd0cc1a | 34 | #define BIT27 (1 << 27) |
f3d | 0:d2382fd0cc1a | 35 | #define BIT28 (1 << 28) |
f3d | 0:d2382fd0cc1a | 36 | #define BIT29 (1 << 29) |
f3d | 0:d2382fd0cc1a | 37 | #define BIT30 (1 << 30) |
f3d | 0:d2382fd0cc1a | 38 | #define BIT31 (1 << 31) |
f3d | 0:d2382fd0cc1a | 39 | DigitalOut myled(LED1); |
f3d | 0:d2382fd0cc1a | 40 | const int duties[]={\ |
f3d | 0:d2382fd0cc1a | 41 | 50,51,53,54,56,57,59,60,62,63,65,66,68,69,71,72,74, \ |
f3d | 0:d2382fd0cc1a | 42 | 75,76,78,79,80,81,83,84,85,86,87,88,89,90,91,92,93,\ |
f3d | 0:d2382fd0cc1a | 43 | 93,94,95,95,96,97,97,98,98,98,99,99,99,99,99,99,100,\ |
f3d | 0:d2382fd0cc1a | 44 | 99,99,99,99,99,99,98,98,98,97,97,96,95,95,94,93,93,\ |
f3d | 0:d2382fd0cc1a | 45 | 92,91,90,89,88,87,86,85,84,83,81,80,79,78,76,75,74,\ |
f3d | 0:d2382fd0cc1a | 46 | 72,71,69,68,66,65,63,62,60,59,57,56,54,53,51,49,48,\ |
f3d | 0:d2382fd0cc1a | 47 | 46,45,43,42,40,39,37,36,34,33,31,30,28,27,25,24,23,\ |
f3d | 0:d2382fd0cc1a | 48 | 21,20,19,18,16,15,14,13,12,11,10,9,8,7,6,6,5,4,4,3,\ |
f3d | 0:d2382fd0cc1a | 49 | 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,\ |
f3d | 0:d2382fd0cc1a | 50 | 5,6,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,23,24,\ |
f3d | 0:d2382fd0cc1a | 51 | 25,27,28,30,31,33,34,36,37,39,40,42,43,45,46,48\ |
f3d | 0:d2382fd0cc1a | 52 | }; |
f3d | 0:d2382fd0cc1a | 53 | /* |
f3d | 0:d2382fd0cc1a | 54 | Pin mappings for Timer 1 (the advanced timer with deadtime) |
f3d | 0:d2382fd0cc1a | 55 | From: https://developer.mbed.org/users/mbed_official/code/mbed-src/file/a11c0372f0ba/targets/hal/TARGET_STM/TARGET_STM32F1/TARGET_NUCLEO_F103RB/PeripheralPins.c |
f3d | 0:d2382fd0cc1a | 56 | {PA_8, PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH1 - Default |
f3d | 0:d2382fd0cc1a | 57 | {PA_9, PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH2 - Default |
f3d | 0:d2382fd0cc1a | 58 | {PA_10, PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH3 - Default |
f3d | 0:d2382fd0cc1a | 59 | {PB_13, PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH1N - Default |
f3d | 0:d2382fd0cc1a | 60 | {PB_14, PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH2N - Default |
f3d | 0:d2382fd0cc1a | 61 | {PB_15, PWM_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, 0)}, // TIM1_CH3N - Default |
f3d | 0:d2382fd0cc1a | 62 | |
f3d | 0:d2382fd0cc1a | 63 | */ |
f3d | 0:d2382fd0cc1a | 64 | // Use mbed to configure the relevant pins as PWM outputs; |
f3d | 0:d2382fd0cc1a | 65 | PwmOut PhaATop(PA_8); |
f3d | 0:d2382fd0cc1a | 66 | PwmOut PhaABtm(PB_13); // This should be the complement of PA_8 |
f3d | 0:d2382fd0cc1a | 67 | AnalogIn Pot(A0); |
f3d | 0:d2382fd0cc1a | 68 | volatile float PotValue; |
f3d | 0:d2382fd0cc1a | 69 | void init(void); |
f3d | 0:d2382fd0cc1a | 70 | int main() { |
f3d | 0:d2382fd0cc1a | 71 | |
f3d | 0:d2382fd0cc1a | 72 | init(); |
f3d | 0:d2382fd0cc1a | 73 | while(1) { |
f3d | 0:d2382fd0cc1a | 74 | myled = 1; // LED is ON |
f3d | 0:d2382fd0cc1a | 75 | wait(0.1); // 200 ms |
f3d | 0:d2382fd0cc1a | 76 | myled = 0; // LED is OFF |
f3d | 0:d2382fd0cc1a | 77 | wait(0.1); // 1 sec |
f3d | 0:d2382fd0cc1a | 78 | PotValue = Pot; |
f3d | 0:d2382fd0cc1a | 79 | } |
f3d | 0:d2382fd0cc1a | 80 | } |
f3d | 0:d2382fd0cc1a | 81 | int index=0; |
f3d | 0:d2382fd0cc1a | 82 | void TimerISR() |
f3d | 0:d2382fd0cc1a | 83 | { |
f3d | 0:d2382fd0cc1a | 84 | TIM1->SR &= ~0x3f; // ack the interrupt |
f3d | 0:d2382fd0cc1a | 85 | TIM1->CCR1=duties[index++]; // get the next duty |
f3d | 0:d2382fd0cc1a | 86 | if (index > 199) |
f3d | 0:d2382fd0cc1a | 87 | index = 0; |
f3d | 0:d2382fd0cc1a | 88 | } |
f3d | 0:d2382fd0cc1a | 89 | void init() |
f3d | 0:d2382fd0cc1a | 90 | { |
f3d | 0:d2382fd0cc1a | 91 | |
f3d | 0:d2382fd0cc1a | 92 | RCC->APB2ENR |= BIT2+BIT3; // enable GPIOA and GPIOB |
f3d | 0:d2382fd0cc1a | 93 | RCC->APB2ENR |= BIT11; // enable TIM1 |
f3d | 0:d2382fd0cc1a | 94 | |
f3d | 0:d2382fd0cc1a | 95 | GPIOA->CRH |= BIT3+BIT0; // PA8 output, alternate function |
f3d | 0:d2382fd0cc1a | 96 | GPIOB->CRH |= BIT23+BIT20; // PB13 output, alternate function |
f3d | 0:d2382fd0cc1a | 97 | |
f3d | 0:d2382fd0cc1a | 98 | TIM1->CR2 = 0; |
f3d | 0:d2382fd0cc1a | 99 | TIM1->DIER = BIT0; // Want update interrupt |
f3d | 0:d2382fd0cc1a | 100 | NVIC_SetVector(TIM1_UP_IRQn,(uint32_t) TimerISR); |
f3d | 0:d2382fd0cc1a | 101 | NVIC_EnableIRQ(TIM1_UP_IRQn); |
f3d | 0:d2382fd0cc1a | 102 | TIM1->SR = 0; // Clear flags. |
f3d | 0:d2382fd0cc1a | 103 | TIM1->CCMR1= BIT6+BIT5+BIT4; |
f3d | 0:d2382fd0cc1a | 104 | TIM1->CCER = BIT2+BIT0; |
f3d | 0:d2382fd0cc1a | 105 | TIM1->ARR = 100; // 1MHz = base clock freq. Divide by 100 to get 10kHz. |
f3d | 0:d2382fd0cc1a | 106 | TIM1->CCR1 = 10; // Low inital duty |
f3d | 0:d2382fd0cc1a | 107 | TIM1->CR1 |= BIT0; //enable counter |
f3d | 0:d2382fd0cc1a | 108 | __enable_irq(); // enable interrupts |
f3d | 0:d2382fd0cc1a | 109 | |
f3d | 0:d2382fd0cc1a | 110 | } |