Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av DanielM »

STM32 har räknare, även timers som det hete på Engelska. En initialisering av en räknare brukar se ut så här hos STM32.

Vid start så anropas räknare för TIM2

Kod: Markera allt

MX_TIM2_Init();
Min fråga till er är att om jag vill ändra

Kod: Markera allt

 htim2.Init.Prescaler
Till ett annat värde, är det bara för mig att ha ändra värdet och anropa

Kod: Markera allt

MX_TIM2_Init();
Igen? Eller är det något annat jag måste tänka på när man ska ändra räknaren under körning?
Ja. TIM2 fungerar som räknare för ADC. Så slutar TIM2 fungera, så slutar ADC att sampla.

Kod: Markera allt

static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 39-1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 4095;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);

}
hummel
Inlägg: 2259
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av hummel »

Det går inte att svara på utan att läsa databladet.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av DanielM »

Jag har den framför mig RM0313. Men här dör man ju. Hur ska man hitta en förklaring i denna röra, att man kan göra det, utan att det påverkat något annat?

Annars har jag en bättre idé kanske? Vad tror ni om att när man kan bränna in skalare i minnet och vid uppstart så läser räknarna dessa från minnet? :)

Kod: Markera allt

//Private variables
//1. sector start address
static uint32_t memory_address;

// Set Sector Adress
void FlashSetAddrs(uint32_t memory_address) {
	memory_address = addrs;
}

// Write Flash
void FlashWriteN(uint32_t idx, void *wrBuf, uint32_t Nsize, DataTypeDef dataType) {
	uint32_t flashAddress = memory_address + idx;

	// Converter
	Convert convert;
	uint32_t wrBuf2[1];

	//Unlock Flash
	HAL_FLASH_Unlock();
	//Write to Flash
	switch (dataType) {
	case DATA_TYPE_U64:
		for (uint32_t i = 0; i < Nsize; i++) {
			HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flashAddress, ((uint64_t*) wrBuf)[i]);
			flashAddress += 8;
		}
		break;

	case DATA_TYPE_U16:
		for (uint32_t i = 0; i < Nsize; i++) {
			HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, flashAddress, ((uint16_t*) wrBuf)[i]);
			flashAddress += 2;
		}
		break;

	case DATA_TYPE_U32:
		for (uint32_t i = 0; i < Nsize; i++) {
			HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, flashAddress, ((uint32_t*) wrBuf)[i]);
			flashAddress += 4;
		}
		break;

	case DATA_TYPE_FLOAT:
		for (uint32_t i = 0; i < Nsize; i++) {
			// Convert float -> uint8_t
			convert.float_value = ((float*) wrBuf)[i];
			// Turn it to uint32_t
			wrBuf2[0] = convert.uint8_values[0] << 24 | convert.uint8_values[1] << 16 | convert.uint8_values[2] << 8 || convert.uint8_values[3];
			// Write the uint32_t byte
			FlashWriteN(idx + 4*i, wrBuf2, 1, DATA_TYPE_U32);
		}
		break;
	}
	//Lock the Flash space
	HAL_FLASH_Lock();
}
//4. Read Flash
void FlashReadN(uint32_t idx, void *rdBuf, uint32_t Nsize, DataTypeDef dataType) {
	uint32_t flashAddress = SectorAddrs + idx;

	// Converter
	Convert convert;
	uint32_t rdBuf2[1];

	switch (dataType) {
	case DATA_TYPE_U64:
		for (uint32_t i = 0; i < Nsize; i++) {
			*((uint64_t*) rdBuf + i) = *(uint64_t*) flashAddress;
			flashAddress += 8;
		}
		break;

	case DATA_TYPE_U16:
		for (uint32_t i = 0; i < Nsize; i++) {
			*((uint16_t*) rdBuf + i) = *(uint16_t*) flashAddress;
			flashAddress += 2;
		}
		break;

	case DATA_TYPE_U32:
		for (uint32_t i = 0; i < Nsize; i++) {
			*((uint32_t*) rdBuf + i) = *(uint32_t*) flashAddress;
			flashAddress += 4;
		}
		break;

	case DATA_TYPE_FLOAT:
		for (uint32_t i = 0; i < Nsize; i++) {
			// Read the uint32_t byte
			FlashReadN(idx + 4 * i, rdBuf2, 1, DATA_TYPE_U32);
			// Convert uint32_t -> float
			convert.uint8_values[0] = rdBuf2[0] >> 24;
			convert.uint8_values[1] = rdBuf2[1] >> 16;
			convert.uint8_values[2] = rdBuf2[2] >> 8;
			convert.uint8_values[3] = rdBuf2[3];
			*((float*) rdBuf + i) = convert.float_value;
		}
		break;
	}
}

Kod: Markera allt

#ifndef SRC_FLASHMEMORY_F373XX_READWRITE_H_
#define SRC_FLASHMEMORY_F373XX_READWRITE_H_

#include "main.h"

//Typedefs
//1. data size
typedef enum{
	DATA_TYPE_U64=0,
	DATA_TYPE_U16,
	DATA_TYPE_U32,
	DATA_TYPE_FLOAT
}DataTypeDef;

// Converter for float <--> uint8_t
typedef union{
    float float_value;
    uint8_t uint8_values[sizeof(float)];
}Convert;

// Set memory address
void FlashSetAddrs(uint32_t memory_address);
// Write Flash
void FlashWriteN(uint32_t idx, void *wrBuf, uint32_t Nsize, DataTypeDef dataType);
// Read Flash
void FlashReadN(uint32_t idx, void *rdBuf, uint32_t Nsize, DataTypeDef dataType);

#endif /* SRC_FLASHMEMORY_F373XX_READWRITE_H_ */
hummel
Inlägg: 2259
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av hummel »

På vilket sätt är databladet en röra? Visst mycket information men det behövs med en avancerad mikrokontroller.

Kan det vara ett alternativ att du väljer en avsevärt simplare mikrokontroller med förre funktionalitet och ett tunnare datablad för ditt projekt?
Användarvisningsbild
Icecap
Inlägg: 26105
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av Icecap »

När det är problem med att läsa datablad brukar det vara för att kundskapen om hur en μC fungerar som låter en del att önska.

Ska man ändra prescaler eller liknande ska det räcka att skriva in nya värden i de rätta registren.
H.O
Inlägg: 5683
Blev medlem: 19 mars 2007, 10:11:27
Ort: Ronneby

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av H.O »

Om du först ändrar prescalerns värde genom t.ex

Kod: Markera allt

htim2.Init.Prescaler = 63;
och sedan anropar MX_TIM2_Init() så kommer (väl?) Init()-rutinen att skriva över prescalerns värde med vad som står i Init()-rutine (alltså 39-1)?
Användarvisningsbild
Klas-Kenny
Inlägg: 11291
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av Klas-Kenny »

Ja alltså det lär säkert fungera att göra så. I den mån att timern efter detta kommer att snurra i ny hastighet (om inte init-funktionen ställer krav på att timern är stoppad innan eller något).

Frågan är ju vad som händer under tiden, och den första frågan kanske är, spelar det någon roll vad som händer under tiden? Om timern tex. Stoppas en stund, gör det något för din applikation?
Användarvisningsbild
Icecap
Inlägg: 26105
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av Icecap »

Om init-rutinen gör saker med timerinterrupten kan det kanske ge problem. Detta iaf. om det är en dynamisk funktion.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av DanielM »

hummel skrev: 11 december 2020, 09:54:02 På vilket sätt är databladet en röra? Visst mycket information men det behövs med en avancerad mikrokontroller.

Kan det vara ett alternativ att du väljer en avsevärt simplare mikrokontroller med förre funktionalitet och ett tunnare datablad för ditt projekt?
STM32's dokumentation ÄR och förblir en röra. Hade det inte varit så, så hade STM32 officiellt inte rekommenderat STM32CubeIDE som det primära verktyget.
Tittar man på MicroChips AVR så brukar det oftast följa med exempelkod i deras dokumentation.

Simplare = Dummare och sämre.
Tittar man på PIC eller AVR så verkar dom ligga efter med tiden. STM32 framstår som monster CPU som verkar ha allt nu för tiden.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av DanielM »

Icecap skrev: 11 december 2020, 10:22:23 När det är problem med att läsa datablad brukar det vara för att kundskapen om hur en μC fungerar som låter en del att önska.

Ska man ändra prescaler eller liknande ska det räcka att skriva in nya värden i de rätta registren.
Det kanske är mer pedagogiskt att anropa befintlig funktion med ett argument som är nya prescaler?
H.O skrev: 11 december 2020, 11:54:30 Om du först ändrar prescalerns värde genom t.ex

Kod: Markera allt

htim2.Init.Prescaler = 63;
och sedan anropar MX_TIM2_Init() så kommer (väl?) Init()-rutinen att skriva över prescalerns värde med vad som står i Init()-rutine (alltså 39-1)?
Så jag kan bara ändra prescaler och sedan återanropa? Helt OK med det?
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av DanielM »

Icecap skrev: 11 december 2020, 15:45:19 Om init-rutinen gör saker med timerinterrupten kan det kanske ge problem. Detta iaf. om det är en dynamisk funktion.
Klas-Kenny skrev: 11 december 2020, 13:45:53 Ja alltså det lär säkert fungera att göra så. I den mån att timern efter detta kommer att snurra i ny hastighet (om inte init-funktionen ställer krav på att timern är stoppad innan eller något).

Frågan är ju vad som händer under tiden, och den första frågan kanske är, spelar det någon roll vad som händer under tiden? Om timern tex. Stoppas en stund, gör det något för din applikation?
Exakt! Det är det jag söker om det är så i databladet. Hittar inget, men STM32 kanske förutsätter att man ska veta det?
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45168
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av TomasL »

I datbldet hittart du ingenting om hur ditt IDE initierar saker, den informationen får du leta efter i ditt IDE
Användarvisningsbild
Klas-Kenny
Inlägg: 11291
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av Klas-Kenny »

DanielM skrev: 11 december 2020, 21:09:58 STM32's dokumentation ÄR och förblir en röra. Hade det inte varit så, så hade STM32 officiellt inte rekommenderat STM32CubeIDE som det primära verktyget.
Tittar man på MicroChips AVR så brukar det oftast följa med exempelkod i deras dokumentation.

Simplare = Dummare och sämre.
Tittar man på PIC eller AVR så verkar dom ligga efter med tiden. STM32 framstår som monster CPU som verkar ha allt nu för tiden.
Bara för att ett specifikt verktyg rekommenderas, så måste väl inte dokumentationen vara dålig? :humm:
ST's dokumentation är väldigt likvärdig med alla andra tillverkare som jag jobbat med (NXP, Microchip, Atmel).

Kollar du sidan 303 i referensmanualen så finner du följande:
Prescaler description
The prescaler can divide the counter clock frequency by any factor between 1 and 65536. It
is based on a 16-bit counter controlled through a 16-bit/32-bit register (in the TIMx_PSC
register). It can be changed on the fly as this control register is buffered. The new prescaler
ratio is taken into account at the next update event.
Och på nästkommande sida ett par illustrerade exempel på vad som händer när man ändrar prescalern under drift.

En bättre beskrivning än så kan man väl knappast drömma om? :)


MEN, som sagt, vad biblioteksfunktionerna hittar på på vägen har inte databladet en aning om.
Antingen så gräver du i dokumentationen för biblioteket, eller så följer du funktionsanropen för init-funktionen för att se vad den gör, eller så gör du det allra enklaste och effektivaste, att skriva det nya värdet direkt till TIM2->PSC.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av DanielM »

Ja. Detta betyder att jag behöver bara uppdatera

Kod: Markera allt

htim2.Init.Prescaler
Med ett nytt värde? :)
Nej, det växer fortfarande följdfrågor kring STM's dokumentation.

Jag vill helst bara ändra "htim2.Init.Prescaler" och se glad ut :)
Användarvisningsbild
AndLi
Inlägg: 17042
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Återinitialisera räknare hos STM32 - Är det bara anropa initialiseringen igen?

Inlägg av AndLi »

Men då har du inte förstått hur HAL biblioteket funkar, de struktarna är inte mappade till registrena för timern.
Skriv svar