Hallo Doc_Arduino, Nyquist-Abtasttheorem fmax = Fs/2 usw, ja das ist mir alles bekannt.
Der clock Fluss bis zum DAC Timer, ist mir bekannt.
Fakt ist, ich habe einen Systemtakt von 480Mhz und eine APB1 Presacalr von 1
Das bedeute die APB1 clock läuft mit dem Systemtakt.
Das bedeutet im Umkehrschluss ich kann das DAc output Register 480 Millionen mal in der Sekunde beschreiben. Als im Grunde genommenem müsste ich eine Rechteck Impuls von 240 Mhz ausgeben können.
Das das nicht geht ist mir klar, weil der DAC irgendwo auch für eine Wandlung zeit benötigt.
Aber im Datenblatt steht, sofern man den Trigger auf None hat (also Automatisch), dann wird ins DAC Output Register geschrien nach einem Bus Takt sobald man ins DAC hold Register beschrieben hat.
Also quasi in Echtzeit zur loop. Der eine Takt ist zu vernachlässigen. Bei 480Mhz sind Das irgendwas mit 2,....ns.
Wenn ich jetzt folgende schleifen aufbau haben:
void loop() {
uint16_t out = 0;
uint16_t out_2 = 4090;
unsigned long beginT = micros();
for (uint16_t i = 0; i < 4090 * 2; i += 5) {
if (out < 4095) {
//HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, out);
hdac1.Instance->DHR12R1 = out;
out += 5;
} else {
//HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, out_2);
hdac1.Instance->DHR12R1 = out_2;
out_2 -= 5;
}
}
unsigned long endT = micros() - beginT;
//Serial.println(endT);
//Serial.println(SystemCoreClock);
}
Dann erwarte ich ein "Ping-Pong" Output von weitaus mehr als 44kHz.
Die ganze schleife ist in gerade mal 22Mikrosekunden durchlaufen. Interessanter weiße ist 22Mikrosekunden ~45kHz.
Ich sehe mit meinem Redpitaya anscheint nur gewisse Punkte der DAC Ausgabe oder der STM32 überspringt Ausgabe werte. Wie Du es schon die ganze Zeit vermutest.
Gut okay, gehen wir die Sache etwas gemütlicher an und gehen mit der Samplerate auf 192kHz runter und geben ein 10kHz Sinus aus:
#include "stm32h7xx.h"
#include "nvic_addr.h"
#include "mbed_error.h"
#define FS 192000
#define FREQUENCY 10000
/******************************************************************************/
/* PLL (clocked by HSE) used as System clock source */
/******************************************************************************/
uint8_t SetSysClock_PLL_HSE() {
RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
// If we are reconfiguring the clock, select CSI as system clock source to allow modification of the PLL configuration
if (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE) {
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_CSI;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
while (1)
; //FAIL
}
}
/* Enable oscillator pin */
__HAL_RCC_GPIOH_CLK_ENABLE();
GPIO_InitTypeDef gpio_osc_init_structure;
gpio_osc_init_structure.Pin = GPIO_PIN_1;
gpio_osc_init_structure.Mode = GPIO_MODE_OUTPUT_PP;
gpio_osc_init_structure.Pull = GPIO_PULLUP;
gpio_osc_init_structure.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOH, &gpio_osc_init_structure);
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_1, GPIO_PIN_SET);
HAL_PWREx_ConfigSupply(PWR_SMPS_1V8_SUPPLIES_LDO);
/* Configure the main internal regulator output voltage */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI48;
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 5;
// 400 MHz (25 / 5 * 160 / 2 = 400)
// 480 MHz (25 / 5 * 192 / 2 = 400)
RCC_OscInitStruct.PLL.PLLN = 192; //was 160;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLQ = 10;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
while (1)
; // FAIL
}
/* Select PLL as system clock source and configure bus clocks dividers */
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_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
while (1)
; //FAIL
}
__HAL_RCC_CSI_ENABLE();
__HAL_RCC_SYSCFG_CLK_ENABLE();
HAL_EnableCompensationCell();
return 1; // OK
}
DAC_HandleTypeDef hdac1;
HAL_DAC_StateTypeDef dacState;
const uint32_t numSamples = FS / FREQUENCY;
const double _T = 1.0f / FS * 1000 * 1000;
static uint16_t sineArray[FS] = { 0 };
uint32_t x = 0;
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) {
while (1)
; //FAIL
}
sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK) {
while (1)
; //FAIL
}
HAL_DAC_Start(&hdac1, DAC_CHANNEL_1);
}
void delay_ns(uint32_t ns) {
uint32_t tickstart = HAL_GetTick();
uint32_t wait = ns * (SystemCoreClock / 1000000000UL);
while ((HAL_GetTick() - tickstart) < wait) {};
}
void setup() {
extern uint8_t SetSysClock_PLL_HSE();
SetSysClock_PLL_HSE();
Serial.begin(9600);
unsigned long i = 0;
for (; i < FS; i++) {
int16_t val = 32767 * (sin(2 * PI * i * FREQUENCY / FS));
sineArray[i] = (val + 32768) >> 4;
}
initDAC1();
}
void loop() {
hdac1.Instance->DHR12R1 = sineArray[x];
x = (x + 1) % FS;
delayMicroseconds(_T);
//Serial.println(SystemCoreClock);
}
Den Sampele intervall regelt delayMicroseconds(_T);. Ich erwarte einen 10Khz sinus am DAC ausgang.
Aber es kommen 100kHz heraus.
Also ist hier irgendwas nicht richtig an meiner Logic.


