(not yet) 101 Rx Samples

本文详细介绍RxJS中的异步背景操作、观察者操作符、限制操作符等核心概念,并通过实例展示如何实现异步代码执行、并行执行及事件观察等功能。
(not yet) 101 Rx Samples

You!
Yes, you, the one who is still scratching their head trying to figure out this Rx thing.
As you learn and explore, please feel free add your own samples here, or tweak existing ones!
Anyone can (and should!) edit this page. (edit button is at the bottom right of each page)

Asynchronous Background Operations

Start - Run Code Asynchronously

var o = Observable.Start(() => { Console.WriteLine("Calculating..."); Thread.Sleep(3000); Console.WriteLine("Done."); });
o.First();   // subscribe and wait for completion of background operation

Run a method asynchronously on demand

Execute a long-running method asynchronously. The method does not start running until there is a subscriber. The method is started every time the observable is created and subscribed, so there could be more than one running at once.

// Synchronous operation
public DataType DoLongRunningOperation(string param)
{
    ...
}

public IObservable<DataType> LongRunningOperationAsync(string param)
{
    return Observable.CreateWithDisposable<DataType>(
        o => Observable.ToAsync(DoLongRunningOperation)(param).Subscribe(o)
    );
}

ForkJoin - Parallel Execution

var o = Observable.ForkJoin(
    Observable.Start(() => { Console.WriteLine("Executing 1st on Thread: {0}", Thread.CurrentThread.ManagedThreadId); return "Result A"; }),
    Observable.Start(() => { Console.WriteLine("Executing 2nd on Thread: {0}", Thread.CurrentThread.ManagedThreadId); return "Result B"; }),
    Observable.Start(() => { Console.WriteLine("Executing 3rd on Thread: {0}", Thread.CurrentThread.ManagedThreadId); return "Result C"; }) 
).Finally(() => Console.WriteLine("Done!"));

foreach (string r in o.First())
    Console.WriteLine(r);

Result
Executing 1st on Thread: 3
Executing 2nd on Thread: 4
Executing 3rd on Thread: 3
Done!
Result A
Result B
Result C
 
 
摘自:http://rxwiki.wikidot.com/101samples
main.c中代码: /* USER CODE BEGIN Header / /* @file : main.c @brief : Main program body @attention <h2><center>© Copyright (c) 2023 STMicroelectronics. All rights reserved. This software component is licensed by ST under BSD 3-Clause license, the “License”; You may not use this file except in compliance with the License. You may obtain a copy of the License at: opensource.org/licenses/BSD-3-Clause / / USER CODE END Header / / Includes ------------------------------------------------------------------*/ #include “main.h” #include “dma.h” #include “fatfs.h” #include “rtc.h” #include “sdmmc.h” #include “spi.h” #include “usart.h” #include “gpio.h” /* Private includes ----------------------------------------------------------/ / USER CODE BEGIN Includes / #include “stdio.h” #include “string.h” #include “ads1282.h” / USER CODE END Includes */ /* Private typedef -----------------------------------------------------------/ / USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------/ / USER CODE BEGIN PD / / USER CODE END PD */ /* Private macro -------------------------------------------------------------/ / USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ #define SYNC_PIN GPIO_PIN_5 #define SYNC_PORT GPIOB uint8_t Buffer_Tx[512] = {0}; uint8_t Buffer_Rx[512] = {0}; int if_cal; long int attribute((section(“.array”))) graphic_1[500]; long int attribute((section(“.array”))) graphic_2[500]; long int attribute((section(“.array”))) graphic_3[500]; unsigned int temp = 0x00; unsigned int tempx; volatile uint8_t data_ready = 0; uint8_t sd_card_available = 0; uint32_t data_collection_count = 0; // 定义工作缓冲区,使用固定大小替代FF_MAX_SS BYTE workBuffer[4096]; // 使用4KB作为工作缓冲区 /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------/ void SystemClock_Config(void); / USER CODE BEGIN PFP / void print_ads1282_data(void); uint8_t initialize_sd_card(void); void debug_ads1282_registers(void); void testSPI(void); void configure_ads1282_clock(void); void wait_for_clock_stabilization(void); void complete_ads1282_init(void); / USER CODE END PFP */ /* Private user code ---------------------------------------------------------/ / USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** @brief The application entry point. @retval int / int main(void) { / USER CODE BEGIN 1 / / USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_USART1_UART_Init(); MX_USART2_UART_Init(); MX_SDMMC1_SD_Init(); MX_FATFS_Init(); MX_SPI1_Init(); MX_RTC_Init(); /* USER CODE BEGIN 2 */ printf(“STM32 System Launched!\r\n”); printf(“Initializing peripherals…\r\n”); // 配置时钟 configure_ads1282_clock(); wait_for_clock_stabilization(); // 初始化SD卡 sd_card_available = initialize_sd_card(); if(sd_card_available) { printf(“SD Card initialized successfully!\r\n”); } else { printf(“SD Card initialization failed!\r\n”); } // 初始化ADS1282 printf(“Initializing ADS1282…\r\n”); complete_ads1282_init(); // 验证ADS1282状态 debug_ads1282_registers(); printf(“System initialization completed!\r\n”); /* USER CODE END 2 */ /* Infinite loop / / USER CODE BEGIN WHILE */ while (1) { testSPI(); // 如果收集了500个数据点,打印它们 if(data_ready) { printf("\r\n=== 500 Data Points Collected ===\r\n"); print_ads1282_data(); // 如果SD卡可用,保存到SD卡 if(sd_card_available) { // 这里可以添加SD卡保存代码 printf("Data saved to SD card.\r\n"); } data_ready = 0; data_collection_count++; printf("Collection cycle #%lu completed. Restarting...\r\n", data_collection_count); // 等待5秒再开始下一轮 HAL_Delay(5000); } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** @brief System Clock Configuration @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /** Initializes the RCC Oscillators according to the specified parameters in the RCC_OscInitStruct structure. / RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.LSIState = RCC_LSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 1; RCC_OscInitStruct.PLL.PLLN = 16; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /* Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART1 |RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_SDMMC1; PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2; PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1; PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; PeriphClkInit.Sdmmc1ClockSelection = RCC_SDMMC1CLKSOURCE_PLLSAI1; PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE; PeriphClkInit.PLLSAI1.PLLSAI1M = 1; PeriphClkInit.PLLSAI1.PLLSAI1N = 8; PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7; PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2; PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2; PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_48M2CLK; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } // 修改MCO配置为输出4.096MHz时钟给ADS1282 // 使用HSE(8.192MHz)的2分频得到4.096MHz HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_2); /** Configure the main internal regulator output voltage */ if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /** @brief Wait for ADS1282 clock stabilization */ void wait_for_clock_stabilization(void) { printf(“Waiting for ADS1282 clock stabilization…\r\n”); // ADS1282需要时钟稳定后才能响应命令 // 等待足够长的时间让时钟稳定 for(int i = 5; i > 0; i–) { printf(" %d seconds…\r\n", i); HAL_Delay(1000); } printf(“Clock stabilization wait completed.\r\n”); } void configure_ads1282_clock(void) { printf(“Configuring MCO for ADS1282 clock…\r\n”); // 启用GPIOA时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置PA8为MCO GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF0_MCO; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置MCO输出HSE的2分频(4.096MHz) HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_2); printf("MCO configured: PA8 outputting 4.096MHz clock for ADS1282\r\n"); printf("Please verify clock signal on PA8 with oscilloscope.\r\n"); } void complete_ads1282_init(void) { printf(“Starting complete ADS1282 initialization…\r\n”); // 1. 确保SYNC为高电平 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET); HAL_Delay(10); // 2. 发送复位命令 printf(" 1. Sending reset command... "); uint8_t reset_cmd = 0x06; HAL_SPI_Transmit(&hspi1, &reset_cmd, 1, 1000); HAL_Delay(500); // 延长复位等待时间 printf("Done\r\n"); // 3. 发送停止连续读取命令 printf(" 2. Stopping continuous read... "); uint8_t sdatac_cmd = 0x11; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); printf("Done\r\n"); // 4. 验证ID寄存器 printf(" 3. Reading ID register... "); uint8_t id_reg = 0; read_ADC_REG(0x00, 1, &id_reg); printf("ID = 0x%02X\r\n", id_reg); // 5. 配置寄存器 printf(" 4. Configuring registers... "); unsigned char config_data[2]; // CONFIG0: 脉冲同步,高分辨率模式,2000SPS,线性相位,SINC+LPF config_data[0] = 0xDF; // 2000SPS, 线性相位, SINC+LPF // CONFIG1: AINP1/AINN1输入,斩波使能,增益1 config_data[1] = 0x0F; // MUX选择AINP1/AINN1, 斩波使能, 增益1 write_ADC_REG(0x01, 2, config_data); HAL_Delay(10); printf("Done\r\n"); // 6. 验证配置 printf(" 5. Verifying configuration... "); unsigned char verify_data[2]; read_ADC_REG(0x01, 2, verify_data); printf("CONFIG0=0x%02X, CONFIG1=0x%02X\r\n", verify_data[0], verify_data[1]); // 7. 启动连续读取模式 printf(" 6. Starting continuous read... "); uint8_t rdatac_cmd = 0x10; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); printf("Done\r\n"); printf("Complete ADS1282 initialization finished.\r\n"); } /** @brief Debug function to read ADS1282 registers */ void debug_ads1282_registers(void) { printf(“Reading ADS1282 registers for verification…\r\n”); read_ADC_ALLREG(); printf(“Register values:\r\n”); for(int i = 0; i < 11; i++) { printf(" Reg[%d]: 0x%02X\r\n", i, adc_regdata[i]); } // 检查ID寄存器是否为预期值 if(adc_regdata[0] == 0x00) { printf(“WARNING: All registers read as 0x00 - SPI communication may be failing!\r\n”); printf(“Please check:\r\n”); printf(" 1. ADS1282 power supply\r\n"); printf(" 2. SPI connections (MOSI, MISO, SCLK, SYNC)\r\n"); printf(" 3. DRDY pin connection (PC1)\r\n"); printf(" 4. Reset pin state (should be high for normal operation)\r\n"); } else { printf(“ID Register value: 0x%02X (should typically be 0x12 for ADS1282)\r\n”, adc_regdata[0]); } printf(“ADS1282 register read completed.\r\n\r\n”); } /** @brief Print collected ADS1282 data */ void print_ads1282_data(void) { printf(“ADS1282 Collected Data (500 points):\r\n”); printf(“Index\tRaw Data\tFiltered Data\r\n”); printf(“-----\t--------\t-------------\r\n”); for(unsigned int i = 0; i < 500; i++) { printf(“%d\t%ld\t%ld\r\n”, i, graphic_1[i], graphic_3[i]); } printf(“=== End of Data ===\r\n\r\n”); } /** @brief Initialize SD Card with error handling */ uint8_t initialize_sd_card(void) { FRESULT fres; DSTATUS stat; printf(“\r\n=== SD Card Initialization ===\r\n”); // 1. SD Card Hardware Initialization printf(“1. SD Card Hardware Initialization:); stat = SD_Driver.disk_initialize(0); if(stat != RES_OK) { printf(“FAILED (Status: %d)\r\n”, stat); printf(” Please check:\r\n”); printf(" - SD card is inserted properly\r\n"); printf(" - SD card is not write-protected\r\n"); printf(" - SD card format is supported (FAT32 recommended)\r\n"); return 0; } printf(“SUCCESS\r\n”); // 2. File System Mount printf("2. File System Mount: "); fres = f_mount(&SDFatFS, SDPath, 1); if(fres != FR_OK) { printf(“FAILED (Error: %d)\r\n”, fres); // 提供特定错误信息 switch(fres) { case FR_NO_FILESYSTEM: printf(" No valid FAT filesystem found.\r\n"); printf(" Please format the SD card as FAT32.\r\n"); break; case FR_NOT_READY: printf(" Storage device not ready.\r\n"); printf(" Check SD card connection.\r\n"); break; case FR_DISK_ERR: printf(" Disk error occurred.\r\n"); printf(" Check SD card health.\r\n"); break; default: printf(" Unknown error.\r\n"); break; } // 尝试创建新的文件系统 printf(" Attempting to create new filesystem...\r\n"); fres = f_mkfs(SDPath, FM_FAT32, 0, workBuffer, sizeof(workBuffer)); if(fres == FR_OK) { printf(" New FAT32 filesystem created successfully!\r\n"); // 再次尝试挂载 fres = f_mount(&SDFatFS, SDPath, 1); if(fres == FR_OK) { printf(" Filesystem mounted successfully after format.\r\n"); } else { printf(" Mount failed after format (Error: %d)\r\n", fres); return 0; } } else { printf(" Format failed (Error: %d)\r\n", fres); printf(" Please format SD card on computer as FAT32 and try again.\r\n"); return 0; } } else { printf(“SUCCESS\r\n”); } // 3. 简单的文件写入测试 printf("3. File System Test: "); uint32_t byteswritten; char test_filename[] = “TEST.TXT”; char test_data[] = “STM32 SD Test OK!”; fres = f_open(&SDFile, test_filename, FA_CREATE_ALWAYS | FA_WRITE); if(fres == FR_OK) { fres = f_write(&SDFile, test_data, strlen(test_data), &byteswritten); if(fres == FR_OK) { f_sync(&SDFile); f_close(&SDFile); printf(“SUCCESS (%lu bytes written)\r\n”, byteswritten); printf(" Write test completed - file created successfully.\r\n"); } else { printf(“WRITE FAILED (Error: %d)\r\n”, fres); f_close(&SDFile); return 0; } } else { printf(“FILE OPEN FAILED (Error: %d)\r\n”, fres); if(fres == FR_INVALID_NAME) { printf(" Invalid filename format.\r\n"); printf(" Please use 8.3 format (max 8 chars + 3 char extension).\r\n"); printf(" Current filename: %s\r\n", test_filename); } return 0; } printf(“=== SD Card Initialization Completed Successfully ===\r\n\r\n”); return 1; } /** @brief Test SPI communication with ADS1282 */ void testSPI(void) { static uint32_t startup_time = 0; static uint8_t startup_done = 0; static uint32_t sample_count = 0; static uint32_t last_print_time = 0; if(!startup_done) { startup_time = HAL_GetTick(); startup_done = 1; last_print_time = startup_time; } // 在连续读取模式下,不需要发送命令,直接读取数据 GPIO_PinState drdy_state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1); if(drdy_state == GPIO_PIN_RESET) { // 数据就绪,读取4字节 unsigned long int temp_read_U = SPI_ReceiveData_4byte(); signed long int temp_read_S = (signed long int)temp_read_U; // 跳过前几个无效数据(ADS1282初始化后可能有垃圾数据) if(sample_count >= 2) { // 打印前10个有效样本用于验证 if(sample_count < 12) { printf("Sample %lu: Raw=0x%08lX, Signed=%ld\r\n", sample_count-2, temp_read_U, temp_read_S); } // 存储数据 if(temp < 500) { graphic_1[temp] = temp_read_S; graphic_2[temp] = graphic_1[temp]; // 应用简单滤波 if(temp > 0) { graphic_3[temp] = (graphic_3[temp-1] * 95 + temp_read_S * 5) / 100; } else { graphic_3[temp] = temp_read_S; } temp++; } } sample_count++; // 检查是否收集了500个点 if(temp >= 500) { data_ready = 1; temp = 0; } } // 每5秒打印一次状态(避免过多输出) uint32_t current_time = HAL_GetTick(); if(current_time - last_print_time > 5000) { if(sample_count < 2) { printf(“Waiting for initial data…\r\n”); } else if(temp == 0 && data_ready == 0) { printf(“Collecting data… (Total samples: %lu)\r\n”, sample_count-2); } last_print_time = current_time; } } /* USER CODE END 4 */ /** @brief This function is executed in case of error occurrence. @retval None / void Error_Handler(void) { / USER CODE BEGIN Error_Handler_Debug / / User can add his own implementation to report the HAL error return state / printf(“Error_Handler called!\r\n”); while(1) { } / USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** @brief Reports the name of the source file and the source line number where the assert_param error has occurred. @param file: pointer to the source file name @param line: assert_param error line source number @retval None */ void assert_failed(uint8_t file, uint32_t line) { / USER CODE BEGIN 6 / printf(“Wrong parameters value: file %s on line %d\r\n”, file, line); / USER CODE END 6 / } #endif / USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *END OF FILE/ ads1282.c中代码: #include “ads1282.h” #include “spi.h” #include “main.h” #include “stdio.h” /* array to save ADC configuration data */ unsigned char adc_regdata[11]; // 定义SYNC引脚 #define SYNC_PIN GPIO_PIN_5 #define SYNC_PORT GPIOB // 定义DRDY引脚 #define DRDY_PIN GPIO_PIN_1 #define DRDY_PORT GPIOC /**************************************************************************** Function Name : write_CMD * Description : write a byte to SPI then read a byte from SPI * Parameters : unsigned char CMD: command suppose to write * * Return Value : unsigned char Data received * ****************************************************************************/ unsigned char write_CMD(unsigned char CMD) { unsigned char received_data = 0; // 对于ADS1282,SYNC在发送命令时应保持高电平(除非特别要求) // ADS1282使用连续读取模式,不需要每次通信都拉低SYNC // 只有在特定命令如RDATA需要拉低SYNC if(CMD == ADC_RDATA) { HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); } /* Send command and receive data */ HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(&hspi1, &CMD, &received_data, 1, 1000); if(status != HAL_OK) { printf("SPI TransmitReceive error: %d\r\n", status); } if(CMD == ADC_RDATA) { HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); } return received_data; } /**************************************************************************** Function Name : read_ADC_REG * Description : read ADC internal register value * Parameters : unsigned int start_addr: address in ADC register * unsigned int length: length to be readed (byte) * unsigned char *rdptr: the received data to be * recorded to this array * Return Value : unsigned int number of data bytes yet to be received * ****************************************************************************/ void read_ADC_REG(unsigned int start_addr, unsigned int length, unsigned char *rdptr) { unsigned char command1; unsigned char command2; unsigned char dummy = 0xFF; /* 发送停止连续读取命令 */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); uint8_t sdatac_cmd = ADC_SDATAC; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); // 增加延迟 /* Send Read Register command */ command1 = 0x20 + (0x1F & start_addr); command2 = 0x00 + (0x1F & (length - 1)); /* 拉低SYNC */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); HAL_Delay(1); /* 发送命令1 */ HAL_SPI_Transmit(&hspi1, &command1, 1, 1000); /* 发送命令2 */ HAL_SPI_Transmit(&hspi1, &command2, 1, 1000); /* 等待一小段时间 */ HAL_Delay(1); /* 读取数据 */ for(unsigned int i = 0; i < length; i++) { HAL_SPI_TransmitReceive(&hspi1, &dummy, &rdptr[i], 1, 1000); } /* 释放SYNC */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); HAL_Delay(10); /* 重新启动连续读取模式 */ uint8_t rdatac_cmd = ADC_RDATAC; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); } /**************************************************************************** Function Name : write_ADC_REG * Description : write ADC internal register value * Parameters : unsigned int start_addr: address in ADC register * unsigned int length: the length of data * unsigned char *rdptr: the data to be transfered * recorded in this array * Return * ****************************************************************************/ void write_ADC_REG(unsigned int start_addr, unsigned int length, unsigned char *wtptr) { unsigned char command1; unsigned char command2; /* 发送停止连续读取命令 */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); uint8_t sdatac_cmd = ADC_SDATAC; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); /* Send Write Register command */ command1 = 0x40 + (0x1F & start_addr); command2 = 0x00 + (0x1F & (length - 1)); /* 拉低SYNC */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); HAL_Delay(1); /* 发送命令1 */ HAL_SPI_Transmit(&hspi1, &command1, 1, 1000); /* 发送命令2 */ HAL_SPI_Transmit(&hspi1, &command2, 1, 1000); /* 写入数据 */ for(unsigned int i = 0; i < length; i++) { HAL_SPI_Transmit(&hspi1, &wtptr[i], 1, 1000); } /* 释放SYNC */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); HAL_Delay(10); /* 重新启动连续读取模式 */ uint8_t rdatac_cmd = ADC_RDATAC; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); } /**************************************************************************** Function Name : read_ADC_DATA * Description : read ADC value in Read Data By Command mode * Parameters : unsigned int ADC_data_wait: time out cycle * Return Value : unsigned long int Data received * ****************************************************************************/ unsigned long int read_ADC_DATA(unsigned int ADC_data_wait) { unsigned long int temp_read = 0U; unsigned char data[4] = {0}; // 在连续读取模式下,不需要发送RDATA命令 // 直接读取4字节数据 // 检查DRDY状态 - 当DRDY为低电平时数据就绪 if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1) == GPIO_PIN_SET) { return 0xFFFFFFFFUL; // 数据未就绪 } // 读取4个字节数据 HAL_SPI_Receive(&hspi1, data, 4, 1000); // 组合4个字节为32位数据 temp_read = (((unsigned long int)data[0]) << 24U) | (((unsigned long int)data[1]) << 16U) | (((unsigned long int)data[2]) << 8U) | ((unsigned long int)data[3]); return temp_read; } /**************************************************************************** Function Name : calibration_ADC * Description : ADC offset or gain calibration command * Parameters : unsigned int CAL_CMD: ADC_OFSCAL or ADC_GANCAL * 0 = offset calibration, 1 = gain calibration * unsigned in ADC_data_wait: time out cycle, 0 diable * Return Value : unsigned long int Data received * ****************************************************************************/ signed int calibration_ADC(unsigned int CAL_CMD, unsigned int ADC_data_wait) { // 停止连续读取 HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); uint8_t sdatac_cmd = ADC_SDATAC; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); // 发送同步命令 uint8_t sync_cmd = ADC_SYNC; HAL_SPI_Transmit(&hspi1, &sync_cmd, 1, 1000); HAL_Delay(10); if(!CAL_CMD) { uint8_t ofscal_cmd = ADC_OFSCAL; HAL_SPI_Transmit(&hspi1, &ofscal_cmd, 1, 1000); } else { uint8_t gancal_cmd = ADC_GANCAL; HAL_SPI_Transmit(&hspi1, &gancal_cmd, 1, 1000); } HAL_Delay(10); // 重新启动连续读取 uint8_t rdatac_cmd = ADC_RDATAC; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); return(0); } /**************************************************************************** Function Name : read_ADC_ALLREG * Description : read all ADC value and save it to array * * Return Value : * ****************************************************************************/ void read_ADC_ALLREG(void) { /* send stop read data continuous mode command */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); uint8_t sdatac_cmd = ADC_SDATAC; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); read_ADC_REG(ADC_ADDR_ID, 11, adc_regdata); HAL_Delay(10); // 重新启动连续读取模式 uint8_t rdatac_cmd = ADC_RDATAC; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); } /**************************************************************************** Function Name : ADC_configuration * Description : configuration the ADC internal register * Parameters : * * ****************************************************************************/ void ADC_configuration(void) { unsigned char ADC_CFG[2]; // 只需要2个字节用于CONFIG0和CONFIG1 // Configure CONFIG0 register ADC_CFG[0] = ADC_SYNC_P & ADC_MODE_H & ADC_RATE_2000 & ADC_FIR_LIN & ADC_FILTER_SINC_LPF; // Configure CONFIG1 register ADC_CFG[1] = ADC_MUX_1 & ADC_CHOP_EN & ADC_GAIN_1; printf("Configuring ADS1282 with:\r\n"); printf(" SYNC: Pulse, MODE: High-resolution, RATE: 2000SPS\r\n"); printf(" FILTER: Linear phase, SINC+LPF\r\n"); printf(" MUX: AINP1/AINN1, CHOP: Enabled, GAIN: 1\r\n"); /* send stop read data continuous mode command */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); uint8_t sdatac_cmd = ADC_SDATAC; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); write_ADC_REG(ADC_ADDR_CFG0, 2, ADC_CFG); HAL_Delay(10); // 重新启动连续读取模式 uint8_t rdatac_cmd = ADC_RDATAC; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); printf("ADS1282 configuration completed.\r\n"); } ads1282.h中代码: #ifndef __ADS1282_H #define __ADS1282_H #include “main.h” /* Pin function definition */ #define DRDY_ADC (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1) == GPIO_PIN_RESET) #define DELAY_FCLK(n) { int nCount=n; for(; nCount != 0; nCount–); } #define DELAY_CIRCLE 100 /* ADC command definition */ #define ADC_WAKEUP 0x00 #define ADC_STANDBY 0x02 #define ADC_SYNC 0x04 #define ADC_RESET 0x06 #define ADC_RDATAC 0x10 #define ADC_SDATAC 0x11 #define ADC_RDATA 0x12 #define ADC_RREG 0x20 #define ADC_WREG 0x40 #define ADC_OFSCAL 0x60 #define ADC_GANCAL 0x61 /* ADC internal register address definition */ #define ADC_ADDR_ID 0x00 #define ADC_ADDR_CFG0 0x01 #define ADC_ADDR_CFG1 0x02 #define ADC_ADDR_HPF0 0x03 #define ADC_ADDR_HPF1 0x04 #define ADC_ADDR_OFC0 0x05 #define ADC_ADDR_OFC1 0x06 #define ADC_ADDR_OFC2 0x07 #define ADC_ADDR_FSC0 0x08 #define ADC_ADDR_FSC1 0x09 #define ADC_ADDR_FSC2 0x0A /* CONFIG0 definition / / Synchronization mode / #define ADC_SYNC_P 0x7F / Pulse SYNC mode(default) / #define ADC_SYNC_C 0xFF / Continuous SYNC mode */ /* MODE / #define ADC_MODE_L 0xBF / Low-power mode / #define ADC_MODE_H 0xFF / High-resolution mode(default) */ /* Data Rate Select / #define ADC_RATE_250 0xC7 / 250SPS / #define ADC_RATE_500 0xCF / 500SPS / #define ADC_RATE_1000 0xD7 / 1000SPS(default) / #define ADC_RATE_2000 0xDF / 2000SPS / #define ADC_RATE_4000 0xE7 / 4000SPS */ /* FIR Phase Response / #define ADC_FIR_LIN 0xFB / Linear phase(default) / #define ADC_FIR_MIN 0xFF / Minimum phase */ /* Digital filter configuration / #define ADC_FILTER_BYPASS 0xFC / On-chip filter bypassed, modulator output mode / #define ADC_FILTER_SINC 0xFD / Sinc filter block only / #define ADC_FILTER_SINC_LPF 0xFE / Sinc + LPF filter blocks (default) / #define ADC_FILTER_SINC_LPF_HPF 0xFF / Sinc + LPF + HPF filter blocks */ /* CONFIG1 definition / / Multiplexer input select / #define ADC_MUX_1 0x0F / AINP1 and AINN1(default) / #define ADC_MUX_2 0x1F / AINP2 and AINN2 / #define ADC_MUX_GND 0x2F / Internal short via 400R / #define ADC_MUX_1_2 0x3F / AINP1 and AINN1 connected to AINP2 and AINN2 / #define ADC_MUX_EX2 0x4F / External short to AINN2 */ /* PGA Chopping Enable / #define ADC_CHOP_DIS 0x77 / PGA chopping disabled / #define ADC_CHOP_EN 0x7F / PGA chopping enabled(defaut) */ /* PGA Gain Select / #define ADC_GAIN_1 0x78 / G = 1(default) / #define ADC_GAIN_2 0x79 / G = 2 / #define ADC_GAIN_4 0x7A / G = 4 / #define ADC_GAIN_8 0x7B / G = 8 / #define ADC_GAIN_16 0x7C / G = 16 / #define ADC_GAIN_32 0x7D / G = 32 / #define ADC_GAIN_64 0x7E / G = 64 */ /* External variables */ extern unsigned char adc_regdata[11]; /* Function prototypes */ unsigned char write_CMD(unsigned char CMD); void read_ADC_REG(unsigned int start_addr, unsigned int length, unsigned char *rdptr); void write_ADC_REG(unsigned int start_addr, unsigned int length, unsigned char *wtptr); unsigned long int read_ADC_DATA(unsigned int ADC_data_wait); signed int calibration_ADC(unsigned int CAL_CMD, unsigned int ADC_data_wait); void read_ADC_ALLREG(void); void ADC_configuration(void); #endif /* __ADS1282_H / spi.c中代码: /* File Name : SPI.c Description : This file provides code for the configuration of the SPI instances. @attention <h2><center>© Copyright (c) 2023 STMicroelectronics. All rights reserved. This software component is licensed by ST under Ultimate Liberty license SLA0044, the “License”; You may not use this file except in compliance with the License. You may obtain a copy of the License at: www.st.com/SLA0044 */ /* Includes ------------------------------------------------------------------*/ #include “spi.h” /* USER CODE BEGIN 0 / #include “stdio.h” / USER CODE END 0 */ SPI_HandleTypeDef hspi1; /* SPI1 init function */ void MX_SPI1_Init(void) { hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; // CPOL = 0 hspi1.Init.CLKPhase = SPI_PHASE_2EDGE; // CPHA = 1 (模式1) - 正确匹配ADS1282 hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; // 降低SPI速度提高稳定性 hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } } void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(spiHandle->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspInit 0 */ /* USER CODE END SPI1_MspInit 0 / / SPI1 clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**SPI1 GPIO Configuration PA1 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN SPI1_MspInit 1 */ /* USER CODE END SPI1_MspInit 1 */ } } void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle) { if(spiHandle->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspDeInit 0 */ /* USER CODE END SPI1_MspDeInit 0 / / Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); /**SPI1 GPIO Configuration PA1 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_6|GPIO_PIN_7); /* USER CODE BEGIN SPI1_MspDeInit 1 */ /* USER CODE END SPI1_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ // 使用PB5作为SYNC/CS引脚 #define SYNC_PIN GPIO_PIN_5 #define SYNC_PORT GPIOB void SPI_SendData(unsigned char data) { HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); // 拉低SYNC作为片选 HAL_SPI_Transmit(&hspi1, &data, 1, 1000); HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); // 释放SYNC } unsigned char SPI_ReceiveData() { unsigned char data = 0; HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); // 拉低SYNC作为片选 HAL_SPI_Receive(&hspi1, &data, 1, 1000); HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); // 释放SYNC return data; } unsigned long int SPI_ReceiveData_4byte() { unsigned char data[4] = {0}; unsigned long int temp_read_U = 0; // 在连续读取模式下,不需要控制SYNC引脚 // 直接读取数据 HAL_StatusTypeDef status = HAL_SPI_Receive(&hspi1, data, 4, 1000); if(status == HAL_OK) { // 将4个字节组合成32位数据 temp_read_U = ((unsigned long int)data[0] << 24) | ((unsigned long int)data[1] << 16) | ((unsigned long int)data[2] << 8) | ((unsigned long int)data[3]); } else { printf("SPI Receive error: %d\r\n", status); } return temp_read_U; } // 新增函数:同时发送和接收数据 unsigned char SPI_TransmitReceive(unsigned char txData) { unsigned char rxData = 0; HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); // 拉低SYNC作为片选 HAL_SPI_TransmitReceive(&hspi1, &txData, &rxData, 1, 1000); HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); // 释放SYNC return rxData; } /* USER CODE END 1 */ /************************ (C) COPYRIGHT STMicroelectronics END OF FILE/ spi.h中代码: /* File Name : SPI.h Description : This file provides code for the configuration of the SPI instances. @attention <h2><center>© Copyright (c) 2023 STMicroelectronics. All rights reserved. This software component is licensed by ST under Ultimate Liberty license SLA0044, the “License”; You may not use this file except in compliance with the License. You may obtain a copy of the License at: www.st.com/SLA0044 / / Define to prevent recursive inclusion -------------------------------------*/ #ifndef __spi_H #define __spi_H #ifdef __cplusplus extern “C” { #endif /* Includes ------------------------------------------------------------------*/ #include “main.h” /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ extern SPI_HandleTypeDef hspi1; /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ void MX_SPI1_Init(void); /* USER CODE BEGIN Prototypes / void SPI_SendData(unsigned char data); unsigned char SPI_ReceiveData(void); unsigned long int SPI_ReceiveData_4byte(void); / USER CODE END Prototypes */ #ifdef cplusplus } #endif #endif /* spi_H */ /** @} */ /** @} */ /************************ (C) COPYRIGHT STMicroelectronics END OF FILE/ gpio.c中代码: /* File Name : gpio.c Description : This file provides code for the configuration of all used GPIO pins. @attention <h2><center>© Copyright (c) 2023 STMicroelectronics. All rights reserved. This software component is licensed by ST under Ultimate Liberty license SLA0044, the “License”; You may not use this file except in compliance with the License. You may obtain a copy of the License at: www.st.com/SLA0044 */ /* Includes ------------------------------------------------------------------*/ #include “gpio.h” /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /----------------------------------------------------------------------------/ /* Configure GPIO / /----------------------------------------------------------------------------/ / USER CODE BEGIN 1 */ /* USER CODE END 1 */ /** Configure pins as * Analog * Input * Output * EVENT_OUT * EXTI * Free pins are configured automatically as Analog (this feature is enabled through * the Code Generation settings) PA8 ------> RCC_MCO */ void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOC, LED_Pin|GPIO_PIN_2, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13|GPIO_PIN_3, GPIO_PIN_SET); /*Configure GPIO pins : PCPin PC2 */ GPIO_InitStruct.Pin = LED_Pin|GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pin : PC1 */ GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pins : PC3 PC4 PC5 PC6 PC7 */ GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6 |GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pins : PA0 PA4 PA5 PA11 PA12 PA15 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11 |GPIO_PIN_12|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pins : PB0 PB1 PB2 PB10 PB11 PB12 PB14 PB15 PB4 PB5 PB6 PB7 PB8 PB9 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10 |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_14|GPIO_PIN_15 |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 |GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pins : PB13 PB3 */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pin : PA8 */ GPIO_InitStruct.Pin = GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_MCO; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pin : PH3 */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); } /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /************************ (C) COPYRIGHT STMicroelectronics END OF FILE/ usart.c中代码: /* File Name : USART.c Description : This file provides code for the configuration of the USART instances. @attention <h2><center>© Copyright (c) 2023 STMicroelectronics. All rights reserved. This software component is licensed by ST under Ultimate Liberty license SLA0044, the “License”; You may not use this file except in compliance with the License. You may obtain a copy of the License at: www.st.com/SLA0044 */ /* Includes ------------------------------------------------------------------*/ #include “usart.h” /* USER CODE BEGIN 0 / #include “stdio.h” / USER CODE END 0 */ UART_HandleTypeDef huart1; UART_HandleTypeDef huart2; /* USART1 init function */ void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } /* USART2 init function */ void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 9600; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspInit 0 */ /* USER CODE END USART1_MspInit 0 / / USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART1_MspInit 1 */ /* USER CODE END USART1_MspInit 1 / } else if(uartHandle->Instance==USART2) { / USER CODE BEGIN USART2_MspInit 0 */ /* USER CODE END USART2_MspInit 0 / / USART2 clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART2_MspInit 1 */ /* USER CODE END USART2_MspInit 1 */ } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) { if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspDeInit 0 */ /* USER CODE END USART1_MspDeInit 0 / / Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 / } else if(uartHandle->Instance==USART2) { / USER CODE BEGIN USART2_MspDeInit 0 */ /* USER CODE END USART2_MspDeInit 0 / / Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); /* USER CODE BEGIN USART2_MspDeInit 1 */ /* USER CODE END USART2_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ #ifdef GNUC #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF); return ch; } void UART1_Transmit(uint8_t *pData, uint16_t Size) { HAL_UART_Transmit(&huart1, pData, Size, 1000); } // 安全的串口输出函数,带重试机制 uint8_t UART1_Transmit_Safe(uint8_t *pData, uint16_t Size, uint8_t max_retries) { uint8_t retry_count = 0; HAL_StatusTypeDef status; do { status = HAL_UART_Transmit(&huart1, pData, Size, 1000); if(status == HAL_OK) { return 1; // 成功 } retry_count++; HAL_Delay(10); // 短暂延时后重试 } while(retry_count < max_retries); return 0; // 失败 } /* USER CODE END 1 */ /************************ (C) COPYRIGHT STMicroelectronics *END OF FILE/ 这是串口输出结果: STM32 System Launched! Initializing peripherals… Configuring MCO for ADS1282 clock… MCO configured: PA8 outputting 4.096MHz clock for ADS1282 Please verify clock signal on PA8 with oscilloscope. Waiting for ADS1282 clock stabilization… 5 seconds… 4 seconds… 3 seconds… 2 seconds… 1 seconds… Clock stabilization wait completed. === SD Card Initialization === SD Card Hardware Initialization: SUCCESS File System Mount: SUCCESS File System Test: SUCCESS (17 bytes written) Write test completed - file created successfully. === SD Card Initialization Completed Successfully === SD Card initialized successfully! Initializing ADS1282… Starting complete ADS1282 initialization… Sending reset command… Done Stopping continuous read… Done Reading ID register… ID = 0x00 Configuring registers… Done Verifying configuration… CONFIG0=0x00, CONFIG1=0x00 Starting continuous read… Done Complete ADS1282 initialization finished. Reading ADS1282 registers for verification… Register values: Reg[0]: 0x00 Reg[1]: 0x00 Reg[2]: 0x00 Reg[3]: 0x00 Reg[4]: 0x00 Reg[5]: 0x00 Reg[6]: 0x00 Reg[7]: 0x00 Reg[8]: 0x00 Reg[9]: 0x00 Reg[10]: 0x00 WARNING: All registers read as 0x00 - SPI communication may be failing! Please check: ADS1282 power supply SPI connections (MOSI, MISO, SCLK, SYNC) DRDY pin connection (PC1) Reset pin state (should be high for normal operation) ADS1282 register read completed. System initialization completed! Waiting for initial data… Waiting for initial data… Waiting for initial data… 使用的stm32L431RCT6单片机,keil_u5软件,此时我的两根采集线没接信号发生器,你应该能看懂我的代码目的吧,sd卡相关功能应该已经正常了,在保持sd卡保持不变的情况下我希望串口实时输出采集到的数据,采集500个后将数据存到sd卡中,我记得spi应该为0,0模式,ads1282应该为连续读取模式,SYNC接了49.9Ω电阻后接到PB5,请你分析一下再给出完整的有改动的改正后的各个文件的完整代码
10-31
main.c中代码: /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2023 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "dma.h" #include "fatfs.h" #include "rtc.h" #include "sdmmc.h" #include "spi.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stdio.h" #include "string.h" #include "ads1282.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ #define SYNC_PIN GPIO_PIN_5 #define SYNC_PORT GPIOB uint8_t Buffer_Tx[512] = {0}; uint8_t Buffer_Rx[512] = {0}; int if_cal; long int __attribute__((section(".array"))) graphic_1[500]; long int __attribute__((section(".array"))) graphic_2[500]; long int __attribute__((section(".array"))) graphic_3[500]; unsigned int temp = 0x00; unsigned int tempx; volatile uint8_t data_ready = 0; uint8_t sd_card_available = 0; uint32_t data_collection_count = 0; // 定义工作缓冲区,使用固定大小替代FF_MAX_SS BYTE workBuffer[4096]; // 使用4KB作为工作缓冲区 /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ void print_ads1282_data(void); uint8_t initialize_sd_card(void); void debug_ads1282_registers(void); void testSPI(void); void configure_ads1282_clock(void); void wait_for_clock_stabilization(void); void complete_ads1282_init(void); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_USART1_UART_Init(); MX_USART2_UART_Init(); MX_SDMMC1_SD_Init(); MX_FATFS_Init(); MX_SPI1_Init(); MX_RTC_Init(); /* USER CODE BEGIN 2 */ printf("STM32 System Launched!\r\n"); printf("Initializing peripherals...\r\n"); // 配置时钟 configure_ads1282_clock(); wait_for_clock_stabilization(); // 初始化SD卡 sd_card_available = initialize_sd_card(); if(sd_card_available) { printf("SD Card initialized successfully!\r\n"); } else { printf("SD Card initialization failed!\r\n"); } // 初始化ADS1282 printf("Initializing ADS1282...\r\n"); complete_ads1282_init(); // 验证ADS1282状态 debug_ads1282_registers(); printf("System initialization completed!\r\n"); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { testSPI(); // 如果收集了500个数据点,打印它们 if(data_ready) { printf("\r\n=== 500 Data Points Collected ===\r\n"); print_ads1282_data(); // 如果SD卡可用,保存到SD卡 if(sd_card_available) { // 这里可以添加SD卡保存代码 printf("Data saved to SD card.\r\n"); } data_ready = 0; data_collection_count++; printf("Collection cycle #%lu completed. Restarting...\r\n", data_collection_count); // 等待5秒再开始下一轮 HAL_Delay(5000); } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitStruct structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.LSIState = RCC_LSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 1; RCC_OscInitStruct.PLL.PLLN = 16; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART1 |RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_SDMMC1; PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2; PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1; PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; PeriphClkInit.Sdmmc1ClockSelection = RCC_SDMMC1CLKSOURCE_PLLSAI1; PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE; PeriphClkInit.PLLSAI1.PLLSAI1M = 1; PeriphClkInit.PLLSAI1.PLLSAI1N = 8; PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7; PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2; PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2; PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_48M2CLK; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } // 修改MCO配置为输出4.096MHz时钟给ADS1282 // 使用HSE(8.192MHz)的2分频得到4.096MHz HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_2); /** Configure the main internal regulator output voltage */ if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /** * @brief Wait for ADS1282 clock stabilization */ void wait_for_clock_stabilization(void) { printf("Waiting for ADS1282 clock stabilization...\r\n"); // ADS1282需要时钟稳定后才能响应命令 // 等待足够长的时间让时钟稳定 for(int i = 5; i > 0; i--) { printf(" %d seconds...\r\n", i); HAL_Delay(1000); } printf("Clock stabilization wait completed.\r\n"); } void configure_ads1282_clock(void) { printf("Configuring MCO for ADS1282 clock...\r\n"); // 启用GPIOA时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置PA8为MCO GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF0_MCO; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置MCO输出HSE的2分频(4.096MHz) HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_2); printf("MCO configured: PA8 outputting 4.096MHz clock for ADS1282\r\n"); printf("Please verify clock signal on PA8 with oscilloscope.\r\n"); } void complete_ads1282_init(void) { printf("Starting complete ADS1282 initialization...\r\n"); // 1. 确保SYNC为高电平 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET); HAL_Delay(10); // 2. 发送复位命令 printf(" 1. Sending reset command... "); uint8_t reset_cmd = 0x06; HAL_SPI_Transmit(&hspi1, &reset_cmd, 1, 1000); HAL_Delay(500); // 延长复位等待时间 printf("Done\r\n"); // 3. 发送停止连续读取命令 printf(" 2. Stopping continuous read... "); uint8_t sdatac_cmd = 0x11; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); printf("Done\r\n"); // 4. 验证ID寄存器 printf(" 3. Reading ID register... "); uint8_t id_reg = 0; read_ADC_REG(0x00, 1, &id_reg); printf("ID = 0x%02X\r\n", id_reg); // 5. 配置寄存器 printf(" 4. Configuring registers... "); unsigned char config_data[2]; // CONFIG0: 脉冲同步,高分辨率模式,2000SPS,线性相位,SINC+LPF config_data[0] = 0xDF; // 2000SPS, 线性相位, SINC+LPF // CONFIG1: AINP1/AINN1输入,斩波使能,增益1 config_data[1] = 0x0F; // MUX选择AINP1/AINN1, 斩波使能, 增益1 write_ADC_REG(0x01, 2, config_data); HAL_Delay(10); printf("Done\r\n"); // 6. 验证配置 printf(" 5. Verifying configuration... "); unsigned char verify_data[2]; read_ADC_REG(0x01, 2, verify_data); printf("CONFIG0=0x%02X, CONFIG1=0x%02X\r\n", verify_data[0], verify_data[1]); // 7. 启动连续读取模式 printf(" 6. Starting continuous read... "); uint8_t rdatac_cmd = 0x10; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); printf("Done\r\n"); printf("Complete ADS1282 initialization finished.\r\n"); } /** * @brief Debug function to read ADS1282 registers */ void debug_ads1282_registers(void) { printf("Reading ADS1282 registers for verification...\r\n"); read_ADC_ALLREG(); printf("Register values:\r\n"); for(int i = 0; i < 11; i++) { printf(" Reg[%d]: 0x%02X\r\n", i, adc_regdata[i]); } // 检查ID寄存器是否为预期值 if(adc_regdata[0] == 0x00) { printf("WARNING: All registers read as 0x00 - SPI communication may be failing!\r\n"); printf("Please check:\r\n"); printf(" 1. ADS1282 power supply\r\n"); printf(" 2. SPI connections (MOSI, MISO, SCLK, SYNC)\r\n"); printf(" 3. DRDY pin connection (PC1)\r\n"); printf(" 4. Reset pin state (should be high for normal operation)\r\n"); } else { printf("ID Register value: 0x%02X (should typically be 0x12 for ADS1282)\r\n", adc_regdata[0]); } printf("ADS1282 register read completed.\r\n\r\n"); } /** * @brief Print collected ADS1282 data */ void print_ads1282_data(void) { printf("ADS1282 Collected Data (500 points):\r\n"); printf("Index\tRaw Data\tFiltered Data\r\n"); printf("-----\t--------\t-------------\r\n"); for(unsigned int i = 0; i < 500; i++) { printf("%d\t%ld\t%ld\r\n", i, graphic_1[i], graphic_3[i]); } printf("=== End of Data ===\r\n\r\n"); } /** * @brief Initialize SD Card with error handling */ uint8_t initialize_sd_card(void) { FRESULT fres; DSTATUS stat; printf("\r\n=== SD Card Initialization ===\r\n"); // 1. SD Card Hardware Initialization printf("1. SD Card Hardware Initialization: "); stat = SD_Driver.disk_initialize(0); if(stat != RES_OK) { printf("FAILED (Status: %d)\r\n", stat); printf(" Please check:\r\n"); printf(" - SD card is inserted properly\r\n"); printf(" - SD card is not write-protected\r\n"); printf(" - SD card format is supported (FAT32 recommended)\r\n"); return 0; } printf("SUCCESS\r\n"); // 2. File System Mount printf("2. File System Mount: "); fres = f_mount(&SDFatFS, SDPath, 1); if(fres != FR_OK) { printf("FAILED (Error: %d)\r\n", fres); // 提供特定错误信息 switch(fres) { case FR_NO_FILESYSTEM: printf(" No valid FAT filesystem found.\r\n"); printf(" Please format the SD card as FAT32.\r\n"); break; case FR_NOT_READY: printf(" Storage device not ready.\r\n"); printf(" Check SD card connection.\r\n"); break; case FR_DISK_ERR: printf(" Disk error occurred.\r\n"); printf(" Check SD card health.\r\n"); break; default: printf(" Unknown error.\r\n"); break; } // 尝试创建新的文件系统 printf(" Attempting to create new filesystem...\r\n"); fres = f_mkfs(SDPath, FM_FAT32, 0, workBuffer, sizeof(workBuffer)); if(fres == FR_OK) { printf(" New FAT32 filesystem created successfully!\r\n"); // 再次尝试挂载 fres = f_mount(&SDFatFS, SDPath, 1); if(fres == FR_OK) { printf(" Filesystem mounted successfully after format.\r\n"); } else { printf(" Mount failed after format (Error: %d)\r\n", fres); return 0; } } else { printf(" Format failed (Error: %d)\r\n", fres); printf(" Please format SD card on computer as FAT32 and try again.\r\n"); return 0; } } else { printf("SUCCESS\r\n"); } // 3. 简单的文件写入测试 printf("3. File System Test: "); uint32_t byteswritten; char test_filename[] = "TEST.TXT"; char test_data[] = "STM32 SD Test OK!"; fres = f_open(&SDFile, test_filename, FA_CREATE_ALWAYS | FA_WRITE); if(fres == FR_OK) { fres = f_write(&SDFile, test_data, strlen(test_data), &byteswritten); if(fres == FR_OK) { f_sync(&SDFile); f_close(&SDFile); printf("SUCCESS (%lu bytes written)\r\n", byteswritten); printf(" Write test completed - file created successfully.\r\n"); } else { printf("WRITE FAILED (Error: %d)\r\n", fres); f_close(&SDFile); return 0; } } else { printf("FILE OPEN FAILED (Error: %d)\r\n", fres); if(fres == FR_INVALID_NAME) { printf(" Invalid filename format.\r\n"); printf(" Please use 8.3 format (max 8 chars + 3 char extension).\r\n"); printf(" Current filename: %s\r\n", test_filename); } return 0; } printf("=== SD Card Initialization Completed Successfully ===\r\n\r\n"); return 1; } /** * @brief Test SPI communication with ADS1282 */ void testSPI(void) { static uint32_t startup_time = 0; static uint8_t startup_done = 0; static uint32_t sample_count = 0; static uint32_t last_print_time = 0; if(!startup_done) { startup_time = HAL_GetTick(); startup_done = 1; last_print_time = startup_time; } // 在连续读取模式下,不需要发送命令,直接读取数据 GPIO_PinState drdy_state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1); if(drdy_state == GPIO_PIN_RESET) { // 数据就绪,读取4字节 unsigned long int temp_read_U = SPI_ReceiveData_4byte(); signed long int temp_read_S = (signed long int)temp_read_U; // 跳过前几个无效数据(ADS1282初始化后可能有垃圾数据) if(sample_count >= 2) { // 打印前10个有效样本用于验证 if(sample_count < 12) { printf("Sample %lu: Raw=0x%08lX, Signed=%ld\r\n", sample_count-2, temp_read_U, temp_read_S); } // 存储数据 if(temp < 500) { graphic_1[temp] = temp_read_S; graphic_2[temp] = graphic_1[temp]; // 应用简单滤波 if(temp > 0) { graphic_3[temp] = (graphic_3[temp-1] * 95 + temp_read_S * 5) / 100; } else { graphic_3[temp] = temp_read_S; } temp++; } } sample_count++; // 检查是否收集了500个点 if(temp >= 500) { data_ready = 1; temp = 0; } } // 每5秒打印一次状态(避免过多输出) uint32_t current_time = HAL_GetTick(); if(current_time - last_print_time > 5000) { if(sample_count < 2) { printf("Waiting for initial data...\r\n"); } else if(temp == 0 && data_ready == 0) { printf("Collecting data... (Total samples: %lu)\r\n", sample_count-2); } last_print_time = current_time; } } /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ printf("Error_Handler called!\r\n"); while(1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ printf("Wrong parameters value: file %s on line %d\r\n", file, line); /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ ads1282.c中代码: #include "ads1282.h" #include "spi.h" #include "main.h" #include "stdio.h" /* array to save ADC configuration data */ unsigned char adc_regdata[11]; // 定义SYNC引脚 #define SYNC_PIN GPIO_PIN_5 #define SYNC_PORT GPIOB // 定义DRDY引脚 #define DRDY_PIN GPIO_PIN_1 #define DRDY_PORT GPIOC /**************************************************************************** * Function Name : write_CMD * * Description : write a byte to SPI then read a byte from SPI * * Parameters : unsigned char CMD: command suppose to write * * * * Return Value : unsigned char Data received * ****************************************************************************/ unsigned char write_CMD(unsigned char CMD) { unsigned char received_data = 0; // 对于ADS1282,SYNC在发送命令时应保持高电平(除非特别要求) // ADS1282使用连续读取模式,不需要每次通信都拉低SYNC // 只有在特定命令如RDATA需要拉低SYNC if(CMD == ADC_RDATA) { HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); } /* Send command and receive data */ HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(&hspi1, &CMD, &received_data, 1, 1000); if(status != HAL_OK) { printf("SPI TransmitReceive error: %d\r\n", status); } if(CMD == ADC_RDATA) { HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); } return received_data; } /**************************************************************************** * Function Name : read_ADC_REG * * Description : read ADC internal register value * * Parameters : unsigned int start_addr: address in ADC register * * unsigned int length: length to be readed (byte) * * unsigned char *rdptr: the received data to be * * recorded to this array * * Return Value : unsigned int number of data bytes yet to be received * ****************************************************************************/ void read_ADC_REG(unsigned int start_addr, unsigned int length, unsigned char *rdptr) { unsigned char command1; unsigned char command2; unsigned char dummy = 0xFF; /* 发送停止连续读取命令 */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); uint8_t sdatac_cmd = ADC_SDATAC; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); // 增加延迟 /* Send Read Register command */ command1 = 0x20 + (0x1F & start_addr); command2 = 0x00 + (0x1F & (length - 1)); /* 拉低SYNC */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); HAL_Delay(1); /* 发送命令1 */ HAL_SPI_Transmit(&hspi1, &command1, 1, 1000); /* 发送命令2 */ HAL_SPI_Transmit(&hspi1, &command2, 1, 1000); /* 等待一小段时间 */ HAL_Delay(1); /* 读取数据 */ for(unsigned int i = 0; i < length; i++) { HAL_SPI_TransmitReceive(&hspi1, &dummy, &rdptr[i], 1, 1000); } /* 释放SYNC */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); HAL_Delay(10); /* 重新启动连续读取模式 */ uint8_t rdatac_cmd = ADC_RDATAC; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); } /**************************************************************************** * Function Name : write_ADC_REG * * Description : write ADC internal register value * * Parameters : unsigned int start_addr: address in ADC register * * unsigned int length: the length of data * * unsigned char *rdptr: the data to be transfered * * recorded in this array * * Return * ****************************************************************************/ void write_ADC_REG(unsigned int start_addr, unsigned int length, unsigned char *wtptr) { unsigned char command1; unsigned char command2; /* 发送停止连续读取命令 */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); uint8_t sdatac_cmd = ADC_SDATAC; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); /* Send Write Register command */ command1 = 0x40 + (0x1F & start_addr); command2 = 0x00 + (0x1F & (length - 1)); /* 拉低SYNC */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); HAL_Delay(1); /* 发送命令1 */ HAL_SPI_Transmit(&hspi1, &command1, 1, 1000); /* 发送命令2 */ HAL_SPI_Transmit(&hspi1, &command2, 1, 1000); /* 写入数据 */ for(unsigned int i = 0; i < length; i++) { HAL_SPI_Transmit(&hspi1, &wtptr[i], 1, 1000); } /* 释放SYNC */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); HAL_Delay(10); /* 重新启动连续读取模式 */ uint8_t rdatac_cmd = ADC_RDATAC; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); } /**************************************************************************** * Function Name : read_ADC_DATA * * Description : read ADC value in Read Data By Command mode * * Parameters : unsigned int ADC_data_wait: time out cycle * * Return Value : unsigned long int Data received * ****************************************************************************/ unsigned long int read_ADC_DATA(unsigned int ADC_data_wait) { unsigned long int temp_read = 0U; unsigned char data[4] = {0}; // 在连续读取模式下,不需要发送RDATA命令 // 直接读取4字节数据 // 检查DRDY状态 - 当DRDY为低电平时数据就绪 if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1) == GPIO_PIN_SET) { return 0xFFFFFFFFUL; // 数据未就绪 } // 读取4个字节数据 HAL_SPI_Receive(&hspi1, data, 4, 1000); // 组合4个字节为32位数据 temp_read = (((unsigned long int)data[0]) << 24U) | (((unsigned long int)data[1]) << 16U) | (((unsigned long int)data[2]) << 8U) | ((unsigned long int)data[3]); return temp_read; } /**************************************************************************** * Function Name : calibration_ADC * * Description : ADC offset or gain calibration command * * Parameters : unsigned int CAL_CMD: ADC_OFSCAL or ADC_GANCAL * * 0 = offset calibration, 1 = gain calibration * * unsigned in ADC_data_wait: time out cycle, 0 diable * * Return Value : unsigned long int Data received * ****************************************************************************/ signed int calibration_ADC(unsigned int CAL_CMD, unsigned int ADC_data_wait) { // 停止连续读取 HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); uint8_t sdatac_cmd = ADC_SDATAC; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); // 发送同步命令 uint8_t sync_cmd = ADC_SYNC; HAL_SPI_Transmit(&hspi1, &sync_cmd, 1, 1000); HAL_Delay(10); if(!CAL_CMD) { uint8_t ofscal_cmd = ADC_OFSCAL; HAL_SPI_Transmit(&hspi1, &ofscal_cmd, 1, 1000); } else { uint8_t gancal_cmd = ADC_GANCAL; HAL_SPI_Transmit(&hspi1, &gancal_cmd, 1, 1000); } HAL_Delay(10); // 重新启动连续读取 uint8_t rdatac_cmd = ADC_RDATAC; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); return(0); } /**************************************************************************** * Function Name : read_ADC_ALLREG * * Description : read all ADC value and save it to array * * * Return Value : * ****************************************************************************/ void read_ADC_ALLREG(void) { /* send stop read data continuous mode command */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); uint8_t sdatac_cmd = ADC_SDATAC; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); read_ADC_REG(ADC_ADDR_ID, 11, adc_regdata); HAL_Delay(10); // 重新启动连续读取模式 uint8_t rdatac_cmd = ADC_RDATAC; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); } /**************************************************************************** * Function Name : ADC_configuration * * Description : configuration the ADC internal register * * Parameters : * * * ****************************************************************************/ void ADC_configuration(void) { unsigned char ADC_CFG[2]; // 只需要2个字节用于CONFIG0和CONFIG1 // Configure CONFIG0 register ADC_CFG[0] = ADC_SYNC_P & ADC_MODE_H & ADC_RATE_2000 & ADC_FIR_LIN & ADC_FILTER_SINC_LPF; // Configure CONFIG1 register ADC_CFG[1] = ADC_MUX_1 & ADC_CHOP_EN & ADC_GAIN_1; printf("Configuring ADS1282 with:\r\n"); printf(" SYNC: Pulse, MODE: High-resolution, RATE: 2000SPS\r\n"); printf(" FILTER: Linear phase, SINC+LPF\r\n"); printf(" MUX: AINP1/AINN1, CHOP: Enabled, GAIN: 1\r\n"); /* send stop read data continuous mode command */ HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); uint8_t sdatac_cmd = ADC_SDATAC; HAL_SPI_Transmit(&hspi1, &sdatac_cmd, 1, 1000); HAL_Delay(10); write_ADC_REG(ADC_ADDR_CFG0, 2, ADC_CFG); HAL_Delay(10); // 重新启动连续读取模式 uint8_t rdatac_cmd = ADC_RDATAC; HAL_SPI_Transmit(&hspi1, &rdatac_cmd, 1, 1000); HAL_Delay(10); printf("ADS1282 configuration completed.\r\n"); } ads1282.h中代码: #ifndef __ADS1282_H #define __ADS1282_H #include "main.h" /* Pin function definition */ #define DRDY_ADC (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1) == GPIO_PIN_RESET) #define DELAY_FCLK(n) { int nCount=n; for(; nCount != 0; nCount--); } #define DELAY_CIRCLE 100 /* ADC command definition */ #define ADC_WAKEUP 0x00 #define ADC_STANDBY 0x02 #define ADC_SYNC 0x04 #define ADC_RESET 0x06 #define ADC_RDATAC 0x10 #define ADC_SDATAC 0x11 #define ADC_RDATA 0x12 #define ADC_RREG 0x20 #define ADC_WREG 0x40 #define ADC_OFSCAL 0x60 #define ADC_GANCAL 0x61 /* ADC internal register address definition */ #define ADC_ADDR_ID 0x00 #define ADC_ADDR_CFG0 0x01 #define ADC_ADDR_CFG1 0x02 #define ADC_ADDR_HPF0 0x03 #define ADC_ADDR_HPF1 0x04 #define ADC_ADDR_OFC0 0x05 #define ADC_ADDR_OFC1 0x06 #define ADC_ADDR_OFC2 0x07 #define ADC_ADDR_FSC0 0x08 #define ADC_ADDR_FSC1 0x09 #define ADC_ADDR_FSC2 0x0A /* CONFIG0 definition */ /* Synchronization mode */ #define ADC_SYNC_P 0x7F /* Pulse SYNC mode(default) */ #define ADC_SYNC_C 0xFF /* Continuous SYNC mode */ /* MODE */ #define ADC_MODE_L 0xBF /* Low-power mode */ #define ADC_MODE_H 0xFF /* High-resolution mode(default) */ /* Data Rate Select */ #define ADC_RATE_250 0xC7 /* 250SPS */ #define ADC_RATE_500 0xCF /* 500SPS */ #define ADC_RATE_1000 0xD7 /* 1000SPS(default) */ #define ADC_RATE_2000 0xDF /* 2000SPS */ #define ADC_RATE_4000 0xE7 /* 4000SPS */ /* FIR Phase Response */ #define ADC_FIR_LIN 0xFB /* Linear phase(default) */ #define ADC_FIR_MIN 0xFF /* Minimum phase */ /* Digital filter configuration */ #define ADC_FILTER_BYPASS 0xFC /* On-chip filter bypassed, modulator output mode */ #define ADC_FILTER_SINC 0xFD /* Sinc filter block only */ #define ADC_FILTER_SINC_LPF 0xFE /* Sinc + LPF filter blocks (default) */ #define ADC_FILTER_SINC_LPF_HPF 0xFF /* Sinc + LPF + HPF filter blocks */ /* CONFIG1 definition */ /* Multiplexer input select */ #define ADC_MUX_1 0x0F /* AINP1 and AINN1(default) */ #define ADC_MUX_2 0x1F /* AINP2 and AINN2 */ #define ADC_MUX_GND 0x2F /* Internal short via 400R */ #define ADC_MUX_1_2 0x3F /* AINP1 and AINN1 connected to AINP2 and AINN2 */ #define ADC_MUX_EX2 0x4F /* External short to AINN2 */ /* PGA Chopping Enable */ #define ADC_CHOP_DIS 0x77 /* PGA chopping disabled */ #define ADC_CHOP_EN 0x7F /* PGA chopping enabled(defaut) */ /* PGA Gain Select */ #define ADC_GAIN_1 0x78 /* G = 1(default) */ #define ADC_GAIN_2 0x79 /* G = 2 */ #define ADC_GAIN_4 0x7A /* G = 4 */ #define ADC_GAIN_8 0x7B /* G = 8 */ #define ADC_GAIN_16 0x7C /* G = 16 */ #define ADC_GAIN_32 0x7D /* G = 32 */ #define ADC_GAIN_64 0x7E /* G = 64 */ /* External variables */ extern unsigned char adc_regdata[11]; /* Function prototypes */ unsigned char write_CMD(unsigned char CMD); void read_ADC_REG(unsigned int start_addr, unsigned int length, unsigned char *rdptr); void write_ADC_REG(unsigned int start_addr, unsigned int length, unsigned char *wtptr); unsigned long int read_ADC_DATA(unsigned int ADC_data_wait); signed int calibration_ADC(unsigned int CAL_CMD, unsigned int ADC_data_wait); void read_ADC_ALLREG(void); void ADC_configuration(void); #endif /* __ADS1282_H */ spi.c中代码: /** ****************************************************************************** * File Name : SPI.c * Description : This file provides code for the configuration * of the SPI instances. ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2023 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: * www.st.com/SLA0044 * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "spi.h" /* USER CODE BEGIN 0 */ #include "stdio.h" /* USER CODE END 0 */ SPI_HandleTypeDef hspi1; /* SPI1 init function */ void MX_SPI1_Init(void) { hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; // CPOL = 0 hspi1.Init.CLKPhase = SPI_PHASE_2EDGE; // CPHA = 1 (模式1) - 正确匹配ADS1282 hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; // 降低SPI速度提高稳定性 hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } } void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(spiHandle->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspInit 0 */ /* USER CODE END SPI1_MspInit 0 */ /* SPI1 clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**SPI1 GPIO Configuration PA1 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN SPI1_MspInit 1 */ /* USER CODE END SPI1_MspInit 1 */ } } void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle) { if(spiHandle->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspDeInit 0 */ /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); /**SPI1 GPIO Configuration PA1 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_6|GPIO_PIN_7); /* USER CODE BEGIN SPI1_MspDeInit 1 */ /* USER CODE END SPI1_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ // 使用PB5作为SYNC/CS引脚 #define SYNC_PIN GPIO_PIN_5 #define SYNC_PORT GPIOB void SPI_SendData(unsigned char data) { HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); // 拉低SYNC作为片选 HAL_SPI_Transmit(&hspi1, &data, 1, 1000); HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); // 释放SYNC } unsigned char SPI_ReceiveData() { unsigned char data = 0; HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); // 拉低SYNC作为片选 HAL_SPI_Receive(&hspi1, &data, 1, 1000); HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); // 释放SYNC return data; } unsigned long int SPI_ReceiveData_4byte() { unsigned char data[4] = {0}; unsigned long int temp_read_U = 0; // 在连续读取模式下,不需要控制SYNC引脚 // 直接读取数据 HAL_StatusTypeDef status = HAL_SPI_Receive(&hspi1, data, 4, 1000); if(status == HAL_OK) { // 将4个字节组合成32位数据 temp_read_U = ((unsigned long int)data[0] << 24) | ((unsigned long int)data[1] << 16) | ((unsigned long int)data[2] << 8) | ((unsigned long int)data[3]); } else { printf("SPI Receive error: %d\r\n", status); } return temp_read_U; } // 新增函数:同时发送和接收数据 unsigned char SPI_TransmitReceive(unsigned char txData) { unsigned char rxData = 0; HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_RESET); // 拉低SYNC作为片选 HAL_SPI_TransmitReceive(&hspi1, &txData, &rxData, 1, 1000); HAL_GPIO_WritePin(SYNC_PORT, SYNC_PIN, GPIO_PIN_SET); // 释放SYNC return rxData; } /* USER CODE END 1 */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ spi.h中代码: /** ****************************************************************************** * File Name : SPI.h * Description : This file provides code for the configuration * of the SPI instances. ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2023 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: * www.st.com/SLA0044 * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __spi_H #define __spi_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "main.h" /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ extern SPI_HandleTypeDef hspi1; /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ void MX_SPI1_Init(void); /* USER CODE BEGIN Prototypes */ void SPI_SendData(unsigned char data); unsigned char SPI_ReceiveData(void); unsigned long int SPI_ReceiveData_4byte(void); /* USER CODE END Prototypes */ #ifdef __cplusplus } #endif #endif /*__ spi_H */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ gpio.c中代码: /** ****************************************************************************** * File Name : gpio.c * Description : This file provides code for the configuration * of all used GPIO pins. ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2023 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: * www.st.com/SLA0044 * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "gpio.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /*----------------------------------------------------------------------------*/ /* Configure GPIO */ /*----------------------------------------------------------------------------*/ /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /** Configure pins as * Analog * Input * Output * EVENT_OUT * EXTI * Free pins are configured automatically as Analog (this feature is enabled through * the Code Generation settings) PA8 ------> RCC_MCO */ void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOC, LED_Pin|GPIO_PIN_2, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13|GPIO_PIN_3, GPIO_PIN_SET); /*Configure GPIO pins : PCPin PC2 */ GPIO_InitStruct.Pin = LED_Pin|GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pin : PC1 */ GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pins : PC3 PC4 PC5 PC6 PC7 */ GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6 |GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pins : PA0 PA4 PA5 PA11 PA12 PA15 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11 |GPIO_PIN_12|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pins : PB0 PB1 PB2 PB10 PB11 PB12 PB14 PB15 PB4 PB5 PB6 PB7 PB8 PB9 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10 |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_14|GPIO_PIN_15 |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 |GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pins : PB13 PB3 */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pin : PA8 */ GPIO_InitStruct.Pin = GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_MCO; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pin : PH3 */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); } /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ usart.c中代码: /** ****************************************************************************** * File Name : USART.c * Description : This file provides code for the configuration * of the USART instances. ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2023 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: * www.st.com/SLA0044 * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usart.h" /* USER CODE BEGIN 0 */ #include "stdio.h" /* USER CODE END 0 */ UART_HandleTypeDef huart1; UART_HandleTypeDef huart2; /* USART1 init function */ void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } /* USART2 init function */ void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 9600; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspInit 0 */ /* USER CODE END USART1_MspInit 0 */ /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART1_MspInit 1 */ /* USER CODE END USART1_MspInit 1 */ } else if(uartHandle->Instance==USART2) { /* USER CODE BEGIN USART2_MspInit 0 */ /* USER CODE END USART2_MspInit 0 */ /* USART2 clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART2_MspInit 1 */ /* USER CODE END USART2_MspInit 1 */ } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) { if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspDeInit 0 */ /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 */ } else if(uartHandle->Instance==USART2) { /* USER CODE BEGIN USART2_MspDeInit 0 */ /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); /* USER CODE BEGIN USART2_MspDeInit 1 */ /* USER CODE END USART2_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF); return ch; } void UART1_Transmit(uint8_t *pData, uint16_t Size) { HAL_UART_Transmit(&huart1, pData, Size, 1000); } // 安全的串口输出函数,带重试机制 uint8_t UART1_Transmit_Safe(uint8_t *pData, uint16_t Size, uint8_t max_retries) { uint8_t retry_count = 0; HAL_StatusTypeDef status; do { status = HAL_UART_Transmit(&huart1, pData, Size, 1000); if(status == HAL_OK) { return 1; // 成功 } retry_count++; HAL_Delay(10); // 短暂延时后重试 } while(retry_count < max_retries); return 0; // 失败 } /* USER CODE END 1 */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 这是串口输出结果: STM32 System Launched! Initializing peripherals... Configuring MCO for ADS1282 clock... MCO configured: PA8 outputting 4.096MHz clock for ADS1282 Please verify clock signal on PA8 with oscilloscope. Waiting for ADS1282 clock stabilization... 5 seconds... 4 seconds... 3 seconds... 2 seconds... 1 seconds... Clock stabilization wait completed. === SD Card Initialization === 1. SD Card Hardware Initialization: SUCCESS 2. File System Mount: SUCCESS 3. File System Test: SUCCESS (17 bytes written) Write test completed - file created successfully. === SD Card Initialization Completed Successfully === SD Card initialized successfully! Initializing ADS1282... Starting complete ADS1282 initialization... 1. Sending reset command... Done 2. Stopping continuous read... Done 3. Reading ID register... ID = 0x00 4. Configuring registers... Done 5. Verifying configuration... CONFIG0=0x00, CONFIG1=0x00 6. Starting continuous read... Done Complete ADS1282 initialization finished. Reading ADS1282 registers for verification... Register values: Reg[0]: 0x00 Reg[1]: 0x00 Reg[2]: 0x00 Reg[3]: 0x00 Reg[4]: 0x00 Reg[5]: 0x00 Reg[6]: 0x00 Reg[7]: 0x00 Reg[8]: 0x00 Reg[9]: 0x00 Reg[10]: 0x00 WARNING: All registers read as 0x00 - SPI communication may be failing! Please check: 1. ADS1282 power supply 2. SPI connections (MOSI, MISO, SCLK, SYNC) 3. DRDY pin connection (PC1) 4. Reset pin state (should be high for normal operation) ADS1282 register read completed. System initialization completed! Waiting for initial data... Waiting for initial data... Waiting for initial data... 此时我的两根采集线没接信号发生器,你应该能看懂我的代码目的吧,sd卡相关功能应该已经正常了,在保持sd卡保持不变的情况下我希望串口实时输出采集到的数据,采集500个后将数据存到sd卡中,我记得spi应该为0,0模式,ads1282应该为连续读取模式,请你分析一下再给出完整的有改动的改正后的各个文件代码
10-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值