I am trying to set up the MCPWM on a esp32-3s wroom-1 module.
I want to write to the registers directly to set the PWM up, but none of the values are changing after I write to them for example:
WRITE_PERI_REG(MCPWM_CLK_REG(0) , MCPWM_CLK_EN);
WRITE_PERI_REG(MCPWM_TIMER0_CFG0_REG(0), ((0x0<<MCPWM_TIMER0_PERIOD_UPMETHOD_S) | (914<<MCPWM_TIMER0_PERIOD_S))); // See page 1344 this sets the when to update and the period
WRITE_PERI_REG(MCPWM_GEN0_TSTMP_A_REG(0), (457)); // Set the timer compare value
None of these writes make any change to the default values if I read the values back after a pause!
(I have checked writing to things like the GPIO register etc and there seems no issue!)
HELP!
MCPWM register programming...
Re: MCPWM register programming...
Did you enable and un-clockgate the MCPWM peripheral? (periph_ll_enable_clk_clear_rst)
Re: MCPWM register programming...
Hi ESP_Sprite Many thanks! I checked and saw I made the foolish mistake of SETTING the clock reset, and not clearing it!Did you enable and un-clockgate the MCPWM peripheral? (periph_ll_enable_clk_clear_rst)
In case someone one day wants to do similar here is the code:
#include <stdio.h>
#include "esp_log.h"
#include "soc/mcpwm_reg.h" // For MCPWM register definitions
#include "soc/gpio_struct.h" // GPIO register definitions
#include "esp32/rom/gpio.h" // For gpio_matrix_out function
#include "driver/gpio.h" // needed for GPIO pins _num_41
#include "soc/gpio_sig_map.h" // needed for PWM0_OUT1A_IDX
#include "soc/system_reg.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/periph_ctrl.h" // For periph_module_enable() function
void app_main() {
SET_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_RMT_CLK_EN); // Enable RMT clock (check which register is needed 0 or 1)
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_RMT_RST); // Unclear Periferal
WRITE_PERI_REG(RMT_CH0CONF0_REG, (40 << RMT_DIV_CNT_CH0_S) | (0x8 << RMT_MEM_SIZE_CH0_S)| (0x1 << RMT_APB_MEM_RST_CH0_S)| (0x1 << RMT_CONF_UPDATE_CH0_S)); // Initialise the TX register 0 !! Ymust have the update bit or you get a carrier wave and wrong timing. Note Memsize=>No. of 48x32 blocks-max8 =8x48 pulses
WRITE_PERI_REG(RMT_SYS_CONF_REG, RMT_SCLK_ACTIVE | RMT_CLK_EN | (0x1 <<RMT_SCLK_SEL_S) | (1 << RMT_SCLK_DIV_NUM_S));
gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT);
gpio_matrix_out(GPIO_NUM_4, RMT_SIG_OUT0_IDX, 0, 0); // Map the pin to the function , signal inversion, open drain
WRITE_PERI_REG(RMT_CH0DATA_REG, (((0b0 << 31) | (PulsePeriod << 16) | (0b1<< 15) | PulsePeriod )));
WRITE_PERI_REG(RMT_CH0DATA_REG, (0x0));
SET_PERI_REG_MASK(RMT_CH0CONF0_REG, RMT_TX_START_CH0); // Send the data
Re: MCPWM register programming...
Just out of curiousity, is there a specific reason you're writing to hardware registers explicitly, not using the IDF driver code?
Re: MCPWM register programming...
I'm just old fashioned I guess! Most of my experience is from programing Atmel microcontrollers, and I find all the ESP32 APIs so very abstracted and exceptionally challenging to know what they are doing and how to use them!
Re: MCPWM register programming...
I am absolutely where you are, I have lots of ESP8266s where I also bypass the SDK code as much as possible (because basically it's just bad). Also very experienced with ATmel microcontrollers.
But I must say, the IDF isn't that bad. It's well-maintained and the source is mostly open. So for the moment, and as long as it can do what I need, I'll stick to IDF driver calls. It will also make sure multi-threading and multi-core will work. But I can imagine the call to simply poke some registers
.
Having said that, using the IDF I think you'll get more help here
But I must say, the IDF isn't that bad. It's well-maintained and the source is mostly open. So for the moment, and as long as it can do what I need, I'll stick to IDF driver calls. It will also make sure multi-threading and multi-core will work. But I can imagine the call to simply poke some registers
Having said that, using the IDF I think you'll get more help here
Re: MCPWM register programming...
I guess I work in a bit of a strange way, and I like to know exactly what is going on in code, so I am not a big fan of "black box" systems and libraries. I realise now just how good Atmel data sheets were!
The EPS32 data sheet are OK, but for example with the ADC... the register information is worthless. I had to reverse engineer some of the earlier version APIs to see why I was getting a full scale readout at only a fraction of the fullscale voltage. It seems the API plucks some fitted curve out of a memory address to generate a calibration table. But its not a standard y=x.... type calibration, and you really cant use the ADC without it! The version 4. I think it was calls are simple enough, but the later versions are mind boggling for something which should inherently be simple!
I have managed to cobble some of the Wifi API stuff together, but only really by copying sample code, and I dont really know how it is functioning. If I try to follow some of the functions it's one call that calls another that accesses a parameter in another function that waits for the return of another variable from another function.. etc..etc. I have no idea how you are supposed to get an idea of what is actually happening, what "things" are critical, etc...
How do you manage with such things yourself?
The EPS32 data sheet are OK, but for example with the ADC... the register information is worthless. I had to reverse engineer some of the earlier version APIs to see why I was getting a full scale readout at only a fraction of the fullscale voltage. It seems the API plucks some fitted curve out of a memory address to generate a calibration table. But its not a standard y=x.... type calibration, and you really cant use the ADC without it! The version 4. I think it was calls are simple enough, but the later versions are mind boggling for something which should inherently be simple!
I have managed to cobble some of the Wifi API stuff together, but only really by copying sample code, and I dont really know how it is functioning. If I try to follow some of the functions it's one call that calls another that accesses a parameter in another function that waits for the return of another variable from another function.. etc..etc. I have no idea how you are supposed to get an idea of what is actually happening, what "things" are critical, etc...
How do you manage with such things yourself?
Re: MCPWM register programming...
Definitively agree there!I realise now just how good Atmel data sheets were!
Also agree on the documentation that's lacking, really. These dreaded "examples". I just complained about the other day, once again. But I feel their stance towards documentation has really improved with the ESP-IDF and some complaints are actually acted upon...
Re: MCPWM register programming...
Totally agree, IDF might not be perfect, but it’s definitely a step up from the old SDK days. Having the source open really helps when you want to dig deeper without going full bare-metal.Tubidy Mp3I am absolutely where you are, I have lots of ESP8266s where I also bypass the SDK code as much as possible (because basically it's just bad). Also very experienced with ATmel microcontrollers.
But I must say, the IDF isn't that bad. It's well-maintained and the source is mostly open. So for the moment, and as long as it can do what I need, I'll stick to IDF driver calls. It will also make sure multi-threading and multi-core will work. But I can imagine the call to simply poke some registers.
Having said that, using the IDF I think you'll get more help here![]()
Who is online
Users browsing this forum: DuckDuckGo [Bot], PerplexityBot, trendictionbot and 2 guests
