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:
void BSP_SPI2_Init(void)
{ SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
/*!< Configure SPI_FLASH_SPI pins: NSS */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*!< Configure SPI_FLASH_SPI pins: SCK */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*!< Configure SPI_FLASH_SPI pins: MISO */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*!< Configure SPI_FLASH_SPI pins: MOSI */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*!< PinAFConfig */
GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_0);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_0);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_0);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_0);
/* Deselect the FLASH: Chip Select high */
/* SPI2 configuration */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
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_Hard;////
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);
SPI_NSSInternalSoftwareConfig(SPI2, SPI_NSSInternalSoft_Reset);
SPI_NSSPulseModeCmd(SPI2,DISABLE);
//SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);
/* Configure IT */
/* Enable SPI2 */
SPI_Cmd(SPI2, ENABLE);
}
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.
void SPI2_DMA_Init(void)
{
DMA_Cmd(DMA1_Channel4, DISABLE);
DMA_DeInit(DMA1_Channel4);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//DMA_InitStructure.DMA_FIFOMode
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(SPI2->DR));
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DstBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 18;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA_Mode_Normal DMA_Mode_Circular
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
/* Enable DMA1 Channel1 Transfer Complete interrupt */
#if 0
DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
/* Enable DMA1 channel4 IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_5_6_7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);//
/* Enable DMA1 Channel4 transfer */
DMA_Cmd(DMA1_Channel4, ENABLE);
}
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.
/****************************************************** ****************************
* @Function : UpdateBuff
* @Description: Compare 2 strings, if different return 1 and Update to Target
* @Input: buf1 buf2 size
* @Output : None
* @Return : None
* @Auth : Solen 2016/8/30
*************************************************** *******************************/
uint8_t UpdateBuff(uint8_t *Src,uint8_t *Taget,uint8_t Size)
{
uint8_t Data_Updated = 0;
for(uint8_t i = 0;i
{
if(Src[i]!=Taget[i])
{
Taget[i] = Src[i];
Data_Updated = 1;
}
}
if(Data_Updated == 1)
return 1;
else
return 0;
}
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.
/****************************************************** ****************************
* @Function : Packet_Align
* @Description: Mainly Used for DBG to certificate SPI - DMA
* @Input : None
* @Output : None
* @Return : None
* @Auth : Solen 2016/8/30
*************************************************** *******************************/
void Packet_Align(void)
{
static uint8_t Packet_Index = 0;
static uint8_t Find_Header = 0;
for(uint8_t i = 0; i < 18; i++)
{
if(Find_Header == 0) //Need to Find Headerk
{
if(TgtBuffer[i] == 0xAA)
{
Find_Header = 1;
Packet_Index = 0;
ThrDimen_Packet_Data[Packet_Index] = 0xAA;
}
}
else
{
Packet_Index++;
ThrDimen_Packet_Data[Packet_Index] = TgtBuffer[i];
if(Packet_Index >=17)
{
Find_Header = 0;
Data_Finished = 1;
}
}
}
}
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
- Popular Resources
- Popular amplifiers
- Naxin Micro and Xinxian jointly launched the NS800RT series of real-time control MCUs
- How to learn embedded systems based on ARM platform
- Summary of jffs2_scan_eraseblock issues
- Application of SPCOMM Control in Serial Communication of Delphi7.0
- Using TComm component to realize serial communication in Delphi environment
- Bar chart code for embedded development practices
- Embedded Development Learning (10)
- Embedded Development Learning (8)
- Embedded Development Learning (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Intel promotes AI with multi-dimensional efforts in technology, application, and ecology
- ChinaJoy Qualcomm Snapdragon Theme Pavilion takes you to experience the new changes in digital entertainment in the 5G era
- Infineon's latest generation IGBT technology platform enables precise control of speed and position
- Two test methods for LED lighting life
- Don't Let Lightning Induced Surges Scare You
- Application of brushless motor controller ML4425/4426
- Easy identification of LED power supply quality
- World's first integrated photovoltaic solar system completed in Israel
- Sliding window mean filter for avr microcontroller AD conversion
- What does call mean in the detailed explanation of ABB robot programming instructions?
- STMicroelectronics discloses its 2027-2028 financial model and path to achieve its 2030 goals
- 2024 China Automotive Charging and Battery Swapping Ecosystem Conference held in Taiyuan
- State-owned enterprises team up to invest in solid-state battery giant
- The evolution of electronic and electrical architecture is accelerating
- The first! National Automotive Chip Quality Inspection Center established
- BYD releases self-developed automotive chip using 4nm process, with a running score of up to 1.15 million
- GEODNET launches GEO-PULSE, a car GPS navigation device
- Should Chinese car companies develop their own high-computing chips?
- Infineon and Siemens combine embedded automotive software platform with microcontrollers to provide the necessary functions for next-generation SDVs
- Continental launches invisible biometric sensor display to monitor passengers' vital signs
- Okay, let’s talk about the Internet of Things technology protocol
- On-line debugging method for embedded processors
- About the original picture and packaging
- PCB issues for switching power supplies
- [Zero-knowledge ESP8266 tutorial] Quick start 21 world clock demo
- A question about the schematic
- How to modify this PCB
- Annual review: 2019 TI training course highlights, good reviews and gifts!
- GPRS series application 5
- C2000 CLA FAQ: Accessing Peripherals