diff options
author | xengineering <me@xengineering.eu> | 2021-09-28 14:16:24 +0200 |
---|---|---|
committer | xengineering <me@xengineering.eu> | 2021-09-28 14:16:24 +0200 |
commit | 9704cdaa3d48fe1deceaba1189706326bd41f306 (patch) | |
tree | a67653a9fc3eb624f0204626e66ed68dd442eace | |
parent | 6c90271b1d20235d917509454dc1b4e4a66f13f6 (diff) | |
download | ledcontrol-9704cdaa3d48fe1deceaba1189706326bd41f306.tar ledcontrol-9704cdaa3d48fe1deceaba1189706326bd41f306.tar.zst ledcontrol-9704cdaa3d48fe1deceaba1189706326bd41f306.zip |
First PWM Demonstration
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | README.md | 7 | ||||
-rw-r--r-- | src/main.c | 91 |
3 files changed, 84 insertions, 15 deletions
@@ -1,2 +1,3 @@ docs build +libopencm3-examples @@ -37,8 +37,11 @@ run # leave GDB with CTRL + D ``` +Mention that you do not have to quit GDB to upload new compiled firmware. Just +call `load` and `run` again. + ## External References -- Nice [Tutorial](https://jacobmossberg.se/posts/2018/08/11/run-c-program-bare-metal-on-arm-cortex-m3.html) about C programs on bare-metal ARM chips -- Another useful [Tutorial](https://www.rhye.org/post/stm32-with-opencm3-0-compiling-and-uploading/) about STM32 programming with libopencm3 +- Nice [tutorial](https://jacobmossberg.se/posts/2018/08/11/run-c-program-bare-metal-on-arm-cortex-m3.html) about C programs on bare-metal ARM chips +- Another useful [tutorial](https://www.rhye.org/post/stm32-with-opencm3-0-compiling-and-uploading/) about STM32 programming with libopencm3 @@ -19,6 +19,7 @@ void main(void) { clock_init(); gpio_init(); + gpio_clear(GPIOC, GPIO13); // set onboard LED on nvic_init(); timer_init(); @@ -28,23 +29,47 @@ void main(void) static void clock_init(void) { + // set sysclk to 72 MHz via external 8 MHz crystal rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); - rcc_periph_clock_enable(RCC_GPIOC); // for PC13 blinking - rcc_periph_clock_enable(RCC_TIM2); // for timer / counter 2 + + // enable clocks for GPIO ports B and C + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOC); + + // enable clock for timer 2 (blinking) + rcc_periph_clock_enable(RCC_TIM2); + + // enable clock for timer 3 (PWM) + rcc_periph_clock_enable(RCC_TIM3); + + // enable clock for alternate functions + rcc_periph_clock_enable(RCC_AFIO); // TODO is this necessary? } static void gpio_init(void) { - gpio_set_mode(GPIOC, - GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, - GPIO13); + // init PC13 onboard LED for blinking + gpio_set_mode( + GPIOC, + GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, + GPIO13 + ); + + // setup PB0 (connected to TIM3_CH3) for PWM + gpio_set_mode( + GPIOB, + GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, + GPIO_TIM3_CH3 + ); } static void nvic_init(void) { + // enable timer 2 interrupt and set priority nvic_enable_irq(NVIC_TIM2_IRQ); nvic_set_priority(NVIC_TIM2_IRQ, 1); } @@ -52,20 +77,60 @@ static void nvic_init(void) static void timer_init(void) { - // set LED on - gpio_clear(GPIOC, GPIO13); - - // setup timer + // setup timer 2 for blinking timer_set_counter(TIM2, 1); timer_set_prescaler(TIM2, 1440); - timer_set_period(TIM2, 50000); - timer_enable_irq(TIM2, TIM_DIER_UIE); // set action to trigger interrupt + timer_set_period(TIM2, 25000); + + // enable timer / counter 2 and the corresponding interrupt for blinking + timer_enable_irq(TIM2, TIM_DIER_UIE); timer_enable_counter(TIM2); + + /* + enable timer / counter 3 + */ + + /* Clock division and mode */ + TIM3_CR1 = TIM_CR1_CKD_CK_INT | TIM_CR1_CMS_EDGE; + /* Period */ + TIM3_ARR = 65535; + /* Prescaler */ + TIM3_PSC = 0; + TIM3_EGR = TIM_EGR_UG; + + /* ---- */ + /* Output compare 3 mode and preload */ + TIM3_CCMR2 |= TIM_CCMR2_OC3M_PWM1 | TIM_CCMR2_OC3PE; + + /* Polarity and state */ + TIM3_CCER |= TIM_CCER_CC3P | TIM_CCER_CC3E; + //TIM3_CCER |= TIM_CCER_CC3E; + + /* Capture compare value */ + TIM3_CCR3 = 30000; + + /* ---- */ + /* ARR reload enable */ + TIM3_CR1 |= TIM_CR1_ARPE; + + /* Counter enable */ + TIM3_CR1 |= TIM_CR1_CEN; } void tim2_isr(void) { + // PWM handling + static uint32_t pwm_value; + pwm_value += 20000; + if (pwm_value > 60000) { + pwm_value = 0; + } + TIM3_CCR3 = pwm_value; + + // toggle blink LED gpio_toggle(GPIOC, GPIO13); - TIM_SR(TIM2) &= ~TIM_SR_UIF; // clear interrrupt flag + + // clear interrrupt flag + TIM_SR(TIM2) &= ~TIM_SR_UIF; } |