esp32开发与应用(和stm32f103用spi通信) 【 声明版权所有欢迎转载请勿用于商业用途。 联系信箱feixiaoxing 163.com】现在esp32和mcu一起出现的场合很多前者适合网络传输和屏幕显示后者则多出现在工业场景。所以两者一起出现就可以发挥各自的优势。但是两个一起合作也有通信的需求。虽然用ttl可以解决通信的问题但是速率比较低不太方便我们一般还是用spi会感觉比较简单一点。1、mcu做spi hostesp32做spi slave之所以会这样是因为很多时候都是采集数据的要求这个时候用mcu做master方便一点。2、gnd务必对接不管是测试的时候还是部署的时候两个模块的gnd需要互联。3、pin连接目前esp32的pin是5/18/19/23而mcu这边的pin是pa4/pa5/pa6/pa7。两者的连接方式是这样的5连接pa418连接pa519连接pa623连接pa7。4、esp32需要主动发起通信怎么办一般是通过gpio让mcu触发一个中断。5、代码部分这部分代码可以让ai写也可以。首先写mcu的代码#include stm32f10x.h #define SPI_CS_LOW() GPIO_ResetBits(GPIOA, GPIO_Pin_4) #define SPI_CS_HIGH() GPIO_SetBits(GPIOA, GPIO_Pin_4) void SPI1_Master_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE); // SCK(PA5), MOSI(PA7) 复用推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // MISO(PA6) 浮空输入 GPIO_InitStructure.GPIO_Pin GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); // NSS(PA4) 用普通GPIO推挽输出软件控制片选 GPIO_InitStructure.GPIO_Pin GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); SPI_CS_HIGH(); // 默认不选中 SPI_InitStructure.SPI_Direction SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode SPI_Mode_Master; SPI_InitStructure.SPI_DataSize SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS SPI_NSS_Soft; // 软件NSS用GPIO4手动拉 SPI_InitStructure.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_64; // 72MHz/641.125MHz先低速验证 SPI_InitStructure.SPI_FirstBit SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial 7; SPI_Init(SPI1, SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); } uint8_t SPI1_TransferByte(uint8_t data) { while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) RESET); SPI_I2S_SendData(SPI1, data); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) RESET); return SPI_I2S_ReceiveData(SPI1); } // 简单延时根据你的系统时钟自行调整或换成systick延时 void delay_us(uint32_t us) { for (uint32_t i 0; i us * 8; i) __NOP(); } void SPI1_TransferBuffer(uint8_t *tx, uint8_t *rx, uint16_t len) { SPI_CS_LOW(); delay_us(10); // 给ESP32 slave一点反应时间非常关键 for (uint16_t i 0; i len; i) { rx[i] SPI1_TransferByte(tx[i]); } SPI_CS_HIGH(); } int main(void) { SPI1_Master_Init(); uint8_t tx_buf[4] {0x11, 0x22, 0x33, 0x44}; uint8_t rx_buf[4] {0}; while (1) { SPI1_TransferBuffer(tx_buf, rx_buf, 4); // rx_buf 里是 ESP32 回传的数据 for (volatile int i 0; i 500000; i); // 简单延时 } }然后是esp32的代码#include driver/spi_slave.h #include esp_log.h #include freertos/FreeRTOS.h #include freertos/task.h #include string.h #define GPIO_MOSI 23 #define GPIO_MISO 19 #define GPIO_SCLK 18 #define GPIO_CS 5 static const char *TAG SPI_SLAVE; void app_main(void) { esp_err_t ret; spi_bus_config_t buscfg { .mosi_io_num GPIO_MOSI, .miso_io_num GPIO_MISO, .sclk_io_num GPIO_SCLK, .quadwp_io_num -1, .quadhd_io_num -1, }; spi_slave_interface_config_t slvcfg { .mode 0, // 对应CPOL0, CPHA0要和STM32一致 .spics_io_num GPIO_CS, .queue_size 3, .flags 0, }; // 初始化SPI从机用DMA ret spi_slave_initialize(SPI2_HOST, buscfg, slvcfg, SPI_DMA_CH_AUTO); ESP_ERROR_CHECK(ret); WORD_ALIGNED_ATTR uint8_t recvbuf[4] {0}; WORD_ALIGNED_ATTR uint8_t sendbuf[4] {0xA1, 0xA2, 0xA3, 0xA4}; // 要回传给STM32的数据 while (1) { spi_slave_transaction_t t {0}; t.length 4 * 8; // 单位bit t.tx_buffer sendbuf; t.rx_buffer recvbuf; // 阻塞等待STM32发起一次传输 ret spi_slave_transmit(SPI2_HOST, t, portMAX_DELAY); if (ret ESP_OK) { ESP_LOGI(TAG, recv: %02X %02X %02X %02X, recvbuf[0], recvbuf[1], recvbuf[2], recvbuf[3]); // 根据收到的数据更新下一次要回传的内容 sendbuf[0]; // 举例简单自增实际按你的协议处理 } } }6、测试测试的时候一般先把esp32准备插好之后再接入mcu。这个时候不出意外就可以在esp32这边看到源源不断的信息打印了。

相关新闻

最新新闻

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现 【免费下载链接】serenity The Serenity Operating System 🐞 项目地址: https://gitcode.com/GitHub_Trending/se/serenity 导读 本文以 getopt(3) 手册 为核心&a…

2026/10/1 19:32:24
轻量服务器还是ECS?大促云服务器选购与避坑实战指南

轻量服务器还是ECS?大促云服务器选购与避坑实战指南

每年大促节点,群里永远有人在问同一个问题:“38元的轻量服务器到底怎么抢?为什么我每次点进去都是已售罄?68元直购和99元的ECS我到底选哪个?”作为一个常年帮团队和自己采购云服务器的老用户,我太清楚这种纠…

2026/9/30 21:32:07
为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南 【免费下载链接】agents Multi-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity 项目地址:…

2026/9/30 19:41:56
PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署 【免费下载链接】PaddleOCR Turn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between i…

2026/10/1 19:32:23
Spring源码解析:构造器注入的类型转换与候选匹配机制

Spring源码解析:构造器注入的类型转换与候选匹配机制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 19:32:35
openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由 【免费下载链接】openai-agents-python A lightweight, powerful framework for multi-agent workflows 项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-pyth…

2026/9/30 21:32:11

日新闻

周新闻

月新闻