Ja, macht Sinn^^. Haben die wahrscheinlich konstruktionsbedingt so gemacht.
Ich habe jetzt mal andere Messmethoden und Debugging Methoden aufgezogen.
Ich habe diesen Sinus berechnung's Quark weggelassen und stattdessen. in einer schleife die Spannung "langsam" erhöht und auch reduziert.
#include "stm32h7xx_hal.h"
#include "stm32h7xx_hal_rcc.h"
#define F_CPU_ACTUAL 480000000
static inline void delayNanoseconds(uint32_t) __attribute__((always_inline, unused));
DAC_HandleTypeDef hdac1;
HAL_DAC_StateTypeDef dacState;
void initDAC1() {
DAC_ChannelConfTypeDef sConfig = { 0 };
// Enable clock for DAC
__HAL_RCC_DAC12_CLK_ENABLE();
// Initialize DAC
hdac1.Instance = DAC1;
hdac1.State = HAL_DAC_STATE_RESET;
if (HAL_DAC_Init(&hdac1) != HAL_OK) {
// Initialization Error
}
// Disable output buffer
//hdac1.Instance->MCR &= ~(DAC_MCR_MODE1_1 | DAC_MCR_MODE1_0);
sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK) {
}
HAL_DAC_Start(&hdac1, DAC_CHANNEL_1);
}
void initRCC_DAC1() {
RCC->D2CFGR = 0;
RCC->D2CFGR |= RCC_D2CFGR_D2PPRE1_DIV1;
}
// Wait for a number of nanoseconds. During this time, interrupts remain
// active, but the rest of your program becomes effectively stalled.
static inline void delayNanoseconds(uint32_t nsec) {
uint32_t begin = DWT->CYCCNT;
uint32_t cycles = ((F_CPU_ACTUAL >> 16) * nsec) / (1000000000UL >> 16);
while (DWT->CYCCNT - begin < cycles)
; //wait
}
void wait_DAC1() {
do {
dacState = HAL_DAC_GetState(&hdac1);
} while (dacState != HAL_DAC_STATE_READY);
}
void setup() {
HAL_Init();
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->LAR = 0xC5ACCE55;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
Serial.begin(9600);
initDAC1();
initRCC_DAC1();
}
void loop() {
uint16_t out = 0;
uint16_t out_2 = 4095;
unsigned long beginT = micros();
for (uint16_t i = 0; i < 4095 * 2; i += 5) {
if (out < 4095) {
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, out);
out += 5;
} else {
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, out_2);
out_2 -= 5;
}
wait_DAC1();
}
unsigned long endT = micros() - beginT;
Serial.println(endT);
}
Man kann die Taktung auch via HAL libaray einstellen:
void initRCC_DAC1() {
//RCC->D2CFGR = 0;
//RCC->D2CFGR |= RCC_D2CFGR_D2PPRE1_DIV1;
RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_D1PCLK1 | RCC_CLOCKTYPE_D3PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV16;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
while (1) {}; // FAIL
}
}
Vorteil ist, dass die Eingaben auch noch validiert werden.
Das Ergebnis nun wie folgt:
RCC_D2CFGR_D2PPRE1_DIV1 ergibt ein Dreieck-Impuls von ~4,7kHz Die ganze Schleife benötigt ~223 Mikrosekunden.
RCC_D2CFGR_D2PPRE1_DIV16 ergibt ein Dreieck-Impuls von ~3,7kHz Die ganze Schleife benötigt ~35 Mikrosekunden.
Weshalb die ausgegebene Frequenz nun Schneller ist, aber der Schleifen Durchlauf insgesamt langsamer verstehe ich noch nicht.
Vermutlich Prüft HAL_DAC_SetValue ob der DAC bereit ist, wenn nicht überspringt er die Funktion. Damit wäre mein Aufruf von wait_DAC1(); überflüssig.
Nebenbei ist das Portenta H7 nur mit 400Mhz getaktet:
4kHz sind jetzt auch nicht unbedingt das was ich erwartet habe.

