Table des matières:
- Étape 1: Matériel
- Étape 2: Construire
- Étape 3: Programmes
- Étape 4: À propos du Code
- Étape 5: Main.h
- Étape 6: Main.c
Vidéo: Oscilloscope à quatre bits : 6 étapes
2024 Auteur: John Day | [email protected]. Dernière modifié: 2024-01-30 09:08
C'est un projet amusant juste pour voir jusqu'où je pourrais pousser un affichage à matrice de points MAX7219. Et au lieu de lui faire exécuter le "jeu de la vie", j'ai décidé d'en faire un "scope". Comme vous le comprendrez d'après le titre, ce n'est pas un remplacement pour un vrai oscilloscope:-).
Comme je ne prévois pas de l'utiliser de manière sérieuse, je ne ferai pas de carte de circuit imprimé pour cela. Peut-être, juste peut-être que je vais le mettre sur une planche à découper, mais pour l'instant, il est et restera sur une planche à pain. De plus, il n'y a pas d'amplificateur/atténuateur d'entrée, vous devez fournir un signal entre 0 et 3,3 V, ne passez pas au négatif ou au-dessus de 3,3 V car vous pourriez endommager le microcontrôleur.
Étape 1: Matériel
C'est bon marché, très bon marché lorsque vous achetez les pièces en Chine via ebay ou des sites similaires. Il utilise une carte de développement STM32F103C8, parfois appelée "pilule bleue" que j'ai achetée pour environ 2 euros (ou USD, ils ont presque la même valeur, fin 2018), deux écrans matriciels 8x8x4 avec des puces MAX7219 dessus, achetés pour 5 euros la pièce et un encodeur rotatif d'environ 1 euro.
Il faut bien sûr une alimentation délivrant 3,3V à quelques centaines de milliampères. Le régulateur de tension de la carte de développement STM32F103C8 n'est pas utilisé, il ne peut pas fournir suffisamment de courant pour les écrans. La fiche technique du MAX7219 spécifie que la tension d'alimentation de fonctionnement doit être comprise entre 4,0 et 5,5 V, mais elle fonctionne bien sur 3,3 V, peut-être pas lorsque vous l'utilisez dans un environnement très chaud ou froid, mais à 20 Celsius, tout va bien. Et maintenant, je n'ai plus besoin d'utiliser de convertisseurs de niveau entre le microcontrôleur et les tableaux d'affichage.
Étape 2: Construire
Lorsque vous regardez la photo, vous pouvez voir que j'utilise les lignes électriques sur les maquettes d'une manière non conventionnelle, les deux lignes en haut sont le rail positif et les deux en bas sont le rail au sol. C'est la façon dont j'ai l'habitude de le faire et ça marche bien, ça fait que la configuration ressemble un peu plus aux schémas que je dessine. De plus, j'ai fait beaucoup de petites planches avec des pièces que je peux brancher sur la maquette pour accélérer les choses et elles sont toutes configurées pour utiliser les deux lignes supérieures comme positives et les lignes inférieures comme masse. Comme je l'ai dit, la résolution est de 4 bits (16 niveaux), et comme il y a 4x8 leds côte à côte, il n'y a que 32 points d'échantillonnage (pts). Comparez cela avec un Rigol Rigol DS1054Z (8 bits et 12Mpts) et vous verrez que ce n'est guère un jouet. Quelle est la bande passante réelle, je ne sais pas, je l'ai testée jusqu'à 10 kHz et cela fonctionne bien.
Étape 3: Programmes
L'IDE que j'utilise est Atollic TrueStudio qui, depuis le début de cette année (2018) a été adopté par ST Micro Electronics et est disponible gratuitement, sans limite de temps, sans limite de taille de code, sans écrans de rappel. Avec lui, j'utilise STM32CubeMX, un programme qui me fournit le code de démarrage et génère l'initialisation de tous les périphériques. Et il a un affichage de toutes les broches du microcontrôleur et de leur utilisation. Même si vous n'utilisez pas STM32CubeMX pour générer du code, c'est très pratique. Une chose que je n'aime pas est le soi-disant HAL qui est la valeur par défaut de STM32CubeMX. Je préfère la méthode de travail LowLayer.
Pour programmer le microcontrôleur, j'utilise soit le programmeur/débogueur ST-Link de ST Micro Electronics, soit le J-Link fabriqué par Segger. Ces deux appareils ne sont pas gratuits, bien que vous puissiez en acheter des copies chinoises pour quelques euros.
Étape 4: À propos du Code
Les MAX7219 adressent les LED de manière horizontale, 8 LED côte à côte. Pour un oscilloscope, 8 LED superposées auraient été plus faciles, j'ai donc créé un simple tampon de trame dans lequel les données sont écrites de manière verticale et lues de la manière horizontale requise. Le MAX7219 utilise un code de 16 bits par 8 LED, où le premier octet est utilisé pour adresser la ligne sélectionnée. Et comme il y a quatre de ces modules empilés les uns à côté des autres, avec leurs entrées connectées aux sorties du module précédent, vous devez envoyer ces 16 bits quatre fois pour atteindre le dernier module. (J'espère que je suis clair…) Les données sont envoyées au MAX7219 en utilisant SPI, un protocole simple mais très rapide. C'est ce que j'expérimentais, à quelle vitesse pouvez-vous envoyer les données au MAX7219. Au final, je suis revenu à 9 MHz juste en dessous de la vitesse maximale spécifiée dans la fiche technique.
J'utilise deux des quatre temporisateurs disponibles du STM32F103C8, un pour la génération de la base de temps et l'autre pour la lecture de l'encodeur rotatif, qui définit la base de temps. TIMER3 génère la base de temps, il le fait en divisant l'horloge par 230, en mettant à jour le compteur toutes les 3,2 uS. Utilisez l'encodeur rotatif que vous pouvez sélectionner pour que le compteur compte de 2 impulsions d'horloge jusqu'à 2000 impulsions d'horloge. Disons que vous choisissez 100. TIMER3 génère alors un EVENEMENT toutes les 320 uS. Cet EVENEMENT déclenche l'ADC pour enregistrer un échantillon du signal d'entrée, et comme il y a 32 échantillons à prendre pour un écran, cela se terminera après environ. 10 ms. En 10 mS, vous pouvez adapter une longueur d'onde de 100 Hz, ou deux de 200 Hz, et ainsi de suite. Dépasser 3 vagues par écran rend cependant assez difficile la reconnaissance de la forme d'onde.
Pour le reste, je ne peux que vous référer au code, il n'est pas difficile à suivre même si vous n'avez qu'une certaine expérience avec un Arduino. En fait, on pourrait faire la même chose avec un Arduino, même si je doute que ça marche aussi vite qu'une "pilule bleue". Le STM32F103C8 est un microcontrôleur 32 bits cadencé à 72 MHz, il possède deux périphériques SPI et un ADC très rapide.
Étape 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 ". inclure "stm32f1xx_ll_dma.h" #inclure "stm32f1xx_ll_spi.h" #inclure "stm32f1xx_ll_tim.h" #inclure "stm32f1xx.h" #inclure "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 #define NVROUIC_PRIORYP0000_2 ((uint32_t)0x00000005) #define #GROUIC_PRIOR32_PRIOR3
#ifdef _cplusplus
extern "C" { #endif void _Error_Handler(char *, int);
#define Error_Handler() _Error_Handler(_FILE_, _LINE_)
#ifdef _cplusplus } #endif
#fin si
Étape 6: Main.c
#include "main.h" static void LL_Init(void); void SystemClock_Config(void); vide statique MX_GPIO_Init(void); vide statique MX_ADC1_Init(void); vide statique MX_SPI1_Init(void); vide statique MX_SPI2_Init(void); vide statique MX_TIM3_Init(void); vide statique 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 effacer_frame_buffer(void); void fill_frame_buffer(void); void display_frame_buffer(void); void set_timebase(void);
uint8_t upper_display[4][8]; //vier octets 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 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 a besoin d'un certain temps après la mise sous tension
MAX7219_1_init(); MAX7219_2_init();
//LL_TIM_SetAutoReload(TIM3, 9);
tandis que (1)
{ set_timebase(); effacer_cadre_buffer(); fill_frame_buffer(); display_frame_buffer(); } }
void effacer_frame_buffer(void)
{ int8_t x; int8_t y;
pour (x = 0; x < 4; x++) //kolom_bytes {
pour (y = 0; y < 8; y++) //lijnen { upper_display[x][y] = 0; //tous les bits op nul lower_display[x][y] = 0; } } }
void fill_frame_buffer(void)
{ uint8_t y = 0; //tension 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 = tampon_échantillon[tijd];
if (y > 7) //dans l'affichage supérieur schrijven
{ upper_display[display_byte][15-y] |= (1 << display_bit); } else //dans l'affichage inférieur schrijven { lower_display[display_byte][7-y] |= (1 << display_bit); } } }
void display_frame_buffer(void)
{
uint8_t y; //acht lijnen boven elkaar (par écran) uint16_t yl; //lijnnummer voor de MAX7219
pour (y = 0; y < 8; y++) { yl = (y+1) << 8; //MAX7219 heeft lijnnummer dans le bois supérieur 8 bits et 16 bits
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 | affichage_inférieur[0][y]), (yl | affichage_inférieur[1][y]), (yl | affichage_inférieur[2][y]), (yl | affichage_inférieur[3][y])); }
}
void set_timebase(void)
{ uint8_t timebase_knop;
timebase_knop = LL_TIM_GetCounter (TIM4) / 2;
commutateur (timebase_knop)
{ cas 0: LL_TIM_SetAutoReload(TIM3, 1999); Pause; cas 1: LL_TIM_SetAutoReload(TIM3, 999); Pause; cas 2: LL_TIM_SetAutoReload(TIM3, 499); Pause; cas 3: LL_TIM_SetAutoReload(TIM3, 199); Pause; cas 4: LL_TIM_SetAutoReload(TIM3, 99); Pause; cas 5: LL_TIM_SetAutoReload(TIM3, 49); Pause; cas 6: LL_TIM_SetAutoReload(TIM3, 19); Pause; cas 7: LL_TIM_SetAutoReload(TIM3, 9); Pause; cas 8: LL_TIM_SetAutoReload(TIM3, 4); Pause; cas 9: LL_TIM_SetAutoReload(TIM3, 1); Pause;
défaut:
LL_TIM_SetAutoReload(TIM3, 99); Pause; } }
annuler MAX7219_1_init()
{ SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI1_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); //arrêt sur SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI1_send64(0x0F00, 0x0F00, 0x0F00, 0x0F00); //mode de test désactivé SPI1_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); //arrêt désactivé, fonctionnement normal SPI1_send64(0x0900, 0x0900, 0x0900, 0x0900); //pas de décodage 7seg, 64 pixels SPI1_send64(0x0A07, 0x0A07, 0x0A07, 0x0A07); //intensité 50% SPI1_send64(0x0B07, 0x0B07, 0x0B07, 0x0B07); //toutes les lignes sur }
annuler MAX7219_2_init()
{ SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI2_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); //arrêt sur SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nop SPI2_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); //mode de test désactivé SPI2_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); //arrêt désactivé, fonctionnement normal SPI2_send64(0x0900, 0x0900, 0x0900, 0x0900); // pas de décodage 7seg, 64 pixels SPI2_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); //intensité 50% SPI2_send64(0x0B07, 0x0B07, 0x0B07, 0x0B07); //toutes les lignes sur }
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, données3);
tandis que (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}
LL_SPI_TransmitData16(SPI1, données2);
tandis que (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}
LL_SPI_TransmitData16(SPI1, données1);
tandis que (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}
LL_SPI_TransmitData16(SPI1, données0);
tandis que (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) {}
LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_4);
renvoie 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, données3);
tandis que (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}
LL_SPI_TransmitData16(SPI2, données2);
tandis que (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}
LL_SPI_TransmitData16(SPI2, données1);
tandis que (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}
LL_SPI_TransmitData16(SPI2, données0);
tandis que (LL_SPI_IsActiveFlag_BSY(SPI2) == 1) {}
LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_12);
renvoie LL_SPI_ReceiveData16(SPI2); }
void ADC1_2_IRQHandler(void)
{ static uint8_t sample_counter; déclencheur uint8_t; statique uint8_t previous_trigger;
si (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++; sinon sample_counter = 0; } else { trigger = LL_ADC_REG_ReadConversionData32(ADC1) / 256;
if ((trigger == 7) && (previous_trigger < trigger)) //gaat niet helemaal goed bij blokgolven… { sample_counter = 0; } previous_trigger = déclencheur; }
LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_13);
LL_ADC_ClearFlag_EOS(ADC1);
} }
vide statique 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));
}
vide statique 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);
}
vide statique 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); }
vide statique 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); }
vide statique 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); }
vide statique 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); }
vide statique 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)
{ tandis que(1) { } }
#ifdef USE_FULL_ASSERT
void assert_failed (fichier uint8_t*, ligne uint32_t)
{ } #fin si
Conseillé:
Tutoriel sur l'accéléromètre numérique Arduino Nano - MMA8452Q 3 axes 12 bits/8 bits : 4 étapes
Tutoriel sur l'accéléromètre numérique à 3 axes 12 bits/8 bits Arduino Nano - MMA8452Q : Le MMA8452Q est un accéléromètre intelligent, à faible consommation, à trois axes, capacitif et micro-usiné avec une résolution de 12 bits. Des options flexibles programmables par l'utilisateur sont fournies à l'aide de fonctions intégrées dans l'accéléromètre, configurables à deux interruptions
Tutoriel Python de l'accéléromètre numérique à 3 axes 12 bits/8 bits Raspberry Pi MMA8452Q : 4 étapes
Tutoriel Python pour l'accéléromètre numérique à 3 axes 12 bits/8 bits Raspberry Pi MMA8452Q : Le MMA8452Q est un accéléromètre intelligent, à faible consommation, à trois axes, capacitif et micro-usiné avec une résolution de 12 bits. Des options flexibles programmables par l'utilisateur sont fournies à l'aide de fonctions intégrées dans l'accéléromètre, configurables à deux interruptions
Tutoriel Java de l'accéléromètre numérique à 3 axes 12 bits/8 bits Raspberry Pi MMA8452Q : 4 étapes
Tutoriel Java de l'accéléromètre numérique à 3 axes 12 bits/8 bits Raspberry Pi MMA8452Q : Le MMA8452Q est un accéléromètre intelligent, à faible consommation, à trois axes, capacitif et micro-usiné avec une résolution de 12 bits. Des options flexibles programmables par l'utilisateur sont fournies à l'aide de fonctions intégrées dans l'accéléromètre, configurables à deux interruptions
DIY MusiLED, LED synchronisées avec la musique avec une application Windows et Linux en un clic (32 bits et 64 bits). Facile à recréer, facile à utiliser, facile à porter. : 3 étapes
DIY MusiLED, LED synchronisées avec la musique avec une application Windows et Linux en un clic (32 bits et 64 bits). Facile à recréer, facile à utiliser, facile à porter. : Ce projet vous aidera à connecter 18 LED (6 rouges + 6 bleues + 6 jaunes) à votre carte Arduino et analyser les signaux en temps réel de la carte son de votre ordinateur et les relayer à les leds pour les éclairer selon les effets de beat (Snare, High Hat, Kick)
Comment faire une vidéo en écran partagé en quatre étapes : 4 étapes (avec photos)
Comment faire une vidéo en écran partagé en quatre étapes : Nous voyons souvent une même personne dans une scène deux fois dans une pièce de théâtre. Et à notre connaissance, l'acteur n'a pas de frère jumeau. Nous avons également observé que deux vidéos de chant sont affichées sur un même écran pour comparer leurs compétences en chant. C'est le pouvoir de spl