当前位置: 首页 > news >正文

单片机SPI主从机通信

一、需求

为扩展更多资源,降低和硬件设备通信的占用时间,主MCUf429需要和从机mcu f103进行通信,f103接入4片SPI ADC 4片 SPI DAC 一片 输出扩展,8片 MAX6675热电偶温度 2片 MAX31865 铂电阻温度,16个输入信号

主机stm32f429 spi3 master,从机stm32f103c8 spi slave,主机每秒和从机通信20次,每次50字节,都使用HAL

一、设计的硬件连接

MASTER F429slave f103
SPI_CLKPC10PA5
SPI_MOSIPC12PA7
SPI_MISOPB4PA6
SPI_CSPA4PA4

二、软件代码

主机比较简单 就使用HAL_SPI_TransmitReceive函数进行读取。

从机代码 采用中断的方式

spi1_slave_it.c

#include "spi1_slave_it.h" #include <string.h> static uint8_t spi1_it_tx_next[SPI1_SLAVE_IT_FRAME_SIZE]; static uint8_t spi1_it_tx_work[SPI1_SLAVE_IT_FRAME_SIZE]; static uint8_t spi1_it_rx_work[SPI1_SLAVE_IT_FRAME_SIZE]; static uint8_t spi1_it_rx_last[SPI1_SLAVE_IT_FRAME_SIZE]; static volatile uint8_t spi1_it_frame_ready = 0U; static volatile uint8_t spi1_it_busy = 0U; static volatile uint32_t spi1_it_frame_count = 0U; static uint32_t SPI1_Slave_IT_EnterCritical(void) { uint32_t primask = __get_PRIMASK(); __disable_irq(); return primask; } static void SPI1_Slave_IT_ExitCritical(uint32_t primask) { if (primask == 0U) { __enable_irq(); } } static void SPI1_Slave_IT_CopyFrame(uint8_t *pDst, const uint8_t *pSrc, uint16_t size) { uint16_t copySize = size; if (copySize > SPI1_SLAVE_IT_FRAME_SIZE) { copySize = SPI1_SLAVE_IT_FRAME_SIZE; } memset(pDst, 0, SPI1_SLAVE_IT_FRAME_SIZE); if ((pSrc != NULL) && (copySize > 0U)) { memcpy(pDst, pSrc, copySize); } } void SPI1_Slave_IT_Init(void) { uint32_t primask = SPI1_Slave_IT_EnterCritical(); memset(spi1_it_tx_next, 0, sizeof(spi1_it_tx_next)); memset(spi1_it_tx_work, 0, sizeof(spi1_it_tx_work)); memset(spi1_it_rx_work, 0, sizeof(spi1_it_rx_work)); memset(spi1_it_rx_last, 0, sizeof(spi1_it_rx_last)); spi1_it_frame_ready = 0U; spi1_it_busy = 0U; spi1_it_frame_count = 0U; SPI1_Slave_IT_ExitCritical(primask); HAL_NVIC_SetPriority(SPI1_IRQn, 1, 0); HAL_NVIC_EnableIRQ(SPI1_IRQn); } HAL_StatusTypeDef SPI1_Slave_IT_Start(void) { HAL_StatusTypeDef status; uint32_t primask = SPI1_Slave_IT_EnterCritical(); if (spi1_it_busy != 0U) { SPI1_Slave_IT_ExitCritical(primask); return HAL_BUSY; } memcpy(spi1_it_tx_work, spi1_it_tx_next, SPI1_SLAVE_IT_FRAME_SIZE); memset(spi1_it_rx_work, 0, SPI1_SLAVE_IT_FRAME_SIZE); spi1_it_busy = 1U; SPI1_Slave_IT_ExitCritical(primask); status = HAL_SPI_TransmitReceive_IT(&hspi1, spi1_it_tx_work, spi1_it_rx_work, SPI1_SLAVE_IT_FRAME_SIZE); if (status != HAL_OK) { primask = SPI1_Slave_IT_EnterCritical(); spi1_it_busy = 0U; SPI1_Slave_IT_ExitCritical(primask); } return status; } HAL_StatusTypeDef SPI1_Slave_IT_SetTxData(const uint8_t *pData, uint16_t size) { uint32_t primask = SPI1_Slave_IT_EnterCritical(); SPI1_Slave_IT_CopyFrame(spi1_it_tx_next, pData, size); if (spi1_it_busy == 0U) { memcpy(spi1_it_tx_work, spi1_it_tx_next, SPI1_SLAVE_IT_FRAME_SIZE); } SPI1_Slave_IT_ExitCritical(primask); return HAL_OK; } HAL_StatusTypeDef SPI1_Slave_IT_GetRxData(uint8_t *pData, uint16_t size) { uint16_t copySize = size; uint32_t primask; if ((pData == NULL) || (size == 0U)) { return HAL_ERROR; } if (copySize > SPI1_SLAVE_IT_FRAME_SIZE) { copySize = SPI1_SLAVE_IT_FRAME_SIZE; } primask = SPI1_Slave_IT_EnterCritical(); memcpy(pData, spi1_it_rx_last, copySize); spi1_it_frame_ready = 0U; SPI1_Slave_IT_ExitCritical(primask); return HAL_OK; } uint8_t SPI1_Slave_IT_IsFrameReady(void) { return spi1_it_frame_ready; } uint32_t SPI1_Slave_IT_GetFrameCount(void) { return spi1_it_frame_count; } void SPI1_Slave_IT_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { if (hspi->Instance != SPI1) { return; } memcpy(spi1_it_rx_last, spi1_it_rx_work, SPI1_SLAVE_IT_FRAME_SIZE); memcpy(spi1_it_tx_work, spi1_it_tx_next, SPI1_SLAVE_IT_FRAME_SIZE); spi1_it_frame_ready = 1U; spi1_it_frame_count++; spi1_it_busy = 0U; (void)SPI1_Slave_IT_Start(); } void SPI1_Slave_IT_ErrorCallback(SPI_HandleTypeDef *hspi) { if (hspi->Instance != SPI1) { return; } if ((hspi->ErrorCode & HAL_SPI_ERROR_OVR) != 0U) { __HAL_SPI_CLEAR_OVRFLAG(hspi); } spi1_it_busy = 0U; (void)SPI1_Slave_IT_Start(); }

spi1_slave_it.h

#ifndef __SPI1_SLAVE_IT_H #define __SPI1_SLAVE_IT_H #ifdef __cplusplus extern "C" { #endif #include "spi.h" #include <stdint.h> #define SPI1_SLAVE_IT_FRAME_SIZE 100U void SPI1_Slave_IT_Init(void); HAL_StatusTypeDef SPI1_Slave_IT_Start(void); HAL_StatusTypeDef SPI1_Slave_IT_SetTxData(const uint8_t *pData, uint16_t size); HAL_StatusTypeDef SPI1_Slave_IT_GetRxData(uint8_t *pData, uint16_t size); uint8_t SPI1_Slave_IT_IsFrameReady(void); uint32_t SPI1_Slave_IT_GetFrameCount(void); void SPI1_Slave_IT_TxRxCpltCallback(SPI_HandleTypeDef *hspi); void SPI1_Slave_IT_ErrorCallback(SPI_HandleTypeDef *hspi); #ifdef __cplusplus } #endif #endif /* __SPI1_SLAVE_IT_H */

主函数

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_I2C1_Init(); MX_SPI1_Init(); MX_TIM1_Init(); MX_USART1_UART_Init(); MX_SPI2_Init(); /* USER CODE BEGIN 2 */ for (uint16_t i = 0; i < SPI1_APP_FRAME_SIZE; i++) { spi1_tx_payload[i] = (uint8_t)i; } #if (SPI1_SLAVE_USE_DMA == 1U) SPI1_Slave_DMA_Init(); (void)SPI1_Slave_DMA_SetTxData(spi1_tx_payload, SPI1_APP_FRAME_SIZE); (void)SPI1_Slave_DMA_Start(); #else SPI1_Slave_IT_Init(); (void)SPI1_Slave_IT_SetTxData(spi1_tx_payload, SPI1_APP_FRAME_SIZE); (void)SPI1_Slave_IT_Start(); #endif /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_Delay(49); spi1_tx_payload[0]++; #if (SPI1_SLAVE_USE_DMA == 1U) (void)SPI1_Slave_DMA_SetTxData(spi1_tx_payload, SPI1_APP_FRAME_SIZE); if (SPI1_Slave_DMA_IsFrameReady() != 0U) { (void)SPI1_Slave_DMA_GetRxData(spi1_rx_payload, SPI1_APP_FRAME_SIZE); spi1_frame_counter = SPI1_Slave_DMA_GetFrameCount(); } #else (void)SPI1_Slave_IT_SetTxData(spi1_tx_payload, SPI1_APP_FRAME_SIZE); if (SPI1_Slave_IT_IsFrameReady() != 0U) { (void)SPI1_Slave_IT_GetRxData(spi1_rx_payload, SPI1_APP_FRAME_SIZE); spi1_frame_counter = SPI1_Slave_IT_GetFrameCount(); } #endif /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }

三、实现效果

每50ms通信一次

每次的数据100字节

一次600us

主从机工程代码下载连接https://download.csdn.net/download/zd845101500/93170524

http://www.jsqmd.com/news/1256650/

相关文章:

  • 本地千万级图库秒级检索:ImageSearch让你的图片管理不再迷茫
  • 亚克力专用胶工厂如何做到品质领先行业
  • 2026深圳传媒艺考培训机构推荐:5家正规机构实力对比评价与避坑FAQ - 互联网科技品牌测评
  • 深度解析:AI驱动的股票智能分析系统实战指南
  • MapGIS Client for JavaScript坐标系的几何定义,转换
  • 从“被生活推动”,进入“主动创造”。
  • 互斥和同步(生产者消费者模型)
  • sqli通关笔记(1-4,5,9)
  • 如何用AI股票分析系统在5分钟内搭建你的智能投资助手
  • 光刻胶面临的技术挑战与对策(上)
  • Beyond Compare 5密钥生成技术深度解析:从RSA算法到逆向工程实战
  • 如何用GitHub Actions实现股票分析自动化:零成本搭建智能投资助手
  • 魔兽争霸III终极优化插件:3分钟解决经典游戏所有兼容性问题
  • 每日关注:2026年7月24日 GitHub Copilot、Kerberos RC4、NemoClaw 与 NAND Flash 7 条技术动态
  • 如何高效管理多字体项目并提升开发体验?
  • 2026年河北安平金属网片厂家怎么选?看这篇就够了 - 信息热点
  • 音乐聚合革命:如何用单一工具终结平台切换烦恼
  • Tableau•解决问题
  • 信号线和电源线共模电感有什么区别?
  • WorkshopDL技术架构深度解析:如何构建跨平台Steam创意工坊下载引擎
  • 5分钟掌握WSABuilds:Windows上运行Android的终极解决方案
  • 【Rust中级教程】1.4. 内存 Pt.2:栈内存、栈帧(stack frame)、栈指针(stack pointer)
  • 3个维修隐坑|广州打印机打印空白页自查,90%不用更换硒鼓
  • 终极指南:如何用Locale-Emulator免费解决日文游戏乱码问题
  • C#学习进阶
  • maven使用install将jar包编译到本地仓库管理
  • 如何用AI股票分析系统5分钟搭建个人投资决策中心
  • 御坂翻译器:5分钟开启Galgame无障碍体验的终极实时翻译解决方案
  • 御坂翻译器:5分钟开启日系游戏无障碍体验的终极方案
  • Prometheus 监控 Kube-state-metrics 终极实战:Kubernetes 对象状态可观测性全解析