summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxengineering <me@xengineering.eu>2021-09-28 14:16:24 +0200
committerxengineering <me@xengineering.eu>2021-09-28 14:16:24 +0200
commit9704cdaa3d48fe1deceaba1189706326bd41f306 (patch)
treea67653a9fc3eb624f0204626e66ed68dd442eace
parent6c90271b1d20235d917509454dc1b4e4a66f13f6 (diff)
downloadledcontrol-9704cdaa3d48fe1deceaba1189706326bd41f306.tar
ledcontrol-9704cdaa3d48fe1deceaba1189706326bd41f306.tar.zst
ledcontrol-9704cdaa3d48fe1deceaba1189706326bd41f306.zip
First PWM Demonstration
-rw-r--r--.gitignore1
-rw-r--r--README.md7
-rw-r--r--src/main.c91
3 files changed, 84 insertions, 15 deletions
diff --git a/.gitignore b/.gitignore
index 15a4222..41b083e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
docs
build
+libopencm3-examples
diff --git a/README.md b/README.md
index 070c535..36228fa 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/src/main.c b/src/main.c
index f8b803b..18a6e4a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}