使用hal库,使stm32f0以dma方式进行串口通信(二)

这里将接着上述生成的代码,编写DMA方式的串口


1. STM32Cube的设置
2. Keil5的代码编写


2. Keil5的代码编写

  1. 生成初始化代码后,先编译一次,获得 .c.h 文件
    使用hal库,使stm32f0以dma方式进行串口通信(二)_第1张图片
  2. 打开 usart.c 文件,在最下方的 /* USER CODE BEGIN 1*/ 的后面添上如下代码
    使用hal库,使stm32f0以dma方式进行串口通信(二)_第2张图片

#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
  return ch;
}

该代码是重定向代码,重定向后可以使用 printf 函数,对串口一进行输出

  1. 打开 main.c 文件,在上方的 /* USER CODE BEGIN PV */ 的后面添上如下代码
    使用hal库,使stm32f0以dma方式进行串口通信(二)_第3张图片

volatile uint8_t RX_Length = 0;     //接收的数据长度                      
volatile uint8_t Recv_Flag = 0;     //接收完成标志位
		 uint8_t RX_Buffer[200];    //缓存区      
const char       Buffer_Size = 200; //缓存区大小

volatile 关键字的原因是因为上述变量将会在中断中发生改变,通过该关键字可以避免一些优化错误。

  1. main.c 中部开启空闲中断
    使用hal库,使stm32f0以dma方式进行串口通信(二)_第4张图片

  __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);			 //使能 idle 中断
  HAL_UART_Receive_DMA(&huart1, RX_Buffer, Buffer_Size );//打开 DMA,接收数据

  1. 打开 stm32f0xx_it.c 文件,在 /* USER CODE BEGIN 0 */ 下方添加代码,引用 main.c 中的变量
    使用hal库,使stm32f0以dma方式进行串口通信(二)_第5张图片

extern volatile uint8_t RX_Length;
extern volatile uint8_t Recv_Flag;
extern uint8_t  RX_Buffer[200];
extern char     Buffer_Size;

  1. 滑到下方,在 /* USER CODE BEGIN USART1_IRQn 0 */ 下方添加代码,即进入中断后需要进行的处理
    使用hal库,使stm32f0以dma方式进行串口通信(二)_第6张图片

uint32_t temp_flag = 0;
uint32_t temp;
temp_flag =__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE);//获取IDLE标志位
if(temp_flag != RESET)									//idle标志被置位
{ 
    __HAL_UART_CLEAR_IDLEFLAG(&huart1);	//清除标志位
    temp = huart1.Instance->ISR;		//清除状态寄存器 ISR
    temp = huart1.Instance->RDR; 		//读取数据寄存器中 RDR 的数据
    HAL_UART_DMAStop(&huart1); 
	temp = hdma_usart1_rx.Instance->CNDTR;//获取 DMA 中未传输的数据个数
    RX_Length = Buffer_Size - temp;     
    Recv_Flag = 1;  					//标志位置1    
 }

  1. 回到 main.c,创建一个数据处理函数,先在 /* USER CODE BEGIN PFP */ 下方写下函数原型
    使用hal库,使stm32f0以dma方式进行串口通信(二)_第7张图片

void Print_Recv_Data( void );

  1. 滑到下方,在 /* USER CODE BEGIN 4 */ 下方编写该函数体
    使用hal库,使stm32f0以dma方式进行串口通信(二)_第8张图片

void Print_Recv_Data( void )
{
  if(Recv_Flag == 1)        
  {
      printf("RX_Length = %d\r\n", RX_Length);                     
      HAL_UART_Transmit(&huart1, RX_Buffer, RX_Length, 0xFFFF); 
      for(uint8_t i=0; i < RX_Length; i++)
      {
         RX_Buffer[i] = 0;	//清空缓存
      }
      RX_Length = 0;		//清除计数
      Recv_Flag = 0;		//清除标志位
   }

}

  1. 回到主函数中部,在 /* USER CODE BEGIN 3 */ 下方编写主函数的内容
    使用hal库,使stm32f0以dma方式进行串口通信(二)_第9张图片

	  if( Recv_Flag == 1)
	  {
		  printf("********该程序将会打印出输入的数据长度和输入的数据********\r\n");	
		  Print_Recv_Data();
		  HAL_UART_Receive_DMA(&huart1, RX_Buffer, Buffer_Size);
	  }

  1. 编译后没有错误,将代码烧写到 MCU 中,运行结果如下
    使用hal库,使stm32f0以dma方式进行串口通信(二)_第10张图片

如有还不明白的地方,可以看一下这位dalao的博客,我也是在他的博客的理解上进行编程的,这是博客地址,顺便再次赞美dalao:白菜没我白

你可能感兴趣的:(STM32)