高級定時器
PY32F030 的內部有一個高級定時器TIM1,是一個16位可編程的定時器,可用于多種場合,如基礎定時功能,輸入脈沖測量,輸出PWM。TIM1的主要特性如下:
- 16bit 可配置的向下、向上、上下重載模式
- 16位的分頻器,支持1~65535的分頻
- 4 個獨立的通道,可用于
- 輸入脈沖捕獲
- 輸出比較
- PWM
- 單脈沖輸出
- 支持互補輸出的死區配置
- 外部信號控制定時器或定時器級聯控制
- DMA 操作
- 中斷事件
- 更新事件
- 觸發事件
- 輸入捕獲事件
- 輸出比較
- 剎車輸入
- 支持正交編碼與霍爾傳感器電路
在驅動包py32f030-hal
中,目前已實現常用的定時、PWM輸出、中斷等功能,擴展其他功能也非常簡單。以下將提供裸機環境操作定時器和多任務系統中配置定時器輸出PWM的例程。示例1: 定時:
examples/advanced_timer_block.rs
#![no_std] #![no_main] use embedded_hal::digital::v2::ToggleableOutputPin; use hal::gpio::{Output, PinIoType, PinSpeed}; use hal::mode::Blocking; use hal::timer::advanced_timer::AnyTimer; use py32f030_hal as hal; use {defmt_rtt as _, panic_probe as _}; #[cortex_m_rt::entry] fn main() -> ! { defmt::info!("timer counter examples start..."); let p = hal::init(Default::default()); let gpioa = p.GPIOA.split(); let timer = AnyTimer::<_, Blocking>::new(p.TIM1).unwrap(); letmut counter = timer.as_counter(); letmut led = Output::new(gpioa.PA0, PinIoType::PullUp, PinSpeed::Low); letmut cnt = 0; loop { let _ = led.toggle(); // 延時 1s counter.delay_us_blocking(1_000_000); defmt::info!("{}", cnt); cnt += 1; } }
#![no_std] #![no_main] use embedded_hal::digital::v2::ToggleableOutputPin; use hal::gpio::{Output, PinIoType, PinSpeed}; use hal::mode::Blocking; use hal::timer::advanced_timer::AnyTimer; use py32f030_hal as hal; use {defmt_rtt as _, panic_probe as _}; #[cortex_m_rt::entry] fn main() -> ! { defmt::info!("timer counter examples start..."); let p = hal::init(Default::default()); let gpioa = p.GPIOA.split(); let timer = AnyTimer::<_, Blocking>::new(p.TIM1).unwrap(); letmut counter = timer.as_counter(); letmut led = Output::new(gpioa.PA0, PinIoType::PullUp, PinSpeed::Low); letmut cnt = 0; loop { let _ = led.toggle(); // 延時 1s counter.delay_us_blocking(1_000_000); defmt::info!("{}", cnt); cnt += 1; } }
運行:
cargo r --example advanced_timer_block
示例2: examples/advanced_timer_block_2.rs
#![no_std] #![no_main] use embedded_hal::timer::CountDown; use fugit::ExtU32; use hal::mode::Blocking; use hal::timer::advanced_timer::AnyTimer; use py32f030_hal as hal; use {defmt_rtt as _, panic_probe as _}; #[cortex_m_rt::entry] fn main() -> ! { defmt::info!("timer counter examples start..."); let p = hal::init(Default::default()); let timer = AnyTimer::<_, Blocking>::new(p.TIM1).unwrap(); letmut counter = timer.as_counter(); letmut cnt = 0; loop { // 延時 5s defmt::info!("repeat...{} ", cnt); counter.start(5u32.secs()); let _ = counter.wait(); cnt += 1; } }
運行:
cargo r --example advanced_timer_block_2
示例3:PWM輸出:
examples/embassy_pwm.rs
配置輸出 PWM 波形
運行:#![no_std] #![no_main] use hal::timer::advanced_timer::{AnyTimer, ChannelConfig, ChannelOutputConfig}; use py32f030_hal::gpio::gpioa::PA0; use py32f030_hal::{selfas hal, mode::Blocking, timer::advanced_timer::Channel}; use embassy_executor::Spawner; use embassy_time::Timer; use embedded_hal::Pwm; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::task] asyncfn run() { loop { Timer::after_secs(2).await; defmt::info!("task run"); } } #[embassy_executor::main] asyncfn main(_spawner: Spawner) { defmt::info!("time1 start..."); let p = hal::init(Default::default()); let gpioa = p.GPIOA.split(); _spawner.spawn(run()).unwrap(); let timer: AnyTimer<_, Blocking> = AnyTimer::new(p.TIM1).unwrap(); letmut pwm = timer.as_pwm(); let channel_1_pin = gpioa.PA3; pwm.set_channel_1_pin::<_, PA0>(Some(channel_1_pin), None); // 配置定時器 pwm.config( /* 配置通道1 */ Some(ChannelConfig::default().ch(ChannelOutputConfig::default())), None, None, None, ); // 計數頻率為1M pwm.set_frequency(1_000_000); // 設置計數周期為1000,則波形的頻率為 1000_000/1000 = 1K pwm.set_period(1000u16 - 1); let max_duty = pwm.get_max_duty(); // 33%的占空比 pwm.set_duty(Channel::CH1, max_duty / 3); // 使能通道 pwm.enable(Channel::CH1); // 開始計數器 pwm.start(); loop { Timer::after_secs(1).await; } }
cargo r --example embassy_pwm?