STM32: Receive SPI bus data in DMA mode and process it according to the protocol

Publisher:EnchantedMagicLatest update time:2018-06-08 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

I. Introduction

To meet the requirements of high-speed data transmission, the SPI bus is used. The MCU (STM32F072 Cortex-M0) receives the SPI data sent by the CPU (18 bytes of data per packet, the starting packet is 0xAA, and the last packet is CheckSum verification). After receiving, the verified data is assigned to the RF and sent to the receiving end.

2. Hardware Circuit

As shown in the figure below, the SPI part uses SPI2, namely PB12 PB13 PB14 PB15

3. Procedure

3.1 SPI Initialization

 SPI is initialized to slave mode, the code is as follows:

  1. void BSP_SPI2_Init(void)  

  2. { SPI_InitTypeDef SPI_InitStructure;  

  3.         GPIO_InitTypeDef GPIO_InitStructure;  

  4.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);   

  5.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);  

  6.         /*!< Configure SPI_FLASH_SPI pins: NSS */      

  7.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;  

  8.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  

  9.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  

  10.         GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;  

  11.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  

  12.         GPIO_Init(GPIOB, &GPIO_InitStructure);   

  13.         /*!< Configure SPI_FLASH_SPI pins: SCK */      

  14.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;  

  15.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  

  16.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  

  17.         GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;  

  18.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  

  19.         GPIO_Init(GPIOB, &GPIO_InitStructure);   

  20.       /*!< Configure SPI_FLASH_SPI pins: MISO */  

  21.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;  

  22.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  

  23.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  

  24.         GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;  

  25.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  

  26.         GPIO_Init(GPIOB, &GPIO_InitStructure);  

  27.          /*!< Configure SPI_FLASH_SPI pins: MOSI */  

  28.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;  

  29.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  

  30.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  

  31.         GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;  

  32.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  

  33.         GPIO_Init(GPIOB, &GPIO_InitStructure);   

  34.         /*!< PinAFConfig */  

  35.         GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_0);    

  36.     GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_0);    

  37.     GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_0);  

  38.     GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_0);   

  39.     /* Deselect the FLASH: Chip Select high */  

  40.     /* SPI2 configuration */  

  41.     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  

  42.     SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;  

  43.     SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;  

  44.     SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;  

  45.     SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;////  

  46.     SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;////  

  47.     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;  

  48.     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;  

  49.     SPI_InitStructure.SPI_CRCPolynomial = 7;  

  50.     SPI_Init(SPI2, &SPI_InitStructure);  

  51.     SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);  

  52.     SPI_NSSInternalSoftwareConfig(SPI2, SPI_NSSInternalSoft_Reset);  

  53.     SPI_NSSPulseModeCmd(SPI2,DISABLE);  

  54.     //SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);  

  55.     /* Configure IT */  

  56.     /* Enable SPI2 */  

  57.           

  58.     SPI_Cmd(SPI2, ENABLE);  

  59.           

  60.           

  61.            

  62. }  

3.2 DMA Initialization

According to the data sheet, the DMA channel of SPI2_RX is 4. Since we need to continuously obtain data from SPI, DMA is set to Circle mode. Since the data length received by SPI is fixed at 18, we can also set BufferSize to 18. The advantage of this is that we do not need to check the flag of DMA transfer completion, but only need to check whether the data in BUFFER has changed. Once there is a change, we can directly load the data from the beginning to the end. Of course, this processing is only applicable to fixed-length data reception. If the data received by DMA is not fixed-length, it needs to be compared with the value of the DMA count value CNTR register.

  1. void SPI2_DMA_Init(void)  

  2.  {  

  3.   DMA_Cmd(DMA1_Channel4, DISABLE);  

  4.   DMA_DeInit(DMA1_Channel4);   

  5.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  

  6.   //DMA_InitStructure.DMA_FIFOMode  

  7.   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(SPI2->DR));  

  8.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DstBuffer;  

  9.   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  

  10.   DMA_InitStructure.DMA_BufferSize = 18;  

  11.   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  

  12.   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  

  13.   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  

  14.   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  

  15.   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA_Mode_Normal DMA_Mode_Circular  

  16.   DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;  

  17.   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  

  18.   DMA_Init(DMA1_Channel4, &DMA_InitStructure);  

  19.     /* Enable DMA1 Channel1 Transfer Complete interrupt */  

  20.   #if 0  

  21.     DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);  

  22.   /* Enable DMA1 channel4 IRQ Channel */  

  23.   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_5_6_7_IRQn;  

  24.   NVIC_InitStructure.NVIC_IRQChannelPriority = 0;  

  25.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

  26.   NVIC_Init(&NVIC_InitStructure);  

  27.     #endif  

  28.   SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);//  

  29.   /* Enable DMA1 Channel4 transfer */  

  30.   DMA_Cmd(DMA1_Channel4, ENABLE);  

  31.  }  

3.3 Data comparison and update

The function of this part is to read the data in DMABuffer in a loop. If the data sent therein changes, it means that new data has been generated. This data will be taken out and processed by the protocol. If there is no data change, no processing will be performed.

  1.  /****************************************************** **************************** 

  2. * @Function : UpdateBuff 

  3. * @Description: Compare 2 strings, if different return 1 and Update to Target 

  4. * @Input: buf1 buf2 size 

  5. * @Output : None 

  6. * @Return : None 

  7. * @Auth : Solen 2016/8/30 

  8. *************************************************** *******************************/  

  9.  uint8_t UpdateBuff(uint8_t *Src,uint8_t *Taget,uint8_t Size)  

  10.  {  

  11.      uint8_t Data_Updated = 0;  

  12.       for(uint8_t i = 0;i

  13.      {  

  14.          if(Src[i]!=Taget[i])  

  15.          {  

  16.              Taget[i] = Src[i];  

  17.              Data_Updated = 1;  

  18.          }  

  19.      }  

  20.      if(Data_Updated == 1)  

  21.          return 1;  

  22.      else  

  23.          return 0;  

  24.  }  


3.4 Protocol Analysis

According to the result of 3.3, if there is new data, protocol analysis is performed. That is, AA is used as the data header to obtain the packet data. Data processing is completed.

  1. /****************************************************** **************************** 

  2. * @Function : Packet_Align 

  3. * @Description: Mainly Used for DBG to certificate SPI - DMA 

  4. * @Input : None 

  5. * @Output : None 

  6. * @Return : None 

  7. * @Auth : Solen 2016/8/30 

  8. *************************************************** *******************************/  

  9.  void Packet_Align(void)  

  10.  {  

  11.      static uint8_t Packet_Index = 0;  

  12.      static uint8_t Find_Header = 0;  

  13.     for(uint8_t i = 0; i < 18; i++)  

  14.      {  

  15.            if(Find_Header == 0) //Need to Find Headerk  

  16.              {  

  17.                  if(TgtBuffer[i] == 0xAA)  

  18.                  {  

  19.                      Find_Header = 1;  

  20.                      Packet_Index = 0;  

  21.                      ThrDimen_Packet_Data[Packet_Index] = 0xAA;  

  22.                  }  

  23.              }  

  24.              else  

  25.              {  

  26.                     Packet_Index++;  

  27.                   ThrDimen_Packet_Data[Packet_Index] = TgtBuffer[i];  

  28.                   if(Packet_Index >=17)  

  29.                     {  

  30.                         Find_Header = 0;  

  31.                         Data_Finished = 1;  

  32.                     }  

  33.              }  

  34.      }  

  35.  }  


Keywords:STM32 Reference address:STM32: Receive SPI bus data in DMA mode and process it according to the protocol

Previous article:STM32 serial bus idle detection
Next article:STM32 HAL library, configure serial port DMA reception and idle interrupt

Recommended ReadingLatest update time:2024-11-23 06:26

STM32 sine wave output
STM32 can output sine waves! How? To output sine waves, several peripherals are needed: Timer, DAC, DMA. Timer is used to set the frequency of the sine wave; DAC, as the name implies, converts digital quantities into analog quantities, which is converted into voltage signals here; DMA directly controls the DAC output w
[Microcontroller]
STM8S105K4 uses hardware SPI to read LSM9DS1
Note on using hardware spi to read LSM9DS1 on STM8S105K4 Several elements of SPI configuration: MSB, master-slave, PHASE_EDGE, POLARITY, NSS; The matching of host clock and SPI speed needs to be tested. What is the CRC in the spi initialization function of STM8? When SPI reads LSM9DS1, you need to specify the read add
[Microcontroller]
STM32 UID global unique identification code summary
UID: unique id is different from the Device ID of the microcontroller (distinguishing whether it is a stm32f103 or stm32f030 microcontroller) The stm32f103 series microcontrollers all have UID, 96 bits, which are placed in three 32-bit registers. The base address is 0x1ffff7e8, and the offset addresses are 0, 4, and 8
[Microcontroller]
Reasons and solutions for STM32 RTC crystal oscillator not oscillating
It is a common "industry consensus" that the RTC crystal oscillator of STM32 often fails to oscillate. Many people ask for help on various electronic forums with questions like "Ask an expert for advice! What should I do if the RTC crystal oscillator does not oscillate?", and the answer can basically be summarized as
[Microcontroller]
Reasons and solutions for STM32 RTC crystal oscillator not oscillating
stm32 HardFault_Handler debugging and problem finding method
stm32 HardFault_Handler debugging and problem finding method  There are two main reasons why HardFault_Handler failure occurs in STM32: 1. Memory overflow or out-of-bounds access. This requires standardizing the code when writing the program yourself, and you need to slowly troubleshoot when you encounter it. 2. Stack
[Microcontroller]
stm32 HardFault_Handler debugging and problem finding method
Configuration issues of STM32 projects with different external crystal oscillators
Problems encountered: The same serial port configuration code can be output normally on one 407 development board, but garbled characters appear when it is switched to another 407 development board. After checking the serial port output waveform, it is found that there is no problem with the level conversion chip, but
[Microcontroller]
STM32 study notes serial port remapping
When designing the schematic diagram, I found that there was a conflict between the pin allocations and needed to remap the pins. I learned from the manual that there are many I/O ports on the STM32, and there are also many built-in peripherals such as: I2C, ADC, ISP, USART, etc. In order to save lead pins, these buil
[Microcontroller]
How to use ST's library to develop STM32
The chip I use is STM32F103VET and the compiler is IAR ARM V5.5, the debugger is JLINK V8 1, download the ST library, the current version is STM32F10x_StdPeriph_Lib_V3.3.0, unzip it, and then copy the entire Libraries to your working directory. The Project directory is a lot of demonstration codes, you can refer to h
[Microcontroller]
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号