单片机SPI主从机通信

单片机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