STM32F103 implements DMA to receive serial port data of indefinite length

Publisher:NanoScribeLatest update time:2019-01-07 Source: eefocusKeywords:STM32F103 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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:

https://mp.csdn.net/postedit

Keywords:STM32F103 Reference address:STM32F103 implements DMA to receive serial port data of indefinite length

Previous article:STM32 serial port DMA receives variable length data
Next article:STM32F103 DMA experiment, memory sends data to serial port 1 via DMA

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components
Guess you like

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号