my_pscc

博客指出优快云 Blog存在bug,但未提及具体情况。

* 优快云 Blog有bug*
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

#include "spi_slave_server.h" #include "shared_data.h" #include <string.h> // spi #include <SPI.h> #include <ESP32SPISlave.h> #include "helper.h" ESP32SPISlave slave; // 创建ESP32SPISlave对象 static bool battery_data_sent = false; // 防止重复填充缓存 #define SPI_SPLAVE_ENABLE 1 // Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS, 1000000, SPI_BITORDER_MSBFIRST, SPI_MODE0); #define MY_CS 12 #define MY_SCK 13 #define MY_MOSI 14 #define MY_MISO 11 // 自定义spi引脚 // SPIClass my_spi(HSPI); // 创建SPIClass对象my_spi #define SPI_READ_TIMEROUT 999999 // 10 // 50ms static constexpr size_t SPI_BUFFER_SIZE = 128; // 上位机 测试42 字节数据正常,模式1,定义SPI通信缓冲区大小为32字节 static constexpr size_t QUEUE_SIZE = 1; static uint8_t spi_tx_buf[SPI_BUFFER_SIZE]{1, 2, 3, 4, 5, 6, 7, 8};//发送缓冲区,预置测试数据1-8 static uint8_t spi_rx_buf[SPI_BUFFER_SIZE]{0, 0, 0, 0, 0, 0, 0, 0};//接收缓冲区,初始化为全0 static uint8_t spi_tx_cmd_buf[SPI_BUFFER_SIZE]{0, 0, 0, 0, 0, 0, 0, 0};//命令发送缓冲区,初始化为全0 #define SPI_TX_CACHE_BUF_LEN 1024//发送缓存总大小为1024字节 #define SPI_TX_PAGE_BUF_LEN (SPI_BUFFER_SIZE - 3) // spi 回复数据的最大长度,单次SPI通信有效数据长度 #define SPI_USER_CMD_NULL 0//空指令 #define SPI_USER_CMD_READ 1//读数据 #define SPI_USER_CMD_WRITE 2//写数据 static volatile uint8_t spi_tx_cache_buf[SPI_TX_CACHE_BUF_LEN]{0, 0, 0, 0, 0, 0, 0, 0}; static volatile int spi_tx_cache_buf_cnt = 0; // spi 发送缓存区数据长度 // static int spi_tx_page_cnt=0;//spi 发送缓存区数据长度 static volatile int spi_current_cmd = 0, spi_current_cmd_len = 0; static uint8_t spi_send_busy = 0;//发送忙标志位 static uint8_t spi_send_mode = 1; // 发送模式选择发串口 int spi_slave_data_cache_add(uint8_t *data, uint16_t len) { if (len > SPI_TX_CACHE_BUF_LEN) { /* code */ len = SPI_TX_CACHE_BUF_LEN; } for (int i = 0; i < len; i++) { /* code */ spi_tx_cache_buf[i] = data[i]; } spi_tx_cache_buf_cnt = len; return 0; } void IRAM_ATTR my_post_setup_cb(spi_slave_transaction_t *trans) { // ==== Step 1: 尝试从 BLE 获取最新数据并写入 spi_tx_cache_buf ==== if (json_updated && !battery_data_sent) { portENTER_CRITICAL_ISR(&json_mutex); int len = strlen(latest_battery_json); if (len > 0 && len < SPI_TX_CACHE_BUF_LEN) { memset((void*)spi_tx_cache_buf, 0, SPI_TX_CACHE_BUF_LEN); memcpy((void*)spi_tx_cache_buf, latest_battery_json, len); spi_tx_cache_buf_cnt = len; battery_data_sent = true; // 标记已加载 } json_updated = false; // 清除标志 portEXIT_CRITICAL_ISR(&json_mutex); } // ==== Step 2: 计算本次应发送的数据段 ==== int over_len = spi_tx_cache_buf_cnt - spi_current_cmd_len * SPI_TX_PAGE_BUF_LEN; if (over_len <= 0) { // 数据已发完,重置状态以便下次更新 if (over_len < 0) return; // 最后一包发完后复位,等待新数据 if (spi_current_cmd_len > 0) { battery_data_sent = false; // 允许下一次更新 spi_current_cmd_len = 0; } return; } if (over_len > SPI_TX_PAGE_BUF_LEN) { over_len = SPI_TX_PAGE_BUF_LEN; } // ==== Step 3: 填充 TX 缓冲区 ==== // 在 my_post_setup_cb 中: memset((void *)spi_tx_buf, 0, SPI_BUFFER_SIZE); spi_tx_buf[0] = 0xab; spi_tx_buf[1] = over_len; spi_tx_buf[2] = spi_current_cmd_len; // 如果是第0包,插入总长度(高位在前) if (spi_current_cmd_len == 0) { spi_tx_buf[3] = (spi_tx_cache_buf_cnt >> 8) & 0xFF; // high spi_tx_buf[4] = spi_tx_cache_buf_cnt & 0xFF; // low // 数据从第5字节开始 int payload_size = (over_len < (SPI_BUFFER_SIZE - 5)) ? over_len : (SPI_BUFFER_SIZE - 5); for (int i = 0; i < payload_size; i++) { spi_tx_buf[5 + i] = spi_tx_cache_buf[i]; } spi_tx_buf[1] = payload_size + 2; // 实际发送长度 = 数据 + 两个长度字节 } else { // 普通包:直接发送数据 for (int i = 0; i < over_len; i++) { spi_tx_buf[3 + i] = spi_tx_cache_buf[(spi_current_cmd_len - 1) * SPI_TX_PAGE_BUF_LEN + i]; } } spi_current_cmd_len++; } /*** * spi slave 任务 * 模式设置4 字节 * spi cmd: 0xaa 0x01 ,切换模式1,发串口1数据 * * 数据读取 64字节,发aa 01 0xff ...... * spi ack: 0xaa 0x01 ,剩余字节全部回复串口数据 */ static void spi_slave_task(void *pvParameters) { size_t received_bytes; while (1) { int cs = digitalRead(MY_CS); #if SPI_SPLAVE_ENABLE if (cs == 0) { memset(spi_rx_buf, 0, SPI_BUFFER_SIZE); received_bytes = slave.transfer(spi_tx_buf, spi_rx_buf, SPI_BUFFER_SIZE, SPI_READ_TIMEROUT); if (received_bytes > 0) { #if 0 printf_log_hex("slave", spi_rx_buf, received_bytes); #endif // 检查是否是请求命令(如 AA 01) if (spi_rx_buf[0] == 0xAA) { uint8_t cmd = spi_rx_buf[1]; // 示例:收到 AA 01 表示请求数据 if (cmd == 0x01) { // 不做任何事 —— 下一次 transfer 会由 my_post_setup_cb 自动填充数据 Serial.println("SPI: 收到 AA 01 请求,准备回传电池数据"); } } } } #endif vTaskDelay(5 / portTICK_PERIOD_MS); } } /** * spi slave 初始化 * SPI_MODE1 * sck 13 * miso 14 * mosi 11 * ss 12 * */ void spi_slave_server_init(void) { #if SPI_SPLAVE_ENABLE slave.setDataMode(SPI_MODE3); slave.setQueueSize(QUEUE_SIZE); slave.begin(HSPI, MY_SCK, MY_MISO, MY_MOSI, MY_CS); // 推荐显式命名引脚 // 注册 post-setup 回调(关键!) slave.setPostSetupCb(my_post_setup_cb); xTaskCreate(spi_slave_task, "spi_slave_task", 8 * 1024, NULL, 2, NULL); Serial.println("SPI Slave 已启动,等待主机访问..."); #endif } ESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0x28 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fce3808,len:0x4bc load:0x403c9700,len:0xbd8 load:0x403cc700,len:0x2a0c entry 0x403c98d0 E (202) esp_core_dump_flash: Core dump data check failed: Calculated checksum='84797ec0' Image checksum='ffffffff' uart1_init... baud_rate=115200,rx= 5,tx= 4 SPI Slave 已启动,等待主机访问... 初始化 BLE 主机... Guru Meditation Error: Core 1 panic'ed (Double exception). Core 1 register dump: PC : 0x4037f18e PS : 0x00040136 A0 : 0x8037f9eb A1 : 0x3fced480 A2 : 0x00040136 A3 : 0x00040026 A4 : 0x3fcf0858 A5 : 0x0000004c A6 : 0x3fcf04a0 A7 : 0x00000001 A8 : 0x3fced540 A9 : 0x00000000 A10 : 0x00000054 A11 : 0xffffffff A12 : 0x00000000 A13 : 0x00001800 A14 : 0x00060523 A15 : 0x00000001 SAR : 0x00000004 EXCCAUSE: 0x00000002 EXCVADDR: 0x00000000 LBEG : 0x400556d5 LEND : 0x400556e5 LCOUNT : 0xfffffff9 Backtrace: 0x4037f18b:0x3fced480 0x4037f9e8:0x00060f23 |<-CORRUPTED ELF file SHA256: 9c14ee0b4f8a43af Rebooting...
10-15
#include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" #include "system_stm32f10x.h" #include "key.h" #include "stm32f10x_it.h" #include "bit_band.h" #include "key_led.h" #include "stm32f10x_tim.h" #include "misc.h" #include "time_init.h" #define pi 3.1415926 #include <math.h> __IO uint32_t SysTick_ms_setnums,SysTick_ms_nums,period,width; float T_sine,ratio_in,T_nums,ratio_out; void SysTick_Configuration(void) { SysTick->CTRL|=0x1<<2; SysTick->CTRL|=0x03; SysTick->LOAD|=71999; } int main() { u16 my_time3_psc=0,my_time3_arr=35999; u16 my_time4_psc=0,my_time4_arr=60000; Time3_PwmoutCNF_OnLibFunc(my_time3_arr,my_time3_psc); Time4_PwmdetectCNF_OnReg(my_time4_arr,my_time4_psc); SysTick_Configuration(); float f_sine; f_sine=0.2; T_sine=1/f_sine; T_nums=((float) T_sine)/0.001; SysTick_ms_setnums=5000; SysTick_ms_nums=SysTick_ms_setnums; while(1) { if (SysTick_ms_nums>=T_nums) SysTick_ms_nums=5000; ratio_in=0.5+0.5*sin(2*pi*f_sine*SysTick_ms_nums*0.001); TIM3->CCR2=ratio_in*my_time3_arr; period=TIM4->CCR1+1; width=TIM4->CCR2+1; ratio_out=((float) width/(float) period); } } #include "time_init.h" #include "stm32f10x_rcc.h" #include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_tim.h" void Time3_PwmoutCNF_OnReg(u16 arr,u16 psc) { RCC->APB2ENR =0x01; //开启AFIO时钟 RCC->APB2ENR |=0x01<<3; //开启GPIOB时钟 RCC->APB1ENR |=0x01<<1; //开启TIM3的时钟 GPIOB->CRL &=~(0x0F<<(4*5)); //设置Pin_5的4位先清零 GPIOB->CRL |=(0x0B<<(4*5)); //0x0B=b1011:设置Pin_5为复用功能推挽输出,速度为50MHz AFIO->MAPR &=~(0x03<<10); AFIO->MAPR |=(0x02<<10); //把TIM3_CH2重新映射到PB5 TIM3->CR1 |=(0x01<<7); //ARPE=1,TIM3->ARR被装入缓存器,同时设置计数模式为CMS=00,DIR=0向上计数,CKD=00 TIM3->PSC=psc; TIM3->ARR=arr; /***********下面配置TIM3 Channel2 PWM 模式********************************//* TIM3->CCMR1 bit15(OC2CE):0 输出比较2清零使能位为零,不受ETRF输入的影响; bit14-bit12(OC2M):110 PWM模式1 bit11(OC2PE):0 禁止TIM2_CCR2预装载功能能; bit10(OC2FE): 0 只根据计数器与CCR2的值,CC2正常操作; bit9~bit8(CC2S):00配置为输出 TIM3->CCMR1=0b01100000=0x60 */ /**************************************************************************/ TIM3->CCER &=~(0x01<<4); //CC2S仅在CC2E=0时才是可写的 TIM3->CCMR1 &=~(0xFF<<1*8); TIM3->CCMR1 |=(0x60<<1*8); TIM3->CCER |=(0x01<<4); //输入/捕获2输出使能,CC2E=1 TIM3->CCER &=~(0x01<<5); //设置输出极性高 CC2P=0 TIM3->CCR1 |=(0x01<<7); // 使能预装载寄存器 TIM3->CR1 |=(0x01<<0); //使能定时器3,CEN=1; TIM3->SMCR &=~(0x07<<0); //因TIM3_SMCR复位值为0,故此两句可以省略 TIM3->SMCR |=(0x00<<0); //TIM3->SMCR的bit2-bit0,即SMS=000关闭从模式 } void Time3_PwmoutCNF_OnLibFunc(u16 arr,u16 psc) { //TIM3 PWM 部分初始化 //PWM 输出初始化 //arr :自动重装值 //psc :时钟预分频数 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);// 使能定时器 3 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能 GPIO 和 AFIO 复用功能时钟 //设置GPIOB.5引脚为复用输出功能,且重映射为TIM3_CH2以输出PWM脉冲波形 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化 GPIO GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); // 重映射 TIM3_CH2 -->PB5 //初始化 TIM3 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period = arr; // 设置在自动重装载周期值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 设置时钟分割 :TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); // 初始化 TIMx //初始化 TIM3 Channel2 PWM 模式 TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // 选择 PWM 模式 1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 比较输出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高 TIM_OC2Init(TIM3, &TIM_OCInitStructure); //④ 初始化外设 TIM3 OC2 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); // 使能预装载寄存器 TIM_Cmd(TIM3, ENABLE); // 使能 TIM3 } //选用PB6作为TIM4_CH1对TIM3输出的PWM(通过复用功能重映射到PB5)信号进行检测 void Time4_PwmdetectCNF_OnReg(u16 arr,u16 psc) { RCC->APB1ENR |=(0x01<<2); RCC->APB2ENR |=(0X01<<0); //使能 AFIO时钟 RCC->APB2ENR |=(0X01<<3); //使能 GPIOB时钟 //设置引脚PB6为TIM4_CH1复用输入功能,配置为浮空输入 GPIOB->CRL |=0x04; //复用输入,配置为浮空输入 //初始化TIM4 TIM4->CR1 |=(0x01<<7); //ARPE=1,TIM3->ARR被装入缓存器,同时设置计数模式为CMS=00,DIR=0向上计数,CKD=00 TIM4->ARR=arr; TIM4->PSC=psc; //设置CC1 TIM4->CCMR1 &=~(0x01<<1); //清零CC1S高位 TIM4->CCMR1 |=0x01; //CC1S=01 选择输入端 IC1映射到TI1上 TIM4->CCMR1 &=~(0x0F<<4); //IC1F=0000 配置输入滤波器 不滤波 TIM4->CCMR1 &=~(0x03<<2); //IC1PS=00 配置输入分频,不分频 TIM4->CCER &=~(0x01<<1); //CC1P=0 上升沿捕获 //设置CC2 TIM4->CCMR1 &=~(0x01<<8); //清零CC2S低位 TIM4->CCMR1 |=(0x01<<9); //CC2S=10 选择输入端 IC2映射到TI1上 TIM4->CCMR1 &=~(0x0F<<4); //IC2F=0000 配置输入滤波器 不滤波 TIM4->CCMR1 &=~(0x03<<2); //IC2PS=00 配置输入分频,不分频 TIM4->CCER |=(0x01<<5); //CC2P=1 下降沿捕获 TIM4->SMCR |=(0x05<<4); //TS=101,选择TI1FP1 TIM4->SMCR |=0x04; //SMS=100,复位模式 TIM4->CCER |=0x01; //CC1E=1 允许捕获计数器的值到捕获寄存器1中 TIM4->CCER |=(0x01<<4); //CC2E=1 允许捕获计数器的值到捕获寄存器2中 TIM4->CR1|=0x01; //使能定时器4 } void Time4_PwmdetectCNF_OnLibFunc(u16 arr,u16 psc) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);// ① 使能定时器 4 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //① 使能 GPIOB 和 AFIO 复用功能时钟 //设置引脚PB6为TIM4_CH1复用输入功能,配置为浮空输入 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //TIM_CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;// 复用输入,配置为浮空输入 GPIO_Init(GPIOB, &GPIO_InitStructure); //① 初始化 GPIO //初始化TIM4 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period = arr; // 设置在自动重装载周期值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 设置时钟分割 :TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); // 初始化 TIMx //设置CC1 TIM_ICInitTypeDef TIM_ICInitStructure1; TIM_ICInitStructure1.TIM_Channel=TIM_Channel_1; TIM_ICInitStructure1.TIM_ICSelection=TIM_ICSelection_DirectTI; //IC1直接映射到TI1上 TIM_ICInitStructure1.TIM_ICFilter=0; //不滤波 TIM_ICInitStructure1.TIM_ICPrescaler=TIM_ICPSC_DIV1; //不分频 TIM_ICInitStructure1.TIM_ICPolarity=TIM_ICPolarity_Rising; //上述沿捕获 TIM_ICInit(TIM4,&TIM_ICInitStructure1); //设置CC2 TIM_ICInitTypeDef TIM_ICInitStructure2; TIM_ICInitStructure2.TIM_Channel=TIM_Channel_2; TIM_ICInitStructure2.TIM_ICSelection=TIM_ICSelection_IndirectTI; //IC2间接接映射到TI1上 TIM_ICInitStructure2.TIM_ICFilter=0; //不滤波 TIM_ICInitStructure2.TIM_ICPrescaler=TIM_ICPSC_DIV1; //不分频 TIM_ICInitStructure2.TIM_ICPolarity=TIM_ICPolarity_Falling; //上述沿捕获 TIM_ICInit(TIM4,&TIM_ICInitStructure2); TIM_SelectSlaveMode(TIM4,TIM_SlaveMode_Reset); TIM_SelectInputTrigger(TIM4,TIM_TS_TI1FP1); //下述两句使能设置已在函数TIM_ICInit中调用函数TI4_Config完成了,故注释掉 // TIM4->CCER |=0x01; //CC1E=1 允许捕获计数器的值到捕获寄存器1中 // TIM4->CCER |=(0x01<<4); //CC2E=1 允许捕获计数器的值到捕获寄存器2中 TIM_Cmd(TIM4,ENABLE); //使能定时器4 } extern __IO uint32_t SysTick_ms_setnums,SysTick_ms_nums; void SysTick_Handler(void) { if(SysTick_ms_nums!=0x00) SysTick_ms_nums--; else SysTick_ms_nums=SysTick_ms_setnums; } 这个stm32嵌入式实验的目的、原理、方法分别是什么
11-21
#include <Arduino.h> #include <SPI.h> #include <ESP32SPISlave.h> #include "spi_slave_server.h" #include <esp32-hal-spi.h> #include "helper.h" // ==================== 配置定义 ==================== #define SPI_SLAVE_ENABLE 1 #define SPI_READ_TIMEOUT 100000 // 微秒级超时 #define RESPONSE_THRESHOLD 256 // 触发响应的总接收字节数 #define SPI_BUFFER_SIZE 256 // 大于67 建议设为128 #define MY_CS 12 // GPIO12 -> CS #define MY_SCK 13 // GPIO13 -> SCK #define MY_MOSI 14 // GPIO14 -> MOSI #define MY_MISO 11 // GPIO11 -> MISO // 命令头定义 #define CMD_HEADER 0xAA #define CMD_SUB_FF 0xFF #define CMD_SUB_00 0x00 // ==================== 全局变量 ==================== ESP32SPISlave slave; uint8_t spi_rx_buf[SPI_BUFFER_SIZE]; // 接收缓冲区 uint8_t spi_tx_buf[SPI_BUFFER_SIZE]; // 发送缓冲区(每次通信回传) static uint8_t spi_tx_cache_buf[RESPONSE_THRESHOLD]; static volatile int spi_tx_cache_buf_cnt = 0; static uint32_t total_received_bytes = 0; // 累计接收字节数 static bool should_respond = false; // 是否需要回复 bool data_received = false; int spi_slave_data_cache_add(uint8_t *data, uint16_t len) { if (len > RESPONSE_THRESHOLD) { len = RESPONSE_THRESHOLD; } memcpy(spi_tx_cache_buf, data, len); spi_tx_cache_buf_cnt = len; //printf_log_hex("CACHE UPDATED", data, len); return 0; } // ==================== 函数声明 ==================== void prepare_response(uint8_t* tx_buf); void print_buffer(const char* tag, const uint8_t* buf, size_t len); void spi_slave_task(void *pvParameters); void spi_slave_server_init(void); /** * 构造响应包:AA 00 RR 01 RR ... 32 RR (共67字节) */ void prepare_response(uint8_t* tx_buf) { memset(tx_buf, 0, SPI_BUFFER_SIZE); tx_buf[0] = CMD_HEADER; for (int i = 0; i < 33; i++) { tx_buf[1 + i * 2] = i; tx_buf[1 + i * 2 + 1] = esp_random() & 0xFF; } } /** * 打印缓冲区(十六进制) */ void print_buffer(const char* tag, const uint8_t* buf, size_t len) { Serial.print("["); Serial.print(tag); Serial.print("] "); for (size_t i = 0; i < len; i++) { if (buf[i] < 0x10) Serial.print("0"); Serial.print(buf[i], HEX); Serial.print(" "); } Serial.println(); } /** * SPI Slave 主任务 */ void spi_slave_task(void *pvParameters) { size_t received_bytes; Serial.println("SPI Slave task started."); while (true) { if (digitalRead(MY_CS) == LOW) { memset(spi_rx_buf, 0, sizeof(spi_rx_buf)); // 判断是否需要发送响应 if (total_received_bytes >= RESPONSE_THRESHOLD) { prepare_response(spi_tx_buf); total_received_bytes = 0; } // 执行传输 received_bytes = slave.transfer(spi_tx_buf, spi_rx_buf, SPI_BUFFER_SIZE, SPI_READ_TIMEOUT); if (received_bytes > 0) { total_received_bytes += received_bytes; Serial.printf("Total RX: %u / %u\n", total_received_bytes, RESPONSE_THRESHOLD); // 打印接收到的数据(可选) // print_buffer("SPI_RX", spi_rx_buf, received_bytes); } } vTaskDelay(1); // 小延时释放 CPU } } /** * 初始化 SPI Slave */ void spi_slave_server_init() { slave.setDataMode(SPI_MODE3); // CPOL=1, CPHA=1 slave.setQueueSize(1); // ✅ 显式使用 SPI3_HOST 更可靠 bool ret = slave.begin(SPI3_HOST, MY_SCK, MY_MISO, MY_MOSI, MY_CS); if (!ret) { Serial.println("❌ Failed to initialize SPI Slave!"); while (1) delay(100); } Serial.println("✅ SPI Slave initialized. Awaiting data..."); // 创建任务 xTaskCreate(spi_slave_task, "spi_slave", 8192, NULL, 2, NULL); } 以上是spi从机代码,其中四个针脚是无法改变的 #include "main.h" #include <WiFi.h> #include "esp_uart_driver.h" #include "uart_msg_analy.h" #include "network_app.h" #include "spi_slave_server.h" uint32_t loop_test_timer_cnt=0; #define UART1_TX_PIN 4 #define UART1_RX_PIN 5 void setup() { delay(100); // 让 ROM 日志输出完成 int httpCode; uart0_init(115200, (void *)0);// 初始化主串口 // 需要放在Setup里初始化 uart1_init(115200, UART1_RX_PIN,UART1_TX_PIN,(void *)uart1_msg_analy);// 配置第二个串口 // 初始化随机数生成器 esp_random(); // 初始化随机数生成器 //wifi_app_init();// 启动WiFi功能 spi_slave_server_init();//初始化SPI从机模式 Serial.printf("wifi spi project done... %s %s\r\n", __DATE__, __TIME__);//打印初始化完成信息 } int test_cnt = 0; char receivedChar = 0; void loop() { uart_process(); if(doDelayMillisTime(2000, &loop_test_timer_cnt, false))//2秒间隔的定时输出,通过loop_test_timer_cnt变量维护定时状态 { Serial.printf("loop... %d\r\n", test_cnt++);//循环输出计数 } vTaskDelay(100 / portTICK_PERIOD_MS); } boolean doDelayMillisTime(uint32_t interval, uint32_t *previousMillis, boolean state)//非阻塞式定时器;state:状态翻转标志 { uint32_t currentMillis = (uint32_t)SYSTEM_TIMER_MS();//获取系统时间 if (currentMillis - *previousMillis >= interval)// interval 定时间隔(ms);previousMillis 存储上次触发时间的指针 { *previousMillis = currentMillis; state = !state; } return state; } void printf_log_hex(char *hex_name, uint8_t *data, uint32_t len)//十六进制数据打印工具 { Serial.printf("%s ,len is:%d \r\n", hex_name, len); for (int i = 0; i < len; i++) { Serial.printf("%02x ", data[i]);//单字节总显示2位 } Serial.printf("\r\n");//保证终端正确换行 } 这是main函数 ESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0xc (RTC_SW_CPU_RST),boot:0x28 (SPI_FAST_FLASH_BOOT) Saved PC:0x42024f06 SPIWP:0xee mode:DIO, clock div:1 load:0x3fce3808,len:0x4bc load:0x403c9700,len:0xbd8 load:0x403cc700,len:0x2a0c entry 0x403c98d0 uart1_init... baud_rate=115200,rx= 5,tx= 4 ✅ SPI Slave initialized. Awaiting data... SPI Slave task started. wifi spi project done... Sep 28 2025 21:01:14 Guru Meditation Error: Core 1 panic'ed (Double exception). Core 1 register dump: PC : 0x4037a616 PS : 0x00040b36 A0 : 0x8037ae33 A1 : 0x3fced340 A2 : 0x00040b36 A3 : 0x00040026 A4 : 0x3fcf0858 A5 : 0x0000004c A6 : 0x3fcf04a0 A7 : 0x00000001 A8 : 0x3fced400 A9 : 0x00000000 A10 : 0x00000054 A11 : 0xffffffff A12 : 0x00000000 A13 : 0x00001800 A14 : 0x00060f23 A15 : 0x00000001 SAR : 0x00000004 EXCCAUSE: 0x00000002 EXCVADDR: 0x00000000 LBEG : 0x400556d5 LEND : 0x400556e5 LCOUNT : 0xfffffff8 Backtrace: 0x4037a613:0x3fced340 0x4037ae30:0x00060923 |<-CORRUPTED ELF file SHA256: c058b642ac1d82ed Rebooting...
09-30
数据驱动的两阶段分布鲁棒(1-范数和∞-范数约束)的电热综合能源系统研究(Matlab代码实现)内容概要:本文围绕“数据驱动的两阶段分布鲁棒(1-范数和∞-范数约束)的电热综合能源系统研究”展开,提出了一种结合数据驱动与分布鲁棒优化方法的建模框架,用于解决电热综合能源系统在不确定性环境下的优化调度问题。研究采用两阶段优化结构,第一阶段进行预决策,第二阶段根据实际场景进行调整,通过引入1-范数和∞-范数约束来构建不确定集,有效刻画风电、负荷等不确定性变量的波动特性,提升模型的鲁棒性和实用性。文中提供了完整的Matlab代码实现,便于读者复现和验证算法性能,并结合具体案例分析了不同约束条件下系统运行的经济性与可靠性。; 适合人群:具备一定电力系统、优化理论和Matlab编程基础的研究生、科研人员及工程技术人员,尤其适合从事综合能源系统、鲁棒优化、不确定性建模等相关领域研究的专业人士。; 使用场景及目标:①掌握数据驱动的分布鲁棒优化方法在综合能源系统中的应用;②理解1-范数和∞-范数在构建不确定集中的作用与差异;③学习两阶段鲁棒优化模型的建模思路与Matlab实现技巧,用于科研复现、论文写作或工程项目建模。; 阅读建议:建议读者结合提供的Matlab代码逐段理解算法实现细节,重点关注不确定集构建、两阶段模型结构设计及求解器调用方式,同时可尝试更换数据或调整约束参数以加深对模型鲁棒性的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值