Vierbits oscilloscoop - Ajarnpa
Vierbits oscilloscoop - Ajarnpa
Anonim
Vier bits oscilloscoop
Vier bits oscilloscoop

Het is een leuk project om te zien hoe ver ik in snelheden een MAX7219 dot matrix-display zou kunnen duwen. En in plaats van hem het "levensspel" te laten spelen, besloot ik er een "scope" mee te maken. Zoals je uit de titel zult begrijpen, is dit geen vervanging voor een echte oscilloscoop:-).

Aangezien ik niet van plan ben dit op een serieuze manier te gebruiken, zal ik er geen printplaat voor maken. Misschien, heel misschien zet ik het op een perf-board, maar voor nu is en blijft het op een breadboard. Ook is er geen ingangsversterker/verzwakker, je moet een signaal leveren tussen 0 en 3,3V, ga niet negatief of hoger dan 3,3V omdat je de microcontroller kunt beschadigen.

Stap 1: Hardware

Hardware
Hardware
Hardware
Hardware
Hardware
Hardware

Het is goedkoop, heel goedkoop als je de onderdelen in China koopt via ebay of vergelijkbare sites. Het maakt gebruik van een STM32F103C8-ontwikkelbord, soms een "blauwe pil" genoemd die ik voor ongeveer 2 euro heb gekocht (of USD, ze zijn bijna dezelfde waarde, eind 2018), twee 8x8x4 dot-matrix-schermen met MAX7219-chips erop, gekocht voor 5 euro per stuk en een encoder van ongeveer 1 euro.

Natuurlijk is een voeding nodig die 3,3V levert bij een paar honderd milliampère. De spanningsregelaar op het ontwikkelbord STM32F103C8 wordt niet gebruikt, deze kan niet genoeg stroom leveren voor de displays. De datasheet voor de MAX7219 specificeert dat de bedrijfsvoedingsspanning tussen 4,0 en 5,5V moet zijn, maar het werkt prima op 3,3V, misschien niet als je het in een zeer warme of koude omgeving gebruikt, maar bij 20 Celsius is het prima. En nu hoef ik geen level-converters tussen de microcontroller en de displayboards te gebruiken.

Stap 2: Bouwen

Bouwen
Bouwen
Bouwen
Bouwen
Bouwen
Bouwen

Als je naar de foto kijkt, zie je misschien dat ik de stroomkabels op de breadboards op een niet-conventionele manier gebruik, beide lijnen bovenaan zijn de positieve rail en beide aan de onderkant zijn de grondrail. Het is de manier waarop ik het gewend ben en het werkt goed, het laat de opstelling een beetje meer lijken op de schema's die ik teken. Ik heb ook veel kleine borden gemaakt met onderdelen die ik op het breadboard kan aansluiten om dingen te versnellen en ze zijn allemaal geconfigureerd om de twee bovenste lijnen als positief en de onderste lijnen als grond te gebruiken. Zoals ik al zei, de resolutie is 4 bit (16 niveaus), en aangezien er 4x8 leds naast elkaar zijn, zijn er slechts 32 sample points (pts). Vergelijk dat eens met een Rigol Rigol DS1054Z (8 bit en 12Mpts) en je zult zien dat dit nauwelijks speelgoed is. Wat de daadwerkelijke bandbreedte is weet ik niet, ik heb het getest tot 10kHz en dat werkt prima.

Stap 3: Programma's

Programma's
Programma's
Programma's
Programma's
Programma's
Programma's
Programma's
Programma's

De IDE die ik gebruik is Atollic TrueStudio die vanaf begin dit jaar (2018) is aangenomen door ST Micro Electronics en gratis beschikbaar is, geen tijdslimiet, geen limiet voor de codegrootte, geen zeurende schermen. Daarbij gebruik ik STM32CubeMX, een programma dat mij de startcode levert en de initialisatie van alle randapparatuur genereert. En het heeft een weergave van alle pinnen van de microcontroller en hun gebruik. Zelfs als je STM32CubeMX niet gebruikt voor het genereren van code, is dit erg handig. Een ding dat ik niet leuk vind, is de zogenaamde HAL, de standaard van STM32CubeMX. Ik geef de voorkeur aan de LowLayer werkwijze.

Voor het programmeren van de microcontroller gebruik ik ofwel de ST-Link programmer/debugger van ST Micro Electronics of de J-Link van Segger. Beide toestellen zijn niet gratis, al kun je er voor een paar euro wel Chinese exemplaren van kopen.

Stap 4: Over de code

De MAX7219's adresseren de LED's op wat ik een horizontale manier noem, 8 LED's naast elkaar. Voor een oscilloscoop zouden 8 LED's op elkaar makkelijker zijn geweest, dus heb ik een simpele frame-buffer gemaakt waar op een verticale manier met data naar wordt geschreven, en op de gewenste horizontale manier wordt uitgelezen. De MAX7219 gebruikt een 16bit-code per 8 LED's, waarbij de eerste byte wordt gebruikt om de geselecteerde regel te adresseren. En aangezien er vier van deze modules naast elkaar zijn gestapeld, met hun ingangen aangesloten op de uitgangen van de module ervoor, moet je die 16 bits vier keer verzenden om de laatste module te bereiken. (Ik hoop dat ik dingen duidelijk maak…) De gegevens worden naar de MAX7219 gestuurd met behulp van SPI, een eenvoudig maar zeer snel protocol. Dit is waar ik mee aan het experimenteren was, hoe snel kun je gaan bij het verzenden van de gegevens naar de MAX7219. Uiteindelijk schakelde ik terug naar 9 MHz net onder de maximale snelheid die de datasheet aangeeft.

Ik gebruik twee van de vier beschikbare timers van de STM32F103C8, één voor het genereren van de tijdbasis en de andere voor het uitlezen van de roterende encoder, die de tijdbasis instelt. TIMER3 genereert de tijdbasis, het doet dit door de klok te delen door 230 en de teller elke 3,2 u bij te werken. Schakel de roterende encoder die u kunt selecteren om de teller te laten tellen van 2 klokpulsen tot 2000 klokpulsen. Stel dat u 100 kiest. TIMER3 genereert dan elke 320 us een EVENT. Deze GEBEURTENIS triggert de ADC om een sample van het ingangssignaal op te nemen, en aangezien er 32 samples zijn om voor één scherm te nemen, zal dit na ongeveer. 10 mS. In 10 mS kun je één golflengte van 100 Hz passen, of twee van 200 Hz, enzovoort. Als u over 3 golven per scherm gaat, is het echter nogal moeilijk om de golfvorm te herkennen.

Voor de rest kan ik je alleen maar verwijzen naar de code, het is ook niet moeilijk te volgen als je maar wat ervaring hebt met een Arduino. In feite zou je hetzelfde kunnen maken met een Arduino, hoewel ik betwijfel of het zo snel zou werken als een "blauwe pil". De STM32F103C8 is een 32-bits microcontroller die draait op 72 MHz, heeft twee SPI-randapparatuur en een zeer snelle ADC.

Stap 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_cortex.h" #include "stm32futils.h" 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_3 ((uend_0000000)

#ifdef _cplusplus

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

#define Error_Handler() _Error_Handler(_FILE_, _LINE_)

#ifdef _cplusplus } #endif

#stop als

Stap 6: Hoofd.c

#include "main.h" static void LL_Init(void); void SystemClock_Config (ongeldig); statische leegte MX_GPIO_Init (ongeldig); statische leegte MX_ADC1_Init (ongeldig); statische leegte MX_SPI1_Init (ongeldig); statische leegte MX_SPI2_Init (ongeldig); statische leegte MX_TIM3_Init (ongeldig); statische leegte MX_TIM4_Init (ongeldig);

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); ongeldig MAX7219_1_init(); ongeldig MAX7219_2_init(); void erase_frame_buffer (ongeldig); void fill_frame_buffer (void); ongeldig display_frame_buffer (ongeldig); void set_timebase (void);

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

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

uint8_t sample_buffer[32]; //buffer voor de resultaten van de ADC

int hoofd(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_Inschakelen (SPI1);

LL_SPI_Inschakelen (SPI2);

LL_TIM_EnableCounter(TIM3);

LL_TIM_EnableCounter(TIM4);

LL_ADC_Inschakelen (ADC1);

LL_ADC_REG_StartConversieSWStart(ADC1); LL_ADC_EnableIT_EOS(ADC1);

LL_mVertraging (500); //MAX7219 heeft wat tijd nodig na het inschakelen

MAX7219_1_init(); MAX7219_2_init();

//LL_TIM_SetAutoReload(TIM3, 9);

terwijl (1)

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

void erase_frame_buffer (ongeldig)

{ int8_t x; int8_t y;

voor (x = 0; x < 4; x++) //kolom_bytes {

for (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; //spanning uint8_t tijd = 0; //tijd uint8_t display_byte; //steeds 8 bits naast elkaar en dat 4 maal op een lijn uint8_t display_bit;

for (tijd = 0; tijd < 32; tijd++) { display_byte = tijd / 8; display_bit = 7 - (tijd % 8);

y = voorbeeld_buffer[tijd];

if (y > 7) //in bovenste display schrijven

{ upper_display[display_byte][15-y] |= (1 << display_bit); } else //in lower display schrijven { lower_display[display_byte][7-y] |= (1 << display_bit); } } }

ongeldig display_frame_buffer (ongeldig)

{

uint8_t y; //acht lijnen boven elkaar (per display) uint16_t yl; //lijnnummer voor de MAX7219

voor (y = 0; y < 8; y++) { yl = (y+1) << 8; //MAX7219 heeft lijnnummer in de bovenste 8 bits van 16 bits woord

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

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

}

void set_timebase(void)

{ uint8_t tijdbasis_knop;

timebase_knop = LL_TIM_GetCounter(TIM4) / 2;

schakelaar (timebase_knop)

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

standaard:

LL_TIM_SetAutoReload(TIM3, 99); pauze; } }

ongeldig MAX7219_1_init()

{ SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI1_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // afsluiten op SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI1_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // testmode uit SPI1_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // uitschakeling, normale werking SPI1_send64 (0x0900, 0x0900, 0x0900, 0x0900); // geen 7seg-decodering, 64 pixels SPI1_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // intensiteit 50% SPI1_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // alle rijen op }

ongeldig MAX7219_2_init()

{SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI2_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // afsluiten op SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI2_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // testmodus uit SPI2_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // uitschakeling, normale werking SPI2_send64 (0x0900, 0x0900, 0x0900, 0x0900); // geen 7seg-decodering, 64 pixels SPI2_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // intensiteit 50% SPI2_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // alle rijen op }

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, data3);

terwijl (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}

LL_SPI_TransmitData16(SPI1, data2);

terwijl (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}

LL_SPI_TransmitData16(SPI1, data1);

terwijl (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}

LL_SPI_TransmitData16(SPI1, data0);

terwijl (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) {}

LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_4);

retourneer LL_SPI_ReceiveData16 (SPI1); }

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, data3);

terwijl (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}

LL_SPI_TransmitData16(SPI2, data2);

terwijl (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}

LL_SPI_TransmitData16(SPI2, data1);

terwijl (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}

LL_SPI_TransmitData16(SPI2, data0);

terwijl (LL_SPI_IsActiveFlag_BSY(SPI2) == 1) {}

LL_GPIO_SetOutputPin (GPIOB, LL_GPIO_PIN_12);

retourneer LL_SPI_ReceiveData16 (SPI2); }

ongeldig ADC1_2_IRQHandler (ongeldig)

{ statische 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++; anders sample_counter = 0; } else {trigger = LL_ADC_REG_ReadConversionData32 (ADC1) / 256;

if ((trigger == 7) && (vorige_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);

} }

statische leegte 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(72000000); LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); LL_SetSystemCoreClock(72000000); LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSRC_PCLK2_DIV_6);

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

}

statische leegte MX_ADC1_Init (ongeldig)

{ 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);

}

statische leegte MX_SPI1_Init (ongeldig)

{ 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); }

statische leegte MX_SPI2_Init (ongeldig)

{ 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); }

statisch ongeldig MX_TIM3_Init(ongeldig)

{ 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); }

statisch ongeldig MX_TIM4_Init(ongeldig)

{ 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); }

statische ongeldig 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-regel)

{ terwijl(1) { } }

#ifdef USE_FULL_ASSERT

void assert_failed(uint8_t* bestand, uint32_t regel)

{ } #stop als