Оглавление:
- Шаг 1. Аппаратное обеспечение
- Шаг 2: сборка
- Шаг 3: Программы
- Шаг 4: О коде
- Шаг 5: Main.h
- Шаг 6: Main.c
Видео: Четырехбитный осциллограф: 6 шагов
2024 Автор: John Day | [email protected]. Последнее изменение: 2024-01-30 11:52
Это проект для развлечения, чтобы посмотреть, как далеко я смогу продвинуть матричный дисплей MAX7219 в скорости. И вместо того, чтобы запускать «игру жизни», я решил сделать из него «прицел». Как вы понимаете из названия, это не замена настоящему осциллографу:-).
Так как серьезно использовать это не планирую, то печатную плату делать не буду. Может, только на перфокарту поставлю, а пока он есть и останется на макетной плате. Также нет входного усилителя / аттенюатора, вы должны подавать сигнал от 0 до 3,3 В, не переходите в отрицательную зону или выше 3,3 В, так как вы можете повредить микроконтроллер.
Шаг 1. Аппаратное обеспечение
Это дешево, очень дешево, когда вы покупаете запчасти в Китае через ebay или аналогичные сайты. Он использует отладочную плату STM32F103C8, которую иногда называют «синей таблеткой», которую я купил примерно за 2 евро (или долларов США, стоимость почти такая же, на конец 2018 года), два точечно-матричных дисплея 8x8x4 с чипами MAX7219, купленные за 5 евро за штуку и датчик угла поворота около 1 евро.
Разумеется, необходим источник питания с напряжением 3,3 В и силой несколько сотен миллиампер. Стабилизатор напряжения на отладочной плате STM32F103C8 не используется, он не может обеспечить достаточный ток для дисплеев. В таблице данных MAX7219 указано, что рабочее напряжение питания должно быть от 4,0 до 5,5 В, но при 3,3 В он работает нормально, возможно, не при использовании в очень жаркой или холодной среде, но при 20 градусах Цельсия это нормально. И теперь мне не нужно использовать преобразователи уровней между микроконтроллером и дисплеями.
Шаг 2: сборка
Когда вы посмотрите на картинку, вы можете увидеть, что я использую линии питания на макетных платах нетрадиционным способом: обе линии вверху являются положительной шиной, а обе линии внизу - шиной заземления. Я привык так делать, и он хорошо работает, он делает установку немного больше похожей на схемы, которые я рисую. Кроме того, я сделал много небольших плат с деталями, которые я могу подключить к макетной плате для ускорения работы, и все они настроены на использование двух верхних линий в качестве положительных, а нижних линий в качестве заземления. Как я уже сказал, разрешение составляет 4 бита (16 уровней), а поскольку рядом расположены светодиоды 4x8, всего 32 точки отсчета (точки). Сравните это с Rigol Rigol DS1054Z (8 бит и 12 Мбит / с), и вы увидите, что это вряд ли игрушка. Какова реальная пропускная способность, я не знаю, я тестировал ее до 10 кГц, и она отлично работает.
Шаг 3: Программы
Я использую среду IDE Atollic TrueStudio, которая с начала этого года (2018) была принята ST Micro Electronics и доступна бесплатно, без ограничений по времени, без ограничений по размеру кода, без раздражающих экранов. Вместе с ним я использую STM32CubeMX, программу, которая предоставляет мне стартовый код и генерирует инициализацию всех периферийных устройств. И в нем есть отображение всех выводов микроконтроллера и их использования. Это очень удобно, даже если вы не используете STM32CubeMX для генерации кода. Одна вещь, которая мне не нравится, - это так называемый HAL, который используется по умолчанию для STM32CubeMX. Я предпочитаю метод работы LowLayer.
Для программирования микроконтроллера я использую либо программатор / отладчик ST-Link от ST Micro Electronics, либо J-Link производства Segger. Оба эти устройства не бесплатны, хотя вы можете купить их китайские копии за несколько евро.
Шаг 4: О коде
MAX7219 адресует светодиоды так, как я его называю, горизонтально, 8 светодиодов расположены рядом друг с другом. Для осциллографа было бы проще расположить 8 светодиодов друг над другом, поэтому я сделал простой буфер кадра, в который данные записываются вертикально, а считываются требуемым горизонтальным образом. MAX7219 использует 16-битный код на 8 светодиодов, где первый байт используется для адресации выбранной строки. И поскольку четыре из этих модулей расположены рядом друг с другом, а их входы подключены к выходам модуля перед ним, вы должны отправить эти 16 бит четыре раза, чтобы добраться до последнего модуля. (Надеюсь, я проясняю ситуацию…) Данные отправляются на MAX7219 с использованием SPI, простого, но очень быстрого протокола. Это то, с чем я экспериментировал, насколько быстро вы можете отправить данные на MAX7219. В конце концов, я снова переключился на 9 МГц, чуть ниже максимальной скорости, указанной в таблице данных.
Я использую два из четырех доступных таймеров STM32F103C8, один для генерации временной развертки, а другой для считывания поворотного энкодера, который устанавливает временную развертку. TIMER3 генерирует развертку времени, делит часы на 230, обновляя счетчик каждые 3,2 мкс. С помощью поворотного энкодера вы можете выбрать счетчик от 2 тактовых импульсов до 2000 тактовых импульсов. Допустим, вы выбрали 100. Затем TIMER3 генерирует СОБЫТИЕ каждые 320 мкс. Это СОБЫТИЕ запускает АЦП для записи выборки входного сигнала, и, поскольку необходимо взять 32 выборки для одного экрана, это завершится примерно через некоторое время. 10 мСм. В 10 мс вы можете уместить одну длину волны 100 Гц или две длины волны 200 Гц и так далее. Однако при превышении 3 волн на экране довольно сложно распознать форму волны.
В остальном я могу порекомендовать вам только код, его нетрудно следовать, даже если у вас есть лишь некоторый опыт работы с Arduino. Фактически, вы могли бы сделать то же самое с Arduino, хотя я сомневаюсь, что он будет работать так же быстро, как «синяя таблетка». STM32F103C8 - это 32-битный микроконтроллер, работающий на частоте 72 МГц, он имеет два периферийных устройства SPI и очень быстрый АЦП.
Шаг 5: Main.h
#ifndef _MAIN_H _ # определить _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_exti.h" #include "stm32f1xx_ll_fxxr.h" #include "stm32f1xx_ll_fixr.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 ((uint32_t) 0x00000004) #define NVIC_PRIORITYGROUP_4 ((uint32_t) 0x00000003) #endif
#ifdef _cplusplus
extern "C" {#endif void _Error_Handler (char *, int);
#define Error_Handler () _Error_Handler (_ FILE_, _LINE_)
#ifdef _cplusplus} #endif
#endif
Шаг 6: Main.c
#include "main.h" static void LL_Init (void); void SystemClock_Config (недействительно); статическая пустота MX_GPIO_Init (void); статическая пустота MX_ADC1_Init (void); статическая пустота MX_SPI1_Init (void); статическая пустота MX_SPI2_Init (void); static void MX_TIM3_Init (void); static void 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 (); недействительным erase_frame_buffer (недействительным); пусто fill_frame_buffer (недействительно); недействительным display_frame_buffer (недействительным); недействительным set_timebase (недействительным);
uint8_t upper_display [4] [8]; // vier bytes naast elkaar, acht onder elkaar
uint8_t lower_display [4] [8]; // Отменить ту же самую форму кадрового буфера
uint8_t sample_buffer [32]; // буфер для результирующего АЦП
int main (пусто)
{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 требуется некоторое время после включения
MAX7219_1_init (); MAX7219_2_init ();
// LL_TIM_SetAutoReload (TIM3, 9);
в то время как (1)
{set_timebase (); erase_frame_buffer (); fill_frame_buffer (); display_frame_buffer (); }}
недействительным erase_frame_buffer (недействительным)
{int8_t x; int8_t y;
for (x = 0; x <4; x ++) // kolom_bytes {
for (y = 0; y <8; y ++) // lijnen {upper_display [x] [y] = 0; // все биты не указаны lower_display [x] [y] = 0; }}}
пусто fill_frame_buffer (недействительно)
{uint8_t y = 0; // напряжение uint8_t tijd = 0; // tijd uint8_t display_byte; // скачет на 8 бит, если нет 4, чтобы он не работал uint8_t display_bit;
для (tijd = 0; tijd <32; tijd ++) {display_byte = tijd / 8; display_bit = 7 - (tijd% 8);
y = sample_buffer [tijd];
if (y> 7) // в верхнем дисплее schrijven
{upper_display [display_byte] [15-y] | = (1 << display_bit); } else // на нижнем дисплее схема {lower_display [display_byte] [7-y] | = (1 << display_bit); }}}
недействительным display_frame_buffer (недействительным)
{
uint8_t y; // ахт линен бовен элкаар (на дисплей) uint16_t yl; // lijnnummer voor de MAX7219
for (y = 0; y <8; y ++) {yl = (y + 1) << 8; // MAX7219 heeft lijnnummer in de upper 8 bit van 16 bit 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]) »; }
}
недействительным set_timebase (недействительным)
{uint8_t timebase_knop;
timebase_knop = LL_TIM_GetCounter (TIM4) / 2;
переключатель (timebase_knop)
{case 0: LL_TIM_SetAutoReload (TIM3, 1999); перерыв; случай 1: LL_TIM_SetAutoReload (TIM3, 999); перерыв; случай 2: LL_TIM_SetAutoReload (TIM3, 499); перерыв; случай 3: LL_TIM_SetAutoReload (TIM3, 199); перерыв; случай 4: LL_TIM_SetAutoReload (TIM3, 99); перерыв; случай 5: LL_TIM_SetAutoReload (TIM3, 49); перерыв; случай 6: LL_TIM_SetAutoReload (TIM3, 19); перерыв; случай 7: LL_TIM_SetAutoReload (TIM3, 9); перерыв; случай 8: LL_TIM_SetAutoReload (TIM3, 4); перерыв; случай 9: LL_TIM_SetAutoReload (TIM3, 1); перерыв;
дефолт:
LL_TIM_SetAutoReload (TIM3, 99); перерыв; }}
void MAX7219_1_init ()
{SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI1_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // завершение работы по SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI1_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // тестовый режим выключен SPI1_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // выключение выключено, нормальная работа SPI1_send64 (0x0900, 0x0900, 0x0900, 0x0900); // без декодирования 7seg, 64 пикселя SPI1_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // интенсивность 50% SPI1_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // все строки включены}
void MAX7219_2_init ()
{SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI2_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // выключение на SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI2_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // тестовый режим выключен SPI2_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // выключение выключено, нормальная работа SPI2_send64 (0x0900, 0x0900, 0x0900, 0x0900); // без декодирования 7seg, 64 пикселя SPI2_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // интенсивность 50% SPI2_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // все строки включены}
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);
в то время как (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, данные2);
в то время как (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, данные1);
в то время как (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, данные0);
в то время как (LL_SPI_IsActiveFlag_BSY (SPI1) == 1) {}
LL_GPIO_SetOutputPin (GPIOA, LL_GPIO_PIN_4);
вернуть 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, данные3);
в то время как (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, данные2);
в то время как (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, данные1);
в то время как (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, данные0);
в то время как (LL_SPI_IsActiveFlag_BSY (SPI2) == 1) {}
LL_GPIO_SetOutputPin (GPIOB, LL_GPIO_PIN_12);
вернуть LL_SPI_ReceiveData16 (SPI2); }
недействительным ADC1_2_IRQHandler (недействительным)
{статический uint8_t sample_counter; uint8_t trigger; статический uint8_t previous_trigger;
если (LL_ADC_IsActiveFlag_EOS (ADC1)! = СБРОС)
{если (sample_counter <32) {sample_buffer [sample_counter] = LL_ADC_REG_ReadConversionData32 (ADC1) / 256; if (sample_counter <32) sample_counter ++; иначе sample_counter = 0; } еще {триггер = LL_ADC_REG_ReadConversionData32 (ADC1) / 256;
if ((trigger == 7) && (previous_trigger <trigger)) // gaat niet helemaal goed bij blokgolven… {sample_counter = 0; } previous_trigger = триггер; }
LL_GPIO_TogglePin (GPIOC, LL_GPIO_PIN_13);
LL_ADC_ClearFlag_EOS (ADC1);
} }
статическая пустота LL_Init (недействительна)
{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 ();
}
недействительным SystemClock_Config (недействительным)
{LL_FLASH_SetLatency (LL_FLASH_LATENCY_2); если (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); пока (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));
}
static void 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);
}
static void 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); }
static void 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); }
static void 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); }
static void 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); }
static void 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 *, строка int)
{в то время как (1) {}}
#ifdef USE_FULL_ASSERT
void assert_failed (файл uint8_t *, строка uint32_t)
{} #endif
Рекомендуемые:
Осциллограф ЭЛТ с питанием от миниатюрной батареи: 7 шагов (с изображениями)
Осциллограф ЭЛТ с питанием от миниатюрной батареи: Здравствуйте! В этом руководстве я покажу вам, как сделать мини-осциллограф с ЭЛТ с питанием от батареи. Осциллограф - важный инструмент для работы с электроникой; вы можете видеть все сигналы, протекающие в цепи, и устранять неполадки
Осциллограф с двумя трассами: 11 шагов (с изображениями)
Осциллограф с двумя трассами: когда я собирал свой предыдущий мини-осциллограф, я хотел посмотреть, насколько хорошо я смогу заставить работать свой самый маленький микроконтроллер ARM STM32F030 (F030), и он отлично справился со своей задачей. В одном из комментариев было высказано предположение, что "Синяя таблетка" с STM32F103
Карманный визуализатор сигналов (карманный осциллограф): 10 шагов (с изображениями)
Карманный визуализатор сигналов (карманный осциллограф): Привет всем! Мы все делаем так много вещей каждый день. Для каждой работы нужны инструменты. Это для изготовления, измерения, отделки и т. Д. Таким образом, работникам электроники нужны такие инструменты, как паяльник, мультиметр, осциллограф и т. Д
Сделайте свой собственный осциллограф (Mini DSO) с помощью STC MCU легко: 9 шагов (с изображениями)
Легко создайте свой собственный осциллограф (Mini DSO) с помощью STC MCU: это простой осциллограф, созданный с помощью STC MCU. Вы можете использовать этот Mini DSO для наблюдения за формой сигнала. Интервал времени: 100 мсек-500 мс Диапазон напряжения: 0-30 В Режим рисования: вектор или точки
Мини-осциллограф своими руками: 13 шагов
Мини-осциллограф DIY: создайте этот небольшой осциллограф. Диапазон частот до 40 кГц (25 мкс в полноэкранном режиме) в 4 выбираемых диапазонах. Входное напряжение составляет от 50 мВ до 50 В в двух диапазонах. Коэффициент усиления регулируется от 1 до 100. Принимает входной сигнал переменного или постоянного тока. Автоматическое переключение