|
| 1 | +//! Example of using a number of timer channels in PWM mode. |
| 2 | +//! Target board: STM32F3DISCOVERY |
| 3 | +#![no_std] |
| 4 | +#![no_main] |
| 5 | + |
| 6 | +extern crate panic_semihosting; |
| 7 | + |
| 8 | +use cortex_m_rt::entry; |
| 9 | +//use cortex_m_semihosting::hprintln; |
| 10 | +use embedded_hal::PwmPin; |
| 11 | +use stm32f3::stm32f303; |
| 12 | +use stm32f3xx_hal::flash::FlashExt; |
| 13 | +use stm32f3xx_hal::gpio::GpioExt; |
| 14 | +use stm32f3xx_hal::pwm::{tim16, tim2, tim3, tim8}; |
| 15 | +use stm32f3xx_hal::rcc::RccExt; |
| 16 | +use stm32f3xx_hal::time::U32Ext; |
| 17 | + |
| 18 | +#[entry] |
| 19 | +fn main() -> ! { |
| 20 | + // Get our peripherals |
| 21 | + let dp = stm32f303::Peripherals::take().unwrap(); |
| 22 | + |
| 23 | + // Configure our clocks |
| 24 | + let mut flash = dp.FLASH.constrain(); |
| 25 | + let mut rcc = dp.RCC.constrain(); |
| 26 | + let clocks = rcc.cfgr.freeze(&mut flash.acr); |
| 27 | + |
| 28 | + // Prep the pins we need in their correct alternate function |
| 29 | + let mut gpioa = dp.GPIOA.split(&mut rcc.ahb); |
| 30 | + let pa4 = gpioa.pa4.into_af2(&mut gpioa.moder, &mut gpioa.afrl); |
| 31 | + let pa6 = gpioa.pa6.into_af2(&mut gpioa.moder, &mut gpioa.afrl); |
| 32 | + let pa7 = gpioa.pa7.into_af2(&mut gpioa.moder, &mut gpioa.afrl); |
| 33 | + |
| 34 | + let mut gpiob = dp.GPIOB.split(&mut rcc.ahb); |
| 35 | + let pb0 = gpiob.pb0.into_af2(&mut gpiob.moder, &mut gpiob.afrl); |
| 36 | + let pb1 = gpiob.pb1.into_af2(&mut gpiob.moder, &mut gpiob.afrl); |
| 37 | + let pb3 = gpiob.pb3.into_af4(&mut gpiob.moder, &mut gpiob.afrl); |
| 38 | + let pb4 = gpiob.pb4.into_af2(&mut gpiob.moder, &mut gpiob.afrl); |
| 39 | + let pb5 = gpiob.pb5.into_af2(&mut gpiob.moder, &mut gpiob.afrl); |
| 40 | + let pb7 = gpiob.pb7.into_af10(&mut gpiob.moder, &mut gpiob.afrl); |
| 41 | + let pb8 = gpiob.pb8.into_af1(&mut gpiob.moder, &mut gpiob.afrh); |
| 42 | + let pb10 = gpiob.pb10.into_af1(&mut gpiob.moder, &mut gpiob.afrh); |
| 43 | + |
| 44 | + let mut gpioc = dp.GPIOC.split(&mut rcc.ahb); |
| 45 | + let pc10 = gpioc.pc10.into_af4(&mut gpioc.moder, &mut gpioc.afrh); |
| 46 | + |
| 47 | + // TIM3 |
| 48 | + // |
| 49 | + // A four channel general purpose timer that's broadly available |
| 50 | + let tim3_channels = tim3( |
| 51 | + dp.TIM3, |
| 52 | + 1280, // resolution of duty cycle |
| 53 | + 50.hz(), // frequency of period |
| 54 | + &clocks, // To get the timer's clock speed |
| 55 | + ); |
| 56 | + |
| 57 | + // Channels without pins cannot be enabled, so we can't forget to |
| 58 | + // connect a pin. |
| 59 | + // |
| 60 | + // DOES NOT COMPILE |
| 61 | + // tim3_channels.0.enable(); |
| 62 | + |
| 63 | + // Each channel can be used with a different duty cycle and have many pins |
| 64 | + let mut tim3_ch1 = tim3_channels.0.output_to_pa6(pa6).output_to_pb4(pb4); |
| 65 | + tim3_ch1.set_duty(tim3_ch1.get_max_duty() / 20); // 5% duty cyle |
| 66 | + tim3_ch1.enable(); |
| 67 | + |
| 68 | + let mut tim3_ch2 = tim3_channels |
| 69 | + .1 |
| 70 | + .output_to_pa4(pa4) |
| 71 | + .output_to_pa7(pa7) |
| 72 | + .output_to_pb5(pb5); |
| 73 | + tim3_ch2.set_duty(tim3_ch2.get_max_duty() / 40 * 3); // 7.5% duty cyle |
| 74 | + tim3_ch2.enable(); |
| 75 | + |
| 76 | + let mut tim3_ch3 = tim3_channels.2.output_to_pb0(pb0); |
| 77 | + tim3_ch3.set_duty(tim3_ch3.get_max_duty() / 50 * 3); // 6% duty cyle |
| 78 | + tim3_ch3.enable(); |
| 79 | + |
| 80 | + let mut tim3_ch4 = tim3_channels.3.output_to_pb1(pb1).output_to_pb7(pb7); |
| 81 | + tim3_ch4.set_duty(tim3_ch4.get_max_duty() / 10); // 10% duty cyle |
| 82 | + tim3_ch4.enable(); |
| 83 | + |
| 84 | + // We can only add valid pins, so we can't do this: |
| 85 | + // |
| 86 | + // DOES NOT COMPILE |
| 87 | + // tim3_ch1.output_to_pb8(pb8); |
| 88 | + |
| 89 | + // The pins that we've used are given away so they can't be |
| 90 | + // accidentaly modified. This line would "disconnect" our pin |
| 91 | + // from the channel. |
| 92 | + // |
| 93 | + // DOES NOT COMPILE |
| 94 | + // pb0.into_af15(&mut gpiob.moder, &mut gpiob.afrl); |
| 95 | + |
| 96 | + // TIM2 |
| 97 | + // |
| 98 | + // A 32-bit timer, so we can set a larger resolution |
| 99 | + let tim2_channels = tim2( |
| 100 | + dp.TIM2, |
| 101 | + 160000, // resolution of duty cycle |
| 102 | + 50.hz(), // frequency of period |
| 103 | + &clocks, // To get the timer's clock speed |
| 104 | + ); |
| 105 | + |
| 106 | + let mut tim2_ch3 = tim2_channels.2.output_to_pb10(pb10); |
| 107 | + tim2_ch3.set_duty(tim2_ch3.get_max_duty() / 20); // 5% duty cyle |
| 108 | + tim2_ch3.enable(); |
| 109 | + |
| 110 | + // TIM16 |
| 111 | + // |
| 112 | + // A single channel timer, so it doesn't return a tuple. We can |
| 113 | + // just use it directly |
| 114 | + let mut tim16_ch1 = tim16( |
| 115 | + dp.TIM16, |
| 116 | + 1280, // resolution of duty cycle |
| 117 | + 50.hz(), // frequency of period |
| 118 | + &clocks, // To get the timer's clock speed |
| 119 | + ) |
| 120 | + .output_to_pb8(pb8); |
| 121 | + tim16_ch1.set_duty(tim16_ch1.get_max_duty() / 20); // 5% duty cyle |
| 122 | + tim16_ch1.enable(); |
| 123 | + |
| 124 | + // TIM8 |
| 125 | + // |
| 126 | + // An advanced timer with complementary outputs, so we can output |
| 127 | + // to complementary pins (works just like standard pins) |
| 128 | + let tim8_channels = tim8( |
| 129 | + dp.TIM8, |
| 130 | + 1280, // resolution of duty cycle |
| 131 | + 50.hz(), // frequency of period |
| 132 | + &clocks, // To get the timer's clock speed |
| 133 | + ); |
| 134 | + |
| 135 | + let mut tim8_ch1 = tim8_channels.0.output_to_pb3(pb3).output_to_pc10(pc10); |
| 136 | + tim8_ch1.set_duty(tim8_ch1.get_max_duty() / 10); // 10% duty cyle |
| 137 | + tim8_ch1.enable(); |
| 138 | + |
| 139 | + // Once we select PB3, we can only use complementary pins (such as |
| 140 | + // PC10). These are pins with alternate functions with an 'N' at |
| 141 | + // the end of the channel (such as TIM8_CH1N) in the reference |
| 142 | + // manual. If we had selected a non-complementary pin first, we |
| 143 | + // would not be able to use PB3 or PC10 (or PA7 which is aready in |
| 144 | + // use). |
| 145 | + // |
| 146 | + // DOES NOT COMPILE |
| 147 | + // tim8_ch1.output_to_pc6(gpioc.pc6.into_af4(&mut gpioc.moder, &mut gpioc.afrl)); |
| 148 | + |
| 149 | + loop {} |
| 150 | +} |
0 commit comments