Search code examples
arduinostm32

Arduino giga PWM on TIMx with registers


I am trying to use the hardware timer to create a PWM signal. First I created a program using in STM cube IDE using black pill (STM32F411 chip), which works fine. Now I am trying to adapt the code for the arduino giga, which I am programming through arduino ide. The timer initializes but the pin PA7 (D5) is not switching between HIGH and LOW. To create the program I used these documents: https://www.st.com/resource/en/reference_manual/rm0399-stm32h745755-and-stm32h747757-advanced-armbased-32bit-mcus-stmicroelectronics.pdf https://www.st.com/resource/en/datasheet/stm32h747xi.pdf https://electroprojecthub.com/blog/stm32-timer-pwm/

I checked all of the registers multiple times and do not see a problem. There are no errors when uploading the code. Here is the code:

void setup() 
{
  Serial.begin(115200);
  while (!Serial);
  HAL_Init();
  // 1. Enabling The Clock Sources
  RCC->APB1LENR |= RCC_APB1LENR_TIM14EN;    // Enable TIM14 peripheral clock source
  RCC->AHB4ENR |= RCC_AHB4ENR_GPIOAEN;    // Enable GPIOA peripheral clock source
  // 2. GPIO Setup
  GPIOA->MODER |= (0x2UL << 14);    // PA7 Alternate function AF9
  GPIOA->OSPEEDR |= ( 0x2UL << 14 );    // PA7 very high speed
  GPIOA->AFR[0] |= ( 0x9UL << 28);  // AF9 for TIM14 AFR[7] 
  // 3. Counter Mode
  // As the TIM14 peripheral only supports counting up there is nothing to be configured.
  // 4. Timer Timing Parameters
  TIM14->PSC = 15000-1;
  TIM14->ARR = 15000-1;
  TIM14->CCR1 = 10000-1;
  // 5. Configure PWM Mode
  TIM14->CCMR1 |= ( 0x6UL << TIM_CCMR1_OC1M_Pos );    // PWM mode 1 6<<4
  TIM14->CCMR1 |= TIM_CCMR1_OC1PE;          // Enable preload of CCR1 1<<3
  // 6. Enable Auto Reload Preload
  TIM14->CR1 |= TIM_CR1_ARPE;    // Enable preload of ARR 1<<7
  // 7. Signal Polarity, CC Output
  TIM14->CCER &= ~TIM_CCER_CC1P;     // Set signal polarity - 0
  TIM14->CCER |= TIM_CCER_CC1E;      // Enable CC - On - OC1 signal is output on the corresponding output pin 1<<0
  // 8. Set Interrupt Source
  TIM14->CR1 |= TIM_CR1_URS;    // Setting UG bit does not gen. int.  Only counter overflow generates an UEV if enabled 1<<2
  // 9. Reload The Registers
  TIM14->EGR |= TIM_EGR_UG;    // Generate an update event 1<<0
  // 10. Enable timer
  TIM14->CR1 |= 1<<0; // enable timer 1<<0
}

void loop() 
{
  Serial.println(TIM14->CNT);
}

Solution

  • GPIOA->MODER |= (0x2UL << 14); // PA7 Alternate function AF9

    In contrast to 'F4, in 'H7 which is basis of your Arduino Giga, all pins except the JTAG ones are set as Analog by default after reset, i.e. most fields of GPIOx_MODER are 0b11. By ORing anything you won't achieve the required 0b10 for Alternate Function.

    Try

    GPIOA->MODER = (GPIOA->MODER & ~(0x3UL << 14)) 
       | (0x2UL << 14);    // PA7 Alternate function AF9
    

    instead.