Vier-Bit-Oszilloskop - Gunook
Vier-Bit-Oszilloskop - Gunook
Anonim
Vier-Bit-Oszilloskop
Vier-Bit-Oszilloskop

Es ist ein Spaßprojekt, nur um zu sehen, wie weit ich ein MAX7219-Punktmatrix-Display in Geschwindigkeit bringen könnte. Und anstatt es das "Spiel des Lebens" ausführen zu lassen, beschloss ich, ein "Scope" damit zu machen. Wie Sie dem Titel entnehmen können, ist dies kein Ersatz für ein echtes Oszilloskop:-).

Da ich nicht vorhabe, dies ernsthaft zu verwenden, werde ich keine Leiterplatte dafür herstellen. Vielleicht, nur vielleicht lege ich es auf ein Perf-Board, aber im Moment ist und bleibt es auf einem Steckbrett. Es gibt auch keinen Eingangsverstärker/Dämpfer, Sie müssen ein Signal zwischen 0 und 3,3 V liefern, gehen Sie nicht negativ oder über 3,3 V, da Sie den Mikrocontroller beschädigen können.

Schritt 1: Hardware

Hardware
Hardware
Hardware
Hardware
Hardware
Hardware

Es ist billig, sehr günstig, wenn Sie die Teile in China über ebay oder ähnliche Seiten kaufen. Es verwendet ein STM32F103C8-Entwicklungsboard, manchmal auch als "blaue Pille" bezeichnet, das ich für etwa 2 Euro (oder USD, sie haben fast den gleichen Wert, Ende 2018) gekauft habe, zwei 8x8x4 Dot-Matrix-Displays mit MAX7219-Chips darauf, gekauft für 5 Euro pro Stück und ein Drehgeber von ca. 1 Euro.

Benötigt wird natürlich ein Netzteil mit 3,3V bei einigen hundert Milliampere. Der Spannungsregler auf dem STM32F103C8-Entwicklungsboard wird nicht verwendet, er kann nicht genügend Strom für die Displays bereitstellen. Das Datenblatt für den MAX7219 gibt an, dass die Betriebsspannung zwischen 4,0 und 5,5 V liegen sollte, aber bei 3,3 V läuft er gut, vielleicht nicht, wenn Sie ihn in einer sehr heißen oder kalten Umgebung verwenden, aber bei 20 Celsius ist es in Ordnung. Und jetzt muss ich keine Pegelwandler zwischen dem Mikrocontroller und den Anzeigetafeln verwenden.

Schritt 2: Erstellen

Bauen
Bauen
Bauen
Bauen
Bauen
Bauen

Wenn Sie sich das Bild ansehen, sehen Sie vielleicht, dass ich die Stromleitungen auf den Steckbrettern auf unkonventionelle Weise verwende, beide Leitungen oben sind die positive Schiene und beide unten sind die Masseschiene. Es ist die Art und Weise, wie ich es gewohnt bin, und es funktioniert gut, es lässt das Setup ein bisschen mehr wie die Schaltpläne aussehen, die ich zeichne. Außerdem habe ich viele kleine Platinen mit Teilen gemacht, die ich in das Steckbrett einstecken kann, um die Dinge zu beschleunigen, und sie sind alle so konfiguriert, dass die beiden oberen Leitungen als Positiv und die unteren Leitungen als Masse verwendet werden. Wie gesagt, die Auflösung beträgt 4 Bit (16 Stufen), und da 4x8 LEDs nebeneinander liegen, sind es nur 32 Abtastpunkte (pts). Vergleichen Sie das mit einem Rigol Rigol DS1054Z (8 Bit und 12 Mpts) und Sie werden sehen, dass dies kaum ein Spielzeug ist. Was die tatsächliche Bandbreite ist, weiß ich nicht, ich habe sie bis zu 10 kHz getestet und das funktioniert gut.

Schritt 3: Programme

Programme
Programme
Programme
Programme
Programme
Programme
Programme
Programme

Die von mir verwendete IDE ist Atollic TrueStudio, die seit Anfang dieses Jahres (2018) von ST Micro Electronics übernommen wurde und kostenlos zur Verfügung steht, keine zeitliche Begrenzung, keine Beschränkung der Codegröße, keine Nörgler-Screens. Zusammen damit verwende ich STM32CubeMX, ein Programm, das mir den Startcode liefert und die Initialisierung aller Peripheriegeräte generiert. Und es hat eine Anzeige aller Pins des Mikrocontrollers und deren Verwendung. Auch wenn Sie STM32CubeMX nicht zum Generieren von Code verwenden, ist dies sehr praktisch. Eine Sache, die ich nicht mag, ist die sogenannte HAL, die der Standard von STM32CubeMX ist. Ich bevorzuge die LowLayer-Arbeitsmethode.

Zur Programmierung des Mikrocontrollers verwende ich entweder den ST-Link Programmer/Debugger von ST Micro Electronics oder den J-Link von Segger. Beide Geräte sind nicht kostenlos, obwohl Sie für ein paar Euro chinesische Kopien davon kaufen können.

Schritt 4: Über den Code

Die MAX7219 adressieren die LEDs in einer, wie ich es nenne, horizontalen Weise, 8 LEDs nebeneinander. Für ein Oszilloskop wären 8 LEDs übereinander einfacher gewesen, deshalb habe ich einen einfachen Frame-Buffer erstellt, der vertikal mit Daten beschrieben und horizontal ausgelesen wird. Der MAX7219 verwendet einen 16-Bit-Code pro 8 LEDs, wobei das erste Byte verwendet wird, um die ausgewählte Leitung zu adressieren. Und da vier dieser Module nebeneinander gestapelt sind und deren Eingänge mit den Ausgängen des Moduls davor verbunden sind, müssen Sie diese 16 Bit viermal senden, um das letzte Modul zu erreichen. (Ich hoffe, ich stelle die Dinge klar…) Die Daten werden mit SPI, einem einfachen, aber sehr schnellen Protokoll, an den MAX7219 gesendet. Damit habe ich experimentiert, wie schnell Sie die Daten an den MAX7219 senden können. Am Ende habe ich wieder auf 9 MHz umgeschaltet, knapp unterhalb der maximalen Geschwindigkeit, die das Datenblatt angibt.

Ich verwende zwei der vier verfügbaren Timer des STM32F103C8, einen für die Generierung der Zeitbasis und den anderen zum Auslesen des Drehgebers, der die Zeitbasis einstellt. TIMER3 erzeugt die Zeitbasis, indem es die Uhr durch 230 teilt und den Zähler alle 3,2 us aktualisiert. Mit dem Drehgeber können Sie wählen, ob der Zähler von 2 Taktimpulsen bis zu 2000 Taktimpulsen zählt. Nehmen wir an, Sie wählen 100. TIMER3 generiert dann alle 320 uS ein EVENT. Dieses EREIGNIS veranlasst den ADC, ein Sample des Eingangssignals aufzuzeichnen. 10 ms. In 10 mS können Sie eine Wellenlänge von 100 Hz oder zwei von 200 Hz usw. anpassen. Bei mehr als 3 Wellen pro Bildschirm ist es jedoch ziemlich schwierig, die Wellenform zu erkennen.

Im Übrigen kann ich Sie nur auf den Code verweisen, es ist nicht schwer zu folgen, auch wenn Sie nur etwas Erfahrung mit einem Arduino haben. Tatsächlich könnte man dasselbe mit einem Arduino machen, obwohl ich bezweifle, dass es so schnell wie eine "blaue Pille" funktionieren würde. Der STM32F103C8 ist ein 32-Bit-Mikrocontroller mit 72 MHz, er verfügt über zwei SPI-Peripheriegeräte und einen sehr schnellen ADC.

Schritt 5: Main.h

#ifndef _MAIN_H_#define _MAIN_H_

#include "stm32f1xx_ll_adc.h"

#include "stm32f1xx_ll_rcc.h" #include "stm32f1xx_ll_bus.h" #include "stm32f1xx_ll_system.h" #include "stm32f1xx_ll_exti.h" #include "stm32f1xx_ll_bus.h" #include "stm32f1xx_ll_exti.h" #include "stm32f1xx_ll_bus.h" #include. include "stm32f1xx_ll_dma.h" #include "stm32f1xx_ll_spi.h" #include "stm32f1xx_ll_tim.h" #include "stm32f1xx.h" #include "stm32f1xx_ll_gpio.h"

#ifndef NVIC_PRIORITYGROUP_0

#define NVIC_PRIORITYGROUP_0 ((uint32_t)0x00000007) #define NVIC_PRIORITYGROUP_1 ((uint32_t)0x00000006) #define NVIC_PRIORITYGROUP_2 ((uint32_t)0x00000005) #define NVIC_PRIORITYGROUP_1 ((uint32_t)0)

#ifdef _cplusplus

extern "C" { #endif void _Error_Handler(char *, int);

#define Error_Handler() _Error_Handler(_FILE_, _LINE_)

#ifdef _cplusplus } #endif

#endif

Schritt 6: Main.c

#include "main.h" statisch void LL_Init(void); void SystemClock_Config(void); statisch leer MX_GPIO_Init(void); statisch leer MX_ADC1_Init(void); statisch leer MX_SPI1_Init(void); statisch leer MX_SPI2_Init(void); statisch leer MX_TIM3_Init(void); statisch leer MX_TIM4_Init(void);

uint16_t SPI1_send64(uint16_t data3, uint16_t data2, uint16_t data1, uint16_t data0);

uint16_t SPI2_send64(uint16_t data3, uint16_t data2, uint16_t data1, uint16_t data0); void MAX7219_1_init(); void MAX7219_2_init(); void delete_frame_buffer(void); void fill_frame_buffer(void); void display_frame_buffer(void); void set_timebase(void);

uint8_t oberes_display[4][8]; //vier bytes naast elkaar, acht onder elkaar

uint8_t unteres_display[4][8]; //deze twee samen vormen de frame-buffer

uint8_t Probenpuffer[32]; //Puffer voor de resultaten van de ADC

int main(void)

{LL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); MX_SPI1_Init(); MX_SPI2_Init(); MX_TIM3_Init(); MX_TIM4_Init();

LL_SPI_Enable(SPI1);

LL_SPI_Enable(SPI2);

LL_TIM_EnableCounter(TIM3);

LL_TIM_EnableCounter(TIM4);

LL_ADC_Enable(ADC1);

LL_ADC_REG_StartConversionSWStart(ADC1); LL_ADC_EnableIT_EOS(ADC1);

LL_mDelay(500); //MAX7219 braucht einige Zeit nach dem Einschalten

MAX7219_1_init(); MAX7219_2_init();

//LL_TIM_SetAutoReload (TIM3, 9);

während (1)

{ set_timebase(); delete_frame_buffer(); fill_frame_buffer(); display_frame_buffer(); } }

void delete_frame_buffer(void)

{int8_tx; int8_t j;

für (x = 0; x < 4; x++) //kolom_bytes {

für (y = 0; y < 8; y++) // lijnen {upper_display[x][y] = 0; //alle Bitjes op nul lower_display[x][y] = 0; } } }

void fill_frame_buffer(void)

{ uint8_t y = 0; // Spannung uint8_t tijd = 0; //tijd uint8_t display_byte; // Rosse 8 Bits naast elkaar en dat 4 mal öffnen lijn uint8_t display_bit;

für (tijd = 0; tijd < 32; tijd++) { display_byte = tijd / 8; display_bit = 7 – (tijd % 8);

y = Sample_Puffer[tijd];

if (y > 7) // im oberen Display schrijven

{ upper_display[display_byte][15-y] |= (1 << display_bit); aufrechtzuerhalten. Sonst // im unteren Display schrijven { Lower_display[display_byte][7-y] |= (1 << display_bit); } } }

void display_frame_buffer(void)

{

uint8_t j; //acht lijnen boven elkaar (pro Display) uint16_t yl; //Nummer für MAX7219

für (y = 0; y < 8; y++) {yl = (y + 1) << 8; //MAX7219 heeft lijnnummer in den oberen 8 Bits von 16 Bits woord

SPI2_send64((yl | oberes_display[0][y]), (yl | oberes_display[1][y]), (yl | oberes_display[2][y]), (yl | oberes_display[3][y]));

SPI1_send64((yl | unteres_display[0][y]), (yl | unteres_display[1][y]), (yl | unteres_display[2][y]), (yl | unteres_display[3][y])); }

}

void set_timebase(void)

{ uint8_t timebase_knop;

timebase_knop = LL_TIM_GetCounter(TIM4) / 2;

Schalter (timebase_knop)

{ Fall 0: LL_TIM_SetAutoReload(TIM3, 1999); brechen; Fall 1: LL_TIM_SetAutoReload(TIM3, 999); brechen; Fall 2: LL_TIM_SetAutoReload(TIM3, 499); brechen; Fall 3: LL_TIM_SetAutoReload(TIM3, 199); brechen; Fall 4: LL_TIM_SetAutoReload(TIM3, 99); brechen; Fall 5: LL_TIM_SetAutoReload(TIM3, 49); brechen; Fall 6: LL_TIM_SetAutoReload(TIM3, 19); brechen; Fall 7: LL_TIM_SetAutoReload(TIM3, 9); brechen; Fall 8: LL_TIM_SetAutoReload(TIM3, 4); brechen; Fall 9: LL_TIM_SetAutoReload(TIM3, 1); brechen;

Ursprünglich:

LL_TIM_SetAutoReload(TIM3, 99); brechen; } }

void MAX7219_1_init()

{ SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI1_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // Herunterfahren auf SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI1_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // Testmodus aus SPI1_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // Herunterfahren aus, Normalbetrieb SPI1_send64 (0x0900, 0x0900, 0x0900, 0x0900); //keine 7seg-Decodierung, 64 Pixel SPI1_send64(0x0A07, 0x0A07, 0x0A07, 0x0A07); // Intensität 50% SPI1_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); //alle Zeilen ein}

void MAX7219_2_init()

{ SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI2_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // Herunterfahren auf SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI2_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // Testmodus aus SPI2_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // Herunterfahren, Normalbetrieb SPI2_send64 (0x0900, 0x0900, 0x0900, 0x0900); //keine 7seg-Decodierung, 64 Pixel SPI2_send64(0x0A07, 0x0A07, 0x0A07, 0x0A07); // Intensität 50% SPI2_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); //alle Zeilen ein}

uint16_t SPI1_send64(uint16_t data3, uint16_t data2, uint16_t data1, uint16_t data0)

{ LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_4);

LL_SPI_TransmitData16(SPI1, Daten3);

während (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}

LL_SPI_TransmitData16(SPI1, Daten2);

während (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}

LL_SPI_TransmitData16(SPI1, Daten1);

während (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}

LL_SPI_TransmitData16(SPI1, Daten0);

während (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) {}

LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_4);

LL_SPI_ReceiveData16(SPI1) zurückgeben; }

uint16_t SPI2_send64(uint16_t data3, uint16_t data2, uint16_t data1, uint16_t data0)

{ LL_GPIO_ResetOutputPin (GPIOB, LL_GPIO_PIN_12);

LL_SPI_TransmitData16(SPI2, Daten3);

während (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}

LL_SPI_TransmitData16(SPI2, Daten2);

während (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}

LL_SPI_TransmitData16(SPI2, Daten1);

während (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}

LL_SPI_TransmitData16(SPI2, Daten0);

während (LL_SPI_IsActiveFlag_BSY(SPI2) == 1) {}

LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_12);

LL_SPI_ReceiveData16(SPI2) zurückgeben; }

void ADC1_2_IRQHandler(void)

{ statisch uint8_t sample_counter; uint8_t-Trigger; statisch uint8_t previous_trigger;

if (LL_ADC_IsActiveFlag_EOS(ADC1) != RESET)

{ if (sample_counter <32) {sample_buffer[sample_counter] = LL_ADC_REG_ReadConversionData32(ADC1) / 256; if (sample_counter < 32) sample_counter++; sonst sample_counter = 0; aufrechtzuerhalten. Sonst { Trigger = LL_ADC_REG_ReadConversionData32 (ADC1) / 256;

if ((trigger == 7) && (vorheriger_trigger < trigger)) //gaat niet helemaal goed bij blokgolven… {sample_counter = 0; } previous_trigger = Trigger; }

LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_13);

LL_ADC_ClearFlag_EOS(ADC1);

} }

statisch leer LL_Init(void)

{ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO); LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);

NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

NVIC_SetPriority(MemoryManagement_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(BusFault_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(UsageFault_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(SVCall_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(DebugMonitor_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(PendSV_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));

LL_GPIO_AF_Remap_SWJ_NOJTAG();

}

void SystemClock_Config(void)

{ LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) Error_Handler(); LL_RCC_HSE_Enable(); while(LL_RCC_HSE_IsReady() != 1); LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE_DIV_1, LL_RCC_PLL_MUL_9); LL_RCC_PLL_Enable(); while(LL_RCC_PLL_IsReady() != 1); LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2); LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL); LL_Init1msTick(7200000); LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); LL_SetSystemCoreClock(7200000); LL_RCC_SetADCLockSource(LL_RCC_ADC_CLKSRC_PCLK2_DIV_6);

NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));

}

statisches Leerzeichen MX_ADC1_Init(void)

{ LL_ADC_InitTypeDef ADC_InitStruct; LL_ADC_CommonInitTypeDef ADC_CommonInitStruct; LL_ADC_REG_InitTypeDef ADC_REG_InitStruct; LL_GPIO_InitTypeDef GPIO_InitStruct;

LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC1);

GPIO_InitStruct. Pin = LL_GPIO_PIN_0;

GPIO_InitStruct. Mode = LL_GPIO_MODE_ANALOG; LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

NVIC_SetPriority(ADC1_2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));

NVIC_EnableIRQ(ADC1_2_IRQn);

ADC_InitStruct. DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;

ADC_InitStruct. SequencersScanMode = LL_ADC_SEQ_SCAN_DISABLE; LL_ADC_Init(ADC1, &ADC_InitStruct);

ADC_CommonInitStruct. Multimode = LL_ADC_MULTI_INDEPENDENT;

LL_ADC_CommonInit(_LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct);

ADC_REG_InitStruct. TriggerSource = LL_ADC_REG_TRIG_EXT_TIM3_TRGO;

ADC_REG_InitStruct. SequencerLength = 1; ADC_REG_InitStruct. SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE; ADC_REG_InitStruct. ContinuousMode = LL_ADC_REG_CONV_SINGLE; ADC_REG_InitStruct. DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE; LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);

LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_0, LL_ADC_SAMPLINGTIME_41CYCLES_5);

}

statisches Leerzeichen MX_SPI1_Init(void)

{ LL_SPI_InitTypeDef SPI_InitStruct; LL_GPIO_InitTypeDef GPIO_InitStruct;

LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);

GPIO_InitStruct. Pin = LL_GPIO_PIN_5|LL_GPIO_PIN_7;

GPIO_InitStruct. Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct. Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct. OutputType = LL_GPIO_OUTPUT_PUSHPULL; LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

//NVIC_SetPriority(SPI1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));

//NVIC_EnableIRQ(SPI1_IRQn);

SPI_InitStruct. TransferDirection = LL_SPI_FULL_DUPLEX;

SPI_InitStruct. Mode = LL_SPI_MODE_MASTER; SPI_InitStruct. DataWidth = LL_SPI_DATAWIDTH_16BIT; SPI_InitStruct. ClockPolarity = LL_SPI_POLARITY_LOW; SPI_InitStruct. ClockPhase = LL_SPI_PHASE_1EDGE; SPI_InitStruct. NSS = LL_SPI_NSS_SOFT; SPI_InitStruct. BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8; SPI_InitStruct. BitOrder = LL_SPI_MSB_FIRST; SPI_InitStruct. CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; SPI_InitStruct. CRCPoly = 10; LL_SPI_Init(SPI1, &SPI_InitStruct); }

statisches Leerzeichen MX_SPI2_Init(void)

{ LL_SPI_InitTypeDef SPI_InitStruct; LL_GPIO_InitTypeDef GPIO_InitStruct;

LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);

GPIO_InitStruct. Pin = LL_GPIO_PIN_13|LL_GPIO_PIN_15;

GPIO_InitStruct. Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct. Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct. OutputType = LL_GPIO_OUTPUT_PUSHPULL; LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

//NVIC_SetPriority(SPI2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));

//NVIC_EnableIRQ(SPI2_IRQn);

SPI_InitStruct. TransferDirection = LL_SPI_FULL_DUPLEX;

SPI_InitStruct. Mode = LL_SPI_MODE_MASTER; SPI_InitStruct. DataWidth = LL_SPI_DATAWIDTH_16BIT; SPI_InitStruct. ClockPolarity = LL_SPI_POLARITY_LOW; SPI_InitStruct. ClockPhase = LL_SPI_PHASE_1EDGE; SPI_InitStruct. NSS = LL_SPI_NSS_SOFT; SPI_InitStruct. BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4; SPI_InitStruct. BitOrder = LL_SPI_MSB_FIRST; SPI_InitStruct. CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; SPI_InitStruct. CRCPoly = 10; LL_SPI_Init(SPI2, &SPI_InitStruct); }

statisches Leerzeichen MX_TIM3_Init(void)

{ LL_TIM_InitTypeDef TIM_InitStruct;

LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);

TIM_InitStruct. Prescaler = 229;

TIM_InitStruct. CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct. Autoreload = 9; TIM_InitStruct. ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; LL_TIM_Init(TIM3, &TIM_InitStruct);

LL_TIM_DisableARRPreload(TIM3);

LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL); LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_UPDATE); LL_TIM_EnableMasterSlaveMode(TIM3); }

statisches Leerzeichen MX_TIM4_Init(void)

{ LL_TIM_InitTypeDef TIM_InitStruct; LL_GPIO_InitTypeDef GPIO_InitStruct;

LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM4);

GPIO_InitStruct. Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7;

GPIO_InitStruct. Mode = LL_GPIO_MODE_FLOATING; LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

LL_TIM_SetEncoderMode(TIM4, LL_TIM_ENCODERMODE_X2_TI1);

LL_TIM_IC_SetActiveInput(TIM4, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_DIRECTTI); LL_TIM_IC_SetPrescaler(TIM4, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1); LL_TIM_IC_SetFilter(TIM4, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1); LL_TIM_IC_SetPolarity(TIM4, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_RISING); LL_TIM_IC_SetActiveInput(TIM4, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI); LL_TIM_IC_SetPrescaler(TIM4, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1); LL_TIM_IC_SetFilter(TIM4, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1); LL_TIM_IC_SetPolarity(TIM4, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING);

TIM_InitStruct. Prescaler = 0;

TIM_InitStruct. CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct. Autoreload = 19; TIM_InitStruct. ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; LL_TIM_Init(TIM4, &TIM_InitStruct);

LL_TIM_DisableARRPreload(TIM4);

LL_TIM_SetTriggerOutput(TIM4, LL_TIM_TRGO_RESET); LL_TIM_DisableMasterSlaveMode(TIM4); }

statisches Leerzeichen MX_GPIO_Init(void)

{ LL_GPIO_InitTypeDef GPIO_InitStruct;

LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC);

LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOD); LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA); LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);

LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_13);

LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_4); LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_12);

GPIO_InitStruct. Pin = LL_GPIO_PIN_13;

GPIO_InitStruct. Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct. Speed = LL_GPIO_SPEED_FREQ_LOW; GPIO_InitStruct. OutputType = LL_GPIO_OUTPUT_PUSHPULL; LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

GPIO_InitStruct. Pin = LL_GPIO_PIN_4;

GPIO_InitStruct. Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct. Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct. OutputType = LL_GPIO_OUTPUT_PUSHPULL; LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct. Pin = LL_GPIO_PIN_12;

GPIO_InitStruct. Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct. Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct. OutputType = LL_GPIO_OUTPUT_PUSHPULL; LL_GPIO_Init(GPIOB, &GPIO_InitStruct); }

void _Error_Handler(char *file, int line)

{ während(1) { } }

#ifdef USE_FULL_ASSERT

void assert_failed(uint8_t* Datei, uint32_t Zeile)

{ } #endif