Forum: Mikrocontroller und Digitale Elektronik STM32: 2x PWM mit Phasenversatz?


von Sunnyboy (Gast)


Lesenswert?

Hallo Leute,

kann mir vielleicht jemand sagen, ob folgendes mit einem STM32F103C8 
funktioniert?

ich möchte für einen zwei Phasen Boostwandler (für einen MPPT Tracker) 
zwei PWMs per STM32F103 erzeugen. Diese sollen das selbe Ton zu Toff 
verhalten haben, aber zueinander um eine halbe Periode versetzt sein.

Das einzige, was ich bis jetzt gefunden habe ist, das man Totzeiten bei 
komplementären PWM Ausgängen einbauen kann, aber ich habe ja keine 
komplementären.

Geht das überhaupt bei dem STM32F103?

Danke

von Walter T. (nicolas)


Lesenswert?

Sunnyboy schrieb:
> aber ich habe ja keine komplementären.

Hast Du. Du weißt es nur nicht. Bei 90° Phasenverschiebung ist das 
Pegel-Vorzeichen doch egal. Es bleiben immer zwei um 90° verschobene 
Rechtecksignale.

: Bearbeitet durch User
von Sunnyboy (Gast)


Lesenswert?

Muss ich nicht um 180° verschieben?

von Walter T. (nicolas)


Lesenswert?

Wenn Du um 180° verschiebst, brauchst Du keine zwei PWM. Da reicht eine 
und ein Inverter.

von Sunnyboy (Gast)


Lesenswert?

Walter T. schrieb:
> Hast Du. Du weißt es nur nicht. Bei 90° Phasenverschiebung ist das
> Pegel-Vorzeichen doch egal. Es bleiben immer zwei um 90° verschobene
> Rechtecksignale.

Irgendwie verstehe ich die Aussage nicht. Könntest du das noch einmal 
erklären?

von temp (Gast)


Lesenswert?

Bei STM32F103 sehe ich nur die Möglichkeit 2 Timer gleich zu 
konfigurieren und vor dem Starten das TIMx_CNT Register bei einem Timer 
mit 0 zu laden und beim anderen mit dem gewünschten Versatz. Alle 
weiteren Aktionen, wie Tastverhältnis setzen z.B., müssen dann natürlich 
auf beiden Timern gemacht werden. Wenn du es dir noch aussuchen kannst, 
nimm den STM32F334. Der hat einen wesentlich besseren Timer (HRTIM) für 
diesen Zweck.

von Sunnyboy (Gast)


Lesenswert?

temp schrieb:
> Bei STM32F103 sehe ich nur die Möglichkeit 2 Timer gleich zu
> konfigurieren und vor dem Starten das TIMx_CNT Register bei einem Timer
> mit 0 zu laden und beim anderen mit dem gewünschten Versatz.

Super, das war es! Riesigen Dank! :)
Ich lasse jetzt einfach (erst einmal zum generellen testen) Timer 2 & 3 
@ 100kHz bei 72MHz Systemtakt laufen und habe TIM2_CNT einfach um den 
halbe Periode gesetzt. Somit ist er genau um eine halbe Periode 
versetzt.

temp schrieb:
> Wenn du es dir noch aussuchen kannst,
> nimm den STM32F334.

Ich hab hier noch eine handvoll von den STM32 Blue Pills mit eben den 
103ern liegen. Ich benutze zwar das Arduino Zeugs nicht, aber die Dinger 
sind einfach unschlagbar günstig. Für <2€ ein "ready to use" Board. Und 
für den selben Preis gibt es auch ein paar ST-Links, von denen auch 
welche habe.

von Walter T. (nicolas)


Lesenswert?

Ich verstehe das Problem wohl immer noch nicht. TIM1 und TIM8 haben eine 
dead time - Funktion (Register OCx und OCxN), deren Polarität sich 
frei wählen läßt.

Zwei phasenstarre, um 90° versetzte PWM sollten damit ohne Klimmzüge 
möglich sein.

: Bearbeitet durch User
von Sunnyboy (Gast)


Lesenswert?

Ich noch einmal :-(

Mich hat das mit TIM1 im complementair Mode nicht in ruhe gelassen...

Also was ich hinbekommen habe ist den ersten Kanal (T1C1 @PA8) zu 
erzeugen und den zweiten (T1C1N @PB13) zu invertieren. Aber wenn ich das 
Register CNT beschreibe bekomme ich keinen Deadtime-Versatz hin... es 
ändert nicht einmal etwas. Kann mir da noch jemand weiter helfen? Und 
ja, dies ist jetzt auf die Schnelle in "Arduino-Syntax" geschrieben - 
Asche auf mein Haupt!
1
#define PWM_OUT PA8       //PWM output
2
#define PWM_OUT_COMP PB13 //complementary output
3
4
void setup()
5
{
6
  pinMode(PC13, OUTPUT);
7
  HardwareTimer timer1 = HardwareTimer(1);
8
  timer1.setPrescaleFactor(1); 
9
  timer1.setPeriod(10); //100kHz
10
  
11
  pinMode(PWM_OUT, PWM); 
12
  pinMode(PWM_OUT_COMP, PWM);
13
  
14
  timer_dev *t = TIMER1; //refers t to Timer 1
15
  timer_reg_map r = t->regs;
16
17
  r.adv->CNT = 360;  << hat gänzlich keine Auswirkung! 360 ist die Hälfte der Periode von 720
18
   
19
  bitSet(r.adv->CCER,0); // enable CC1E
20
  bitSet(r.adv->CCER,2); // enable CC1NE
21
  bitSet(r.adv->CCER,3); // invert CC1NE 
22
    
23
  pwmWrite(PWM_OUT, 300); //
24
}

von Walter T. (nicolas)


Lesenswert?

Da wäre es sinnvoll zu wissen, in welchen Registern pwmWrite() 
herumschreibt.

von Sunnyboy (Gast)


Lesenswert?


von Walter T. (nicolas)


Lesenswert?

Sunnyboy schrieb:
> Hier wäre die Implementation dazu zu finden:

Dann wäre es interessant, zu wissen, in welchen Registern 
timer_set_compare() herumschreibt.

von Sunnyboy (Gast)


Lesenswert?

Ich finde es schlicht weg nicht - irgendwie undurchsichtig :-(

Welche müssten es denn sein? Dann setzte ich diese per Hand.

von Walter T. (nicolas)


Lesenswert?

Sunnyboy schrieb:
> Welche müssten es denn sein? Dann setzte ich diese per Hand.

Irgendwie fühle ich mich jetzt in Zugzwang, weil ich vorher auch schon 
geantwortet habe, und ich muß gestehen: Ich weiß es nicht. Ich nutze 
nicht bare metal, sondern die Standard Peripheral Library. Deren 
Implementierungsbeispiele wären also auch meine erste Anlaufstelle. Da 
sieht das Beispiel "TIM\ComplementarySignals" ziemlich nach dem aus, was 
Du vorhast.

von Hermann S. (diphtong)


Lesenswert?

Servus,

der Beitrag ist zwar schon etwas älter, aber ich habe auch ein kleines 
Problem mit soetwas.

Ich möchte auf einem STM32F103 eine Vollbrücke ansteuern und mit 
Phasenverschiebung regeln.

Ich habe auf einem Blue Pill Board TIM1 im output compare programmiert; 
CH1 CH1N und CH2 CH2N, die Phasenverschiebung zwischen CH1 und CH2 mach 
ich mit CCR1 und CCR2.
Über den ADC werden zwei Poti Werte eingelesen, eines für die 
Phasenverschiebung und eines für die Frequenz zum einstellen.
Zuätzlich sind noch 2 Hall Sensoren zur Stromüberwachung verbaut.

Das Ganze funktioniert auch schon ziemlich gut...nur ein kleines 
Problem:

Der Phasenversatz lässt sich über das Poti super einstellen, aber hin 
und wieder springen die Phasen umher. Also...wenn die Phasenverschiebung 
z. B. 0 sein sollte, kann es sein dass die auf einmal auf 100% springt, 
oder wenn so ca. 20% eingestellt sind, springt sie dann auf 80%...und 
auch wieder zurück.

Ich bekomme auch immer Warnungen, immer wenn der ADCWerte[3] ausgelesen 
wird:
"array subscript is above array bound"
Was kann das bedeuten???

Vielen Dank schon mal!


/* USER CODE BEGIN Header */
/**
  ************************************************************************ 
******
  * @file           : main.c
  * @brief          : Main program body
  ************************************************************************ 
******
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause 
license,
  * the "License"; You may not use this file except in compliance with 
the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ************************************************************************ 
******
  */
/* USER CODE END Header */

/* Includes 
------------------------------------------------------------------*/
#include "main.h"

/* Private includes 
----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ssd1306.h"
#include "fonts.h"
#include "math.h"
/* USER CODE END Includes */

/* Private typedef 
-----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define 
------------------------------------------------------------*/
/* USER CODE BEGIN PD */
volatile uint16_t ADCWerte[3];
volatile uint16_t shift;
volatile uint16_t frequenz;
volatile uint16_t i = 0;
char potiwert[12];
char potiwert2[12];
char shiftwert[12];
char frequenzwert[12];
char sensorwert1[12];
char sensorwert2[12];
char offsetwert1[12];
char offsetwert2[12];
double poti;
double poti2;
double sensor1;
double sensor2;
double s1offset;
double s2offset;
double strommax1 = 200; // +/- maximalwert Strom1 bei Abschaltung 
(Rohwert)
double strommax2 = 200; // +/- maximalwert Strom2 bei Abschaltung 
(Rohwert)

/* USER CODE END PD */

/* Private macro 
-------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables 
---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

I2C_HandleTypeDef hi2c1;
DMA_HandleTypeDef hdma_i2c1_rx;
DMA_HandleTypeDef hdma_i2c1_tx;

TIM_HandleTypeDef htim1;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes 
-----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_TIM1_Init(void);
static void MX_ADC1_Init(void);
static void MX_I2C1_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code 
---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */


  /* MCU 
Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the 
Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM1_Init();
  MX_ADC1_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
  SSD1306_Init();
  SSD1306_Clear();
  HAL_ADC_Start (&hadc1);
  HAL_ADCEx_Calibration_Start(&hadc1);
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*) ADCWerte, 4); //ADC -> DMA start
  HAL_Delay(100);

  s1offset = ADCWerte[2]; //Sensorwert1 offset aus Array auslesen
  s2offset = ADCWerte[3]; //Sensorwert2 offset aus Array auslesen
  HAL_Delay(100);

  frequenz = ((ADCWerte[1]*0.293)+450)-1; //frequenz berechnen 20-80 kHz
  shift = (frequenz*ADCWerte[0])/4096; //Phasenverschiebung berechnen

  i = shift; // i = berechneter Wert Phasenverschiebung für Softstart
  shift = 0;
  sensor1 = ADCWerte[2]; //Sensorwert1 aus Array auslesen
  sensor2 = ADCWerte[3]; //Sensorwert2 aus Array auslesen

  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET); //Enable pin ein
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); //Enable pin ein

  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1);    //start Timer1 CH1
  HAL_TIMEx_OCN_Start(&htim1, TIM_CHANNEL_1); //start Timer1 CH1N
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_2);    //start Timer1 CH2
  HAL_TIMEx_OCN_Start(&htim1, TIM_CHANNEL_2); //start Timer1 CH2N

  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
++++++++++++++++++++++++
  //Softstart:

  TIM1->ARR= frequenz; //counter period (frequenz) aktualisieren
  TIM1->CCR2 = shift;// Phasenverschiebung aktualisieren

  HAL_Delay(1000);

  for(shift=0; shift<=i; shift++) {
    shift = shift+5;

    TIM1->CCR2 = shift;

    sprintf (shiftwert, "%4d", shift);
      SSD1306_GotoXY (5,10);
      SSD1306_Puts ("shift", &Font_7x10, 1);
      SSD1306_GotoXY (55,10);
      SSD1306_Puts (shiftwert , &Font_7x10, 1);
      SSD1306_UpdateScreen(); //display

    HAL_Delay(0.01);
  }
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+++++++++++++++++++++++++
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

  while (ADCWerte[2] <= (s1offset+strommax1) && ADCWerte[2] >= 
(s1offset-strommax1) && ADCWerte[3] <= (s2offset+strommax2) && 
ADCWerte[3] >= (s2offset-strommax2)) //Hall-sensorwerte für 
Überstromüberwachung
  {
    //shift=0;
      frequenz = ((ADCWerte[1]*0.293)+450)-1; //frequenz berechnen 20-80 
kHz
      shift = (frequenz*ADCWerte[0])/4096; //Phasenverschiebung 
berechnen

      TIM1->ARR = frequenz; //counter period (frequenz) aktualisieren
      TIM1->CCR2 = shift;// Phasenverschiebung aktualisieren

      poti = ADCWerte[0]; //Potiwert shift aus Array auslesen
      poti2 = ADCWerte[1]; //Potiwert Frequenz aus Array auslesen
      //sensor1 = ADCWerte[2]; //Sensorwert1 aus Array auslesen
      //sensor2 = ADCWerte[3]; //Sensorwert2 aus Array auslesen

      //HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET); //Enable 
pin ein
      //HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); //Enable pin 
ein

    sprintf (potiwert, "%4d", ADCWerte[0]); //Poti Rohwert
    sprintf (potiwert2, "%4d", ADCWerte[1]); //Poti2 Rohwert
    sprintf (potiwert, "%5.3f [V]", ((poti/4096)*3.3)); //Poti Spannung 
[V]
    sprintf (potiwert2, "%5.3f [V]", ((poti2/4096)*3.3)); //Poti2 
Spannung [V]
    sprintf (shiftwert, "%4d %%", ((shift*100)/frequenz));
    sprintf (frequenzwert, "%5.2f kHz", 
((72000000/2/(double)frequenz)/1000));

    sprintf (offsetwert1, "%4.0f", s1offset);
    sprintf (offsetwert2, "%4.0f", s2offset);

    //verschiedene Ausgaben des 1. Sensors

    //sprintf (sensorwert1, "%4.0f", sensor1); //Sensor1 Rohwerte
    sprintf (sensorwert1, "%4.0f", (ADCWerte[2]-s1offset)); //Sensor1 
Rohwerte mit Offset
    //sprintf (sensorwert1, "%6.4f [V]", ((sensor1/4096)*3.3)); 
//Sensor1 Spannung [V]
    //sprintf (sensorwert1, "%6.4f [V]", (((sensor1/4096)*3.3)-1.7000)); 
//Sensor1 Spannung mit Offset [V]
    //sprintf (sensorwert1, "%4.0f [mV]", ((sensor1/4096)*3.3)*1000); 
//Sensor1 Spannung [mV]
    //sprintf (sensorwert1, "%4.0f [Gs]", 
((((1000-(-1000))/(4.0-1.0))*((sensor1/4096)*3.3)-1.0)+(-1000))); 
//Sensor1 Magnetfussdichte [Gauss]
    //sprintf (sensorwert1, "%6.3f [T]", 
((((sensor1-2100)/4096)*3.3)*(1000/1.5))/10000); //Sensor1 
Magnetfussdichte [T]
    //sprintf (sensorwert1, "%4.1f [A]", 
(((((sensor1-2100)/4096)*3.3)*(1000/1.5))/10000)*4998556*0.0014); 
//Sensor1 Strom [A]


    // verschiedene Ausgaben des 2. Sensors

    //sprintf (sensorwert2, "%4.0f", sensor2); //Sensor2 Rohwerte
    sprintf (sensorwert2, "%4.0f", (ADCWerte[3]-s2offset)); //Sensor2 
Rohwerte mit Offset
    //sprintf (sensorwert2, "%6.4f [V]", ((sensor2/4096)*3.3)); 
//Sensor2 Spannung [V]
    //sprintf (sensorwert2, "%6.4f [V]", (((sensor2/4096)*3.3)-1.7000)); 
//Sensor2 Spannung mit Offset [V]
    //sprintf (sensorwert2, "%4.0f [mV]", ((sensor2/4096)*3.3)*1000); 
//Sensor2 Spannung [mV]
    //sprintf (sensorwert2, "%4.0f [Gs]", 
((((1000-(-1000))/(4.0-1.0))*((sensor2/4096)*3.3)-1.0)+(-1000))); 
//Sensor2 Magnetfussdichte [Gauss]
    //sprintf (sensorwert2, "%6.3f [T]", 
((((sensor2-2100)/4096)*3.3)*(1000/1.5))/10000); //Sensor2 
Magnetfussdichte [T]
    //sprintf (sensorwert2, "%4.1f [A]", 
(((((sensor2-2100)/4096)*3.3)*(1000/1.5))/10000)*4998556*0.0014); 
//Sensor2 Strom [A]


      SSD1306_GotoXY (5,0);
      SSD1306_Puts ("Poti1", &Font_7x10, 1);
      SSD1306_GotoXY (55,0);
      SSD1306_Puts (potiwert, &Font_7x10, 1);

      SSD1306_GotoXY (5,10);
      SSD1306_Puts ("Poti2", &Font_7x10, 1);
      SSD1306_GotoXY (55,10);
      SSD1306_Puts (potiwert2, &Font_7x10, 1);

      SSD1306_GotoXY (5,20);
      SSD1306_Puts ("shift", &Font_7x10, 1);
      SSD1306_GotoXY (62,20);
      SSD1306_Puts (shiftwert , &Font_7x10, 1);

      SSD1306_GotoXY (5,30);
      SSD1306_Puts ("freq", &Font_7x10, 1);
      SSD1306_GotoXY (55,30);
      SSD1306_Puts (frequenzwert , &Font_7x10, 1);

      SSD1306_GotoXY (5,41);
      SSD1306_Puts ("H1:", &Font_7x10, 1);
      SSD1306_GotoXY (30,41);
      SSD1306_Puts (sensorwert1, &Font_7x10, 1);

      SSD1306_GotoXY (70,41);
      SSD1306_Puts ("H2:", &Font_7x10, 1);
      SSD1306_GotoXY (95,41);
      SSD1306_Puts (sensorwert2, &Font_7x10, 1);

      SSD1306_GotoXY (5,52);
      SSD1306_Puts ("o1:", &Font_7x10, 1);
      SSD1306_GotoXY (30,52);
      SSD1306_Puts (offsetwert1, &Font_7x10, 1);

      SSD1306_GotoXY (70,52);
      SSD1306_Puts ("o2:", &Font_7x10, 1);
      SSD1306_GotoXY (95,52);
      SSD1306_Puts (offsetwert2, &Font_7x10, 1);

      SSD1306_UpdateScreen(); //display

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

  // 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
++++++++++++++++++++++++++++++++
  // Bei Überstromerkennung
  ueberstrom:
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET); //Enable pin 
aus
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); //Enable pin aus
  HAL_ADC_Stop_DMA(&hadc1);                  //ADC -> DMA stop
  HAL_TIM_OC_Stop(&htim1, TIM_CHANNEL_1);    //stop Timer1 CH1
  HAL_TIMEx_OCN_Stop(&htim1, TIM_CHANNEL_1); //stop Timer1 CH1N
  HAL_TIM_OC_Stop(&htim1, TIM_CHANNEL_2);    //stop Timer1 CH2
  HAL_TIMEx_OCN_Stop(&htim1, TIM_CHANNEL_2); //stop Timer1 CH2N
  SSD1306_ToggleInvert();
  SSD1306_UpdateScreen();
  HAL_Delay(500);
  goto ueberstrom;
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+++++++++++++++++++++++++++++++++++
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != 
HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV8;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief ADC1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 4;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_4;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief TIM1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 1200;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_OC_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != 
HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != 
HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.Pulse = 600;
  if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != 
HAL_OK)
  {
    Error_Handler();
  }
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1;
  sBreakDeadTimeConfig.DeadTime = 50;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != 
HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

  /* USER CODE END TIM1_Init 2 */
  HAL_TIM_MspPostInit(&htim1);

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  /* DMA1_Channel6_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
  /* DMA1_Channel7_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1|GPIO_PIN_15, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PB1 PB15 */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return 
state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line 
number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and 
line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, 
line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF 
FILE****/

von Hermann S. (diphtong)


Lesenswert?

Hat keiner eine Antwort?

PS: es hat nix mit dem gefälschten Stm32 aus dem anderen Beitrag zu tun, 
ich hab hier zwar auch einen gefälschten chip, aber es ist kein 
Unterschied erkennbar, wenn ichs auf einen orig stm32f103c8t6 aufspiele.

von Hermann S. (diphtong)


Lesenswert?

und wenn ich ccr1=0 und ccr2=200 zum beispiel fest vergebe und die ccr2 
aktualisierung über den ADC auskommentiere, funktionierts. es muss wohl 
was mit dem adc/dma zu tun haben?!

von Hermann S. (diphtong)


Lesenswert?

Beitrag von Sascha, nicht den PA0 zu benutzen hat funktioniert!

Beitrag "Ungenauigkeit beim STM32 ADC"

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.