Mục lục:

Máy hiện sóng bốn bit: 6 bước
Máy hiện sóng bốn bit: 6 bước

Video: Máy hiện sóng bốn bit: 6 bước

Video: Máy hiện sóng bốn bit: 6 bước
Video: Hướng dẫn sử dụng máy hiện sóng đo tín hiệu điện cơ bản 2024, Tháng mười một
Anonim
Máy hiện sóng bốn bit
Máy hiện sóng bốn bit

Đó là một dự án thú vị chỉ để xem tôi có thể đẩy một màn hình ma trận điểm MAX7219 đi bao xa. Và thay vì để nó chạy "trò chơi của cuộc sống", tôi quyết định tạo một "phạm vi" với nó. Như bạn sẽ hiểu từ tiêu đề, đây không phải là sự thay thế cho một máy hiện sóng thực sự:-).

Vì tôi không có kế hoạch sử dụng nó theo bất kỳ cách nghiêm túc nào nên tôi sẽ không làm bảng mạch in cho nó. Có lẽ, chỉ có thể tôi sẽ đặt nó trên một bảng điều khiển nhưng hiện tại thì nó đang và sẽ ở lại, trên một bảng mạch. Ngoài ra, không có bộ khuếch đại / bộ suy giảm đầu vào, bạn phải cung cấp tín hiệu từ 0 đến 3,3V, không đi âm hoặc quá 3,3V vì bạn có thể làm hỏng bộ vi điều khiển.

Bước 1: Phần cứng

Phần cứng
Phần cứng
Phần cứng
Phần cứng
Phần cứng
Phần cứng

Nó là rẻ, rất rẻ khi bạn mua các bộ phận ở Trung Quốc thông qua ebay hoặc các trang web tương tự. Nó sử dụng bảng phát triển STM32F103C8, đôi khi được gọi là "viên thuốc màu xanh" mà tôi đã mua với giá khoảng 2 euro (hoặc USD, chúng gần như có giá trị như nhau, vào cuối năm 2018), hai màn hình ma trận điểm 8x8x4 với chip MAX7219 trên đó, được mua với giá 5 euro một chiếc và một bộ mã hóa vòng quay khoảng 1 euro.

Tất nhiên cần thiết là một nguồn điện cung cấp 3,3V ở mức vài trăm miliampe. Bộ điều chỉnh điện áp trên bảng phát triển STM32F103C8 không được sử dụng, nó không thể cung cấp đủ dòng điện cho các màn hình. Biểu dữ liệu cho MAX7219 chỉ định điện áp cung cấp hoạt động phải từ 4,0 đến 5,5V nhưng nó chạy tốt trên 3,3V, có lẽ không phải khi bạn sử dụng nó trong môi trường quá nóng hoặc quá lạnh, nhưng ở nhiệt độ 20 độ C là ổn. Và bây giờ tôi không phải sử dụng bộ chuyển đổi mức giữa bộ vi điều khiển và bảng hiển thị.

Bước 2: Xây dựng

Xây dựng
Xây dựng
Xây dựng
Xây dựng
Xây dựng
Xây dựng

Khi bạn nhìn vào hình ảnh, bạn có thể thấy rằng tôi sử dụng đường dây điện trên bảng mạch theo cách không thông thường, cả hai đường trên cùng là đường ray dương và cả hai đường dưới cùng là đường sắt nối đất. Đó là cách tôi đã từng làm và nó hoạt động tốt, nó làm cho việc thiết lập trông giống với sơ đồ tôi vẽ hơn một chút. Ngoài ra, tôi đã làm rất nhiều bảng nhỏ với các bộ phận trên đó tôi có thể cắm vào bảng mạch để tăng tốc mọi thứ và tất cả chúng đều được cấu hình để sử dụng hai dòng trên cùng là dương và các dòng dưới là mặt đất. Như tôi đã nói, độ phân giải là 4 bit (16 mức) và vì có đèn led 4x8 cạnh nhau nên chỉ có 32 điểm mẫu (pts). So sánh với Rigol Rigol DS1054Z (8 bit và 12Mpts) và bạn sẽ thấy rằng đây không phải là một món đồ chơi. Tôi không biết băng thông thực tế là bao nhiêu, tôi đã thử nghiệm nó lên đến 10kHz và hoạt động tốt.

Bước 3: Chương trình

Các chương trình
Các chương trình
Các chương trình
Các chương trình
Các chương trình
Các chương trình
Các chương trình
Các chương trình

IDE tôi sử dụng là Atollic TrueStudio, tính đến đầu năm nay (2018) đã được ST Micro Electronics thông qua và có sẵn miễn phí, không giới hạn thời gian, không giới hạn kích thước mã, không có màn hình khó hiểu. Cùng với nó, tôi sử dụng STM32CubeMX, một chương trình cung cấp cho tôi mã bắt đầu và tạo ra quá trình khởi tạo tất cả các thiết bị ngoại vi. Và nó có một màn hình hiển thị tất cả các chân của bộ vi điều khiển và công dụng của chúng. Ngay cả khi bạn không sử dụng STM32CubeMX để tạo mã thì điều này cũng rất tiện dụng. Một điều tôi không thích là cái gọi là HAL là mặc định của STM32CubeMX. Tôi thích phương pháp làm việc LowLayer hơn.

Để lập trình vi điều khiển, tôi sử dụng trình gỡ lỗi / lập trình ST-Link của ST Micro Electronics hoặc J-Link do Segger tạo ra. Cả hai thiết bị này đều không miễn phí, mặc dù bạn có thể mua bản sao tiếng Trung của chúng với giá vài euro.

Bước 4: Giới thiệu về mã

MAX7219 giải quyết các đèn LED theo kiểu tôi gọi là kiểu nằm ngang, 8 đèn LED cạnh nhau. Đối với máy hiện sóng 8 đèn LED sẽ dễ dàng hơn, vì vậy tôi đã tạo một bộ đệm khung đơn giản được ghi vào dữ liệu theo chiều dọc và đọc ra theo chiều ngang cần thiết. MAX7219 sử dụng mã 16 bit trên 8 đèn LED, trong đó byte đầu tiên được sử dụng để đánh địa chỉ dòng đã chọn. Và vì có bốn trong số các mô-đun này xếp chồng lên nhau, với đầu vào của chúng được kết nối với đầu ra của mô-đun trước nó, bạn phải gửi 16bits đó bốn lần để đến được mô-đun cuối cùng. (Tôi hy vọng tôi đang làm mọi thứ rõ ràng…) Dữ liệu được gửi tới MAX7219 bằng SPI, một giao thức đơn giản nhưng rất nhanh. Đây là những gì tôi đang thử nghiệm, bạn có thể gửi dữ liệu đến MAX7219 nhanh đến mức nào. Cuối cùng, tôi đã chuyển trở lại 9 MHz ngay dưới tốc độ tối đa mà biểu dữ liệu chỉ định.

Tôi sử dụng hai trong số bốn bộ định thời có sẵn của STM32F103C8, một bộ để tạo cơ sở thời gian và bộ định thời còn lại để đọc ra bộ mã hóa quay, thiết lập cơ sở thời gian. TIMER3 tạo cơ sở thời gian, nó thực hiện điều đó bằng cách chia đồng hồ cho 230, cập nhật bộ đếm sau mỗi 3,2 uS. Phù hợp với bộ mã hóa quay mà bạn có thể chọn để có bộ đếm từ 2 xung đồng hồ lên đến 2000 xung đồng hồ. Giả sử bạn chọn 100. TIMER3 sau đó tạo SỰ KIỆN sau mỗi 320 uS. EVENT này kích hoạt ADC để ghi lại một mẫu tín hiệu đầu vào và vì đây là 32 mẫu cần lấy cho một lần sàng lọc, quá trình này sẽ hoàn tất sau khoảng thời gian. 10 mS. Trong 10mS, bạn có thể lắp một bước sóng 100 Hz hoặc hai bước sóng 200 Hz, v.v. Mặc dù vậy, việc trải qua 3 sóng trên mỗi màn hình làm cho nó khá khó để nhận ra dạng sóng.

Phần còn lại, tôi chỉ có thể giới thiệu cho bạn mã, không khó để làm theo ngay cả khi bạn chỉ có một số kinh nghiệm với Arduino. Trên thực tế, bạn có thể tạo ra điều tương tự với Arduino, mặc dù tôi nghi ngờ rằng nó sẽ hoạt động nhanh như một "viên thuốc màu xanh". STM32F103C8 là một vi điều khiển 32bit chạy ở tốc độ 72 MHz, nó có hai thiết bị ngoại vi SPI và một ADC rất nhanh.

Bước 5: Main.h

#ifndef _MAIN_H _ # xác định _MAIN_H_

#include "stm32f1xx_ll_adc.h"

#inch bao gồm "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

Bước 6: Main.c

#include "main.h" static void LL_Init (void); void SystemClock_Config (void); static void MX_GPIO_Init (void); static void MX_ADC1_Init (void); static void MX_SPI1_Init (void); static 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 (); void xóa_ khung_bộ đệm (void); void fill_frame_buffer (void); void display_frame_buffer (void); void set_timebase (void);

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

uint8_t hạ_trình [4] [8]; // deze twee samen vormen de frame-buffer

uint8_t sample_buffer [32]; // đệm 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 cần một khoảng thời gian sau khi bật nguồn

MAX7219_1_init (); MAX7219_2_init ();

// LL_TIM_SetAutoReload (TIM3, 9);

trong khi (1)

{set_timebase (); xóa_ khung_bộ đệm (); fill_frame_buffer (); display_frame_buffer (); }}

void xóa_frame_buffer (vô hiệu hóa)

{int8_t x; int8_t y;

for (x = 0; x <4; x ++) // kolom_byte {

for (y = 0; y <8; y ++) // lijnen {upper_display [x] [y] = 0; // alle bitjes op nul low_display [x] [y] = 0; }}}

void fill_frame_buffer (void)

{uint8_t y = 0; // điện áp uint8_t tijd = 0; // tijd uint8_t display_byte; // mã 8 bit 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 = sample_buffer [tijd];

if (y> 7) // trong hiển thị phía trên schrijven

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

void display_frame_buffer (void)

{

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

for (y = 0; y <8; y ++) {yl = (y + 1) << 8; // MAX7219 heeft lijnnummer trong de trên 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 | low_display [0] [y]), (yl | low_display [1] [y]), (yl | low_display [2] [y]), (yl | low_display [3] [y])); }

}

void set_timebase (void)

{uint8_t timebase_knop;

timebase_knop = LL_TIM_GetCounter (TIM4) / 2;

chuyển đổi (timebase_knop)

{case 0: LL_TIM_SetAutoReload (TIM3, 1999); nghỉ; trường hợp 1: LL_TIM_SetAutoReload (TIM3, 999); nghỉ; trường hợp 2: LL_TIM_SetAutoReload (TIM3, 499); nghỉ; trường hợp 3: LL_TIM_SetAutoReload (TIM3, 199); nghỉ; trường hợp 4: LL_TIM_SetAutoReload (TIM3, 99); nghỉ; trường hợp 5: LL_TIM_SetAutoReload (TIM3, 49); nghỉ; trường hợp 6: LL_TIM_SetAutoReload (TIM3, 19); nghỉ; trường hợp 7: LL_TIM_SetAutoReload (TIM3, 9); nghỉ; trường hợp 8: LL_TIM_SetAutoReload (TIM3, 4); nghỉ; trường hợp 9: LL_TIM_SetAutoReload (TIM3, 1); nghỉ;

vỡ nợ:

LL_TIM_SetAutoReload (TIM3, 99); nghỉ; }}

void MAX7219_1_init ()

{SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI1_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // tắt máy trên SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI1_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // tắt chế độ kiểm tra SPI1_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // tắt máy, hoạt động bình thường SPI1_send64 (0x0900, 0x0900, 0x0900, 0x0900); // không có giải mã 7seg, 64 pixel SPI1_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // cường độ 50% SPI1_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // tất cả các hàng trên}

void MAX7219_2_init ()

{SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI2_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // tắt máy trên SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI2_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // tắt chế độ kiểm tra SPI2_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // tắt máy, hoạt động bình thường SPI2_send64 (0x0900, 0x0900, 0x0900, 0x0900); // không có giải mã 7seg, 64 pixel SPI2_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // cường độ 50% SPI2_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // tất cả các hàng trên}

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

trong khi (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}

LL_SPI_TransmitData16 (SPI1, data2);

trong khi (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}

LL_SPI_TransmitData16 (SPI1, data1);

trong khi (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}

LL_SPI_TransmitData16 (SPI1, data0);

trong khi (LL_SPI_IsActiveFlag_BSY (SPI1) == 1) {}

LL_GPIO_SetOutputPin (GPIOA, LL_GPIO_PIN_4);

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

trong khi (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}

LL_SPI_TransmitData16 (SPI2, data2);

trong khi (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}

LL_SPI_TransmitData16 (SPI2, data1);

trong khi (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}

LL_SPI_TransmitData16 (SPI2, data0);

trong khi (LL_SPI_IsActiveFlag_BSY (SPI2) == 1) {}

LL_GPIO_SetOutputPin (GPIOB, LL_GPIO_PIN_12);

return LL_SPI_ReceiveData16 (SPI2); }

void ADC1_2_IRQHandler (void)

{static uint8_t sample_counter; trình kích hoạt uint8_t; static uint8_t before_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 ++; else sample_counter = 0; } else {trigger = LL_ADC_REG_ReadConversionData32 (ADC1) / 256;

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

LL_GPIO_TogglePin (GPIOC, LL_GPIO_PIN_13);

LL_ADC_ClearFlag_EOS (ADC1);

} }

static void LL_Init (void)

{LL_APB2_GRP1_EnableClock (LL_APB2_GRP1_PERIPH_AFIO); LL_APB1_GRP1_EnableClock (LL_APB1_GRP1_PERIPH_PWR);

NVIC_SetPosystemGrouping (NVIC_PRIORITYGROUP_4);

NVIC_SetPosystem (MemoryManagement_IRQn, NVIC_EncodePosystem (NVIC_GetPosystemGrouping (), 0, 0)); NVIC_SetPosystem (BusFault_IRQn, NVIC_EncodePooter (NVIC_GetPosystemGrouping (), 0, 0)); NVIC_SetPosystem (UsageFault_IRQn, NVIC_EncodePosystem (NVIC_GetPosystemGrouping (), 0, 0)); NVIC_SetPosystem (SVCall_IRQn, NVIC_EncodePosystem (NVIC_GetPosystemGrouping (), 0, 0)); NVIC_SetPosystem (DebugMonitor_IRQn, NVIC_EncodePooter (NVIC_GetPosystemGrouping (), 0, 0)); NVIC_SetPosystem (PendSV_IRQn, NVIC_EncodePooter (NVIC_GetPosystemGrouping (), 0, 0)); NVIC_SetPosystem (SysTick_IRQn, NVIC_EncodePooter (NVIC_GetPosystemGrouping (), 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_SetPosystem (SysTick_IRQn, NVIC_EncodePooter (NVIC_GetPosystemGrouping (), 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_SetPosystem (ADC1_2_IRQn, NVIC_EncodePosystem (NVIC_GetPosystemGrouping (), 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_SetPosystem (SPI1_IRQn, NVIC_EncodePosystem (NVIC_GetPosystemGrouping (), 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_SetPosystem (SPI2_IRQn, NVIC_EncodePosystem (NVIC_GetPosystemGrouping (), 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 (tệp char *, dòng int)

{trong khi (1) {}}

#ifdef USE_FULL_ASSERT

void khẳng định_failed (tệp uint8_t *, dòng uint32_t)

{} #endif

Đề xuất: