Available on crate feature
unstable only.Expand description
§Pulse Counter (PCNT)
§Overview
The PCNT module counts rising and/or falling edges of input signals. Each unit is an independent counter with two channels. Channel edge and control inputs can be configured separately.
Units are peripheral singletons (PCNT0_UNIT0, PCNT0_UNIT1, …, and
PCNT1_UNIT0, … when the chip has a second register block). Construct a
Unit from a singleton; there is no hub driver.
The hardware raises one interrupt per PCNT register block. Unit emulates
per-unit interrupts by installing a shared dispatcher that calls the handler
registered on each unit whose status bit is set.
§Examples
§Decoding a quadrature encoder
static UNIT0: Mutex<RefCell<Option<Unit<'static>>>> = Mutex::new(RefCell::new(None));
static VALUE: AtomicI32 = AtomicI32::new(0);
let mut u0 = Unit::new(peripherals.PCNT0_UNIT1);
u0.set_interrupt_handler(interrupt_handler);
u0.set_low_limit(Some(-100))?;
u0.set_high_limit(Some(100))?;
u0.set_filter(Some(min(10u16 * 80, 1023u16)))?;
u0.clear();
let ch0 = &u0.channel0;
let config = InputConfig::default().with_pull(Pull::Up);
let pin_a = Input::new(peripherals.GPIO4, config);
let pin_b = Input::new(peripherals.GPIO5, config);
let input_a = pin_a.peripheral_input();
let input_b = pin_b.peripheral_input();
ch0.set_ctrl_signal(input_a.clone());
ch0.set_edge_signal(input_b.clone());
ch0.set_ctrl_mode(channel::CtrlMode::Reverse, channel::CtrlMode::Keep);
ch0.set_input_mode(channel::EdgeMode::Increment, channel::EdgeMode::Decrement);
let ch1 = &u0.channel1;
ch1.set_ctrl_signal(input_b);
ch1.set_edge_signal(input_a);
ch1.set_ctrl_mode(channel::CtrlMode::Reverse, channel::CtrlMode::Keep);
ch1.set_input_mode(channel::EdgeMode::Decrement, channel::EdgeMode::Increment);
u0.listen();
u0.resume();
let counter = u0.counter.clone();
critical_section::with(|cs| UNIT0.borrow_ref_mut(cs).replace(u0));
let mut last_value: i32 = 0;
loop {
let value: i32 = counter.get() as i32 + VALUE.load(Ordering::SeqCst);
if value != last_value {
last_value = value;
}
}
#[esp_hal::handler]
fn interrupt_handler() {
critical_section::with(|cs| {
let mut u0 = UNIT0.borrow_ref_mut(cs);
if let Some(u0) = u0.as_mut() {
if u0.interrupt_is_set() {
let events = u0.events();
if events.high_limit {
VALUE.fetch_add(100, Ordering::SeqCst);
} else if events.low_limit {
VALUE.fetch_add(-100, Ordering::SeqCst);
}
u0.reset_interrupt();
}
}
});
}Re-exports§
pub use unit::Unit;
Modules§
Structs§
- AnyPcnt
Unit - Any PCNT unit.