I have been debugging the STM32F103 development board these days. I need to receive a certain length of continuous data. When the data stream is received, the serial port reception interrupt is triggered. The length of the data stream is calculated and the data is transferred to the memory.
main.c
// DMA memory to peripheral (serial port) data transmission experiment
#include "stm32f10x.h"
#include "bsp_usart_dma.h"
#include "bsp_led.h"
extern uint8_t ReceiveBuff[RECEIVEBUFF_SIZE];
static void Delay(__IO u32 nCount);
/**
* @brief main function
* @param None
* @retval None
*/
int main(void)
{
uint16_t i;
/* Initialize USART */
USART_Config();
/* Configure to use DMA mode */
USARTx_DMA_Config();
USARTx_NVIC_Config();
/* Configure RGB color lights */
LED_GPIO_Config();
//printf("\r\n USART1 DMA TX 测试 \r\n");
/*Fill in the data to be sent*/
for(i=0;i { ReceiveBuff[i] = 'P'; } /*To demonstrate that DMA continues to run while the CPU can handle other things, continue to use DMA to send data, the amount is very large, * Long-term operation may cause the computer serial port debugging assistant to freeze and the mouse to fly around. *Or change the loop mode in DMA configuration to single mode*/ /* The CPU is idle at this time and can do other things*/ //For example, control LEDs at the same time while(1) { LED1_TOGGLE Delay(0xFFFFF); } } static void Delay(__IO uint32_t nCount) //Simple delay function { for(; nCount != 0; nCount--); } /*********************************************END OF FILE**********************/ bsp_usart_dma.c #include "bsp_usart_dma.h" uint8_t ReceiveBuff[RECEIVEBUFF_SIZE]; /** * @brief USART GPIO configuration, working parameter configuration * @param None * @retval None */ void USART_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; // Turn on the serial port GPIO clock DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); // Turn on the clock of the serial port peripheral DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE); // Configure the GPIO of USART Tx to push-pull multiplexing mode GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); // Configure the GPIO of USART Rx to floating input mode GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); //Configure the working parameters of the serial port //Configure baud rate USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE; //Configure the data word length USART_InitStructure.USART_WordLength = USART_WordLength_8b; //Configure stop bits USART_InitStructure.USART_StopBits = USART_StopBits_1; //Configure the check digit USART_InitStructure.USART_Parity = USART_Parity_No ; // Configure hardware flow control USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //Configure the working mode, send and receive together USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // Complete the initialization configuration of the serial port USART_Init(DEBUG_USARTx, &USART_InitStructure); // Enable idle interrupt USART_ITConfig(DEBUG_USARTx, USART_IT_IDLE, ENABLE); /* Enable USART1 DMA reception */ USART_DMACmd(DEBUG_USARTx, USART_DMAReq_Rx, ENABLE); // Enable the serial port USART_Cmd(DEBUG_USARTx, ENABLE); } /***************** Send a byte***********************/ void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch) { /* Send one byte of data to USART */ USART_SendData(pUSARTx,ch); /* Wait for the send data register to be empty*/ while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } /****************** Send 8-bit array************************/ void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num) { uint8_t i; for(i=0; i { /* Send one byte of data to USART */ Usart_SendByte(pUSARTx,array[i]); } /* Wait for sending to complete */ while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET); } /***************** Send string *************************/ void Usart_SendString( USART_TypeDef * pUSARTx, char *str) { unsigned int k=0; do { Usart_SendByte( pUSARTx, *(str + k) ); k++; } while(*(str + k)!='\0'); /* Wait for sending to complete */ while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) {} } /***************** Send a 16-digit number***********************/ void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch) { uint8_t temp_h, temp_l; /* Take out the high eight bits*/ temp_h = (ch&0XFF00)>>8; /* Take out the lower eight bits*/ temp_l = ch&0XFF; /* Send the high eight bits */ USART_SendData(pUSARTx,temp_h); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); /* Send the lower eight bits */ USART_SendData(pUSARTx,temp_l); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } ///Redirect the C library function printf to the serial port, and you can use the printf function after redirection int fputc(int ch, FILE *f) { /* Send a byte of data to the serial port */ USART_SendData(DEBUG_USARTx, (uint8_t) ch); /* Wait for sending to complete */ while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET); return (ch); } ///Redirect the C library function scanf to the serial port, rewrite it to use scanf, getchar and other functions int fgetc(FILE *f) { /* Wait for serial port input data*/ while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET); return (int)USART_ReceiveData(DEBUG_USARTx); } /** * @brief USARTx RX NVIC configuration, peripheral to memory (DR->USART1) * @param None * @retval None */ void USARTx_DMA_Config(void) { DMA_InitTypeDef DMA_InitStructure; // Start DMA clock RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // Set DMA source address: serial port data register address*/ DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS; // Memory address (pointer to the variable to be transferred) DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ReceiveBuff; // Direction: from peripherals to memory DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // Transfer size DMA_InitStructure.DMA_BufferSize = RECEIVEBUFF_SIZE; // The peripheral address does not increase DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // Memory address increment DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // Peripheral data unit DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // Memory data unit DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // DMA mode, one-shot or cyclic mode DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // Priority: Medium DMA_InitStructure.DMA_Priority = DMA_Priority_High; // Disable memory-to-memory transfers DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //Configure DMA channel DMA_Init(USART_RX_DMA_CHANNEL, &DMA_InitStructure); // Enable DMA DMA_Cmd (USART_RX_DMA_CHANNEL,ENABLE); } //Restore the DMA pointer void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx) { DMA_Cmd(DMA_CHx, DISABLE ); //Disable the channel indicated by USART1 TX DMA1 DMA_SetCurrDataCounter(DMA_CHx, RECEIVEBUFF_SIZE); //DMA channel DMA buffer size DMA_Cmd(DMA_CHx, ENABLE); //Open the channel indicated by USART1 TX DMA1 } /** * @brief USARTx RX NVIC configuration, peripheral to memory (DR->USART1) * @param None * @retval None */ void USARTx_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); /* Enable the USART Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } //Serial port interrupt function void USART1_IRQHandler(void) //Serial port 1 interrupt service routine { uint8_t Usart1_Rec_Cnt; if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //Receive interrupt (the received data must end with 0x0d 0x0a) { USART_ReceiveData(USART1); //Read data Note: This sentence is required, otherwise the interrupt flag cannot be cleared. Usart1_Rec_Cnt = RECEIVEBUFF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5); //Calculate the length of the data in this frame //***********Frame data processing function************// printf ("Thelenght:%d\r\n",Usart1_Rec_Cnt); printf ("The data:\r\n"); Usart_SendArray(DEBUG_USARTx, ReceiveBuff, RECEIVEBUFF_SIZE); printf ("\r\nOver! \r\n"); //*************************************// USART_ClearITPendingBit(USART1,USART_IT_IDLE); //Clear interrupt flag MYDMA_Enable(DMA1_Channel5); //Restore DMA pointer and wait for the next reception } } bsp_usart_dma.h #ifndef __USARTDMA_H #define __USARTDMA_H #include "stm32f10x.h" #include // Serial port working parameter macro definition #define DEBUG_USARTx USART1 #define DEBUG_USART_CLK RCC_APB2Periph_USART1 #define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO pin macro definition #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOA #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9 #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10 //DMA request channel corresponding to the serial port #define USART_TX_DMA_CHANNEL DMA1_Channel4 #define USART_RX_DMA_CHANNEL DMA1_Channel5 //Peripheral register address #define USART_DR_ADDRESS (USART1_BASE+0x04) // The amount of data to send at one time #define RECEIVEBUFF_SIZE 50 void USART_Config(void); void USARTx_DMA_Config(void); #endif /* __USARTDMA_H */ After compilation, it runs successfully, and the running results are:
Previous article:STM32 serial port DMA receives variable length data
Next article:STM32F103 DMA experiment, memory sends data to serial port 1 via DMA
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications