73 lines
2.5 KiB
C
73 lines
2.5 KiB
C
/**
|
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "pico/stdlib.h"
|
|
#include "hardware/pwm.h"
|
|
#include "hardware/clocks.h"
|
|
|
|
// This example drives a PWM output at a range of duty cycles, and uses
|
|
// another PWM slice in input mode to measure the duty cycle. You'll need to
|
|
// connect these two pins with a jumper wire:
|
|
const uint OUTPUT_PIN = 2;
|
|
const uint MEASURE_PIN = 5;
|
|
|
|
float measure_duty_cycle(uint gpio) {
|
|
// Only the PWM B pins can be used as inputs.
|
|
assert(pwm_gpio_to_channel(gpio) == PWM_CHAN_B);
|
|
uint slice_num = pwm_gpio_to_slice_num(gpio);
|
|
|
|
// Count once for every 100 cycles the PWM B input is high
|
|
pwm_config cfg = pwm_get_default_config();
|
|
pwm_config_set_clkdiv_mode(&cfg, PWM_DIV_B_HIGH);
|
|
pwm_config_set_clkdiv(&cfg, 100);
|
|
pwm_init(slice_num, &cfg, false);
|
|
gpio_set_function(gpio, GPIO_FUNC_PWM);
|
|
|
|
pwm_set_enabled(slice_num, true);
|
|
sleep_ms(10);
|
|
pwm_set_enabled(slice_num, false);
|
|
float counting_rate = clock_get_hz(clk_sys) / 100;
|
|
float max_possible_count = counting_rate * 0.01;
|
|
return pwm_get_counter(slice_num) / max_possible_count;
|
|
}
|
|
|
|
const float test_duty_cycles[] = {
|
|
0.f,
|
|
0.1f,
|
|
0.5f,
|
|
0.9f,
|
|
1.f
|
|
};
|
|
|
|
int main() {
|
|
stdio_init_all();
|
|
printf("\nPWM duty cycle measurement example\n");
|
|
|
|
// Configure PWM slice and set it running
|
|
const uint count_top = 1000;
|
|
pwm_config cfg = pwm_get_default_config();
|
|
pwm_config_set_wrap(&cfg, count_top);
|
|
pwm_init(pwm_gpio_to_slice_num(OUTPUT_PIN), &cfg, true);
|
|
|
|
// Note we aren't touching the other pin yet -- PWM pins are outputs by
|
|
// default, but change to inputs once the divider mode is changed from
|
|
// free-running. It's not wise to connect two outputs directly together!
|
|
gpio_set_function(OUTPUT_PIN, GPIO_FUNC_PWM);
|
|
|
|
// For each of our test duty cycles, drive the output pin at that level,
|
|
// and read back the actual output duty cycle using the other pin. The two
|
|
// values should be very close!
|
|
for (int i = 0; i < count_of(test_duty_cycles); ++i) {
|
|
float output_duty_cycle = test_duty_cycles[i];
|
|
pwm_set_gpio_level(OUTPUT_PIN, output_duty_cycle * (count_top + 1));
|
|
float measured_duty_cycle = measure_duty_cycle(MEASURE_PIN);
|
|
printf("Output duty cycle = %.1f%%, measured input duty cycle = %.1f%%\n",
|
|
output_duty_cycle * 100.f, measured_duty_cycle * 100.f);
|
|
}
|
|
}
|