Hi @sacd
My apologies for the delay in getting back, I was just trying to sort out why the code that I provided didn't even compile, as when I last ran it, admittedly a few years ago, it worked just fine.
It turns out the Espressif have completely rewritten their IDF library, presumably to accommodate their new ESP32 derivative devices. This unfortunately includes all the structures used to access the registers, rendering my previous example unusable.
Anyway, I started replacing the previous old structures with new ones thinking this would work, however it also turned out the Espressif have now turned the MCPWM module off by default, whereas previously it was turned on.
I wish that Espressif wouldn't make such substantial changes to their core code, but the fact is that they do.
I finally worked around the issues, here's the revised code, this time outputting 5, 1kHz pulses at 50% duty-cycle every second on GPIO27:
// Output a burst of 5 pulses at 1kHz, 50% duty-cycle on GPIO pin 27
#include "soc/mcpwm_struct.h"
#include "driver/mcpwm.h"
#define GPIO_PWM0A_OUT 27
#define PERIP_CLK_EN_REG (*(volatile uint32_t*)0x3FF000C0) // Peripheral Clock Enable Register definition
#define PERIP_RST_EN_REG (*(volatile uint32_t*)0x3FF000C4) // Peripheral Reset Enable Register definition
static void IRAM_ATTR isr_handler(void* arg)
{
static volatile uint32_t counter = 0;
if (MCPWM0.int_st.op0_tea_int_st) // Check for interrupt on timer compare matach
{
if (counter == 0) // Start of pulse burst...
{
counter++;
MCPWM0.operators[0].timestamp[0].gen = 500; // Set the counter compare for 50% duty-cycle
}
else if (counter <= 5) // Have we counted up to 5?
{
counter++; // Increment the counter and continue
}
else
{
counter = 0; // Reset the counter
MCPWM0.operators[0].timestamp[0].gen = 0; // Set the counter compare for 0% duty-cycle
MCPWM0.int_ena.op0_tea_int_ena = 0; // Disable interrupt on TEA event
}
MCPWM0.int_clr.op0_tea_int_clr = 1; // Clear the interrupt flag
}
}
void setup()
{
PERIP_RST_EN_REG |= 1 << 17; // Reset the MCPWM0 peripheral
PERIP_RST_EN_REG &= ~(1 << 17);
PERIP_CLK_EN_REG |= 1 << 17; // Enable the MCPWM0 clock source
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_PWM0A_OUT); // Initialise channel MCPWM0A on GPIO pin 27
MCPWM0.clk_cfg.clk_prescale = 9; // Set the 160MHz clock prescaler to 9 (160MHz/(9+1)=16MHz)
MCPWM0.timer[0].timer_cfg0.timer_prescale = 15; // Set timer 0 prescaler to 8 (16MHz/(15+1))=1MHz)
MCPWM0.timer[0].timer_cfg0.timer_period = 999; // Set the PWM period to 1kHz (1MHz/(999+1)=1kHz)
MCPWM0.operators[0].timestamp[0].gen = 0; // Set the counter compare for 0% duty-cycle
MCPWM0.operators[0].generator[0].gen_utez = 2; // Set the PWM0A ouput to go high at the start of the timer period
MCPWM0.operators[0].generator[0].gen_utea = 1; // Clear on compare match
mcpwm_isr_register(MCPWM_UNIT_0, isr_handler, NULL, ESP_INTR_FLAG_IRAM, NULL); //Set ISR Handler
MCPWM0.timer[0].timer_cfg1.timer_mod = 1; // Set timer 0 to increment
MCPWM0.timer[0].timer_cfg1.timer_start = 2; // Set timer 0 to free-run
}
void loop()
{
MCPWM0.int_clr.op0_tea_int_clr = 1; // Clear the interrupt flag
MCPWM0.int_ena.op0_tea_int_ena = 1; // Enable interrupt on TEA event
delay(1000); // Wait for 1 second
}