<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)

本节主要讲解串口1的收发通信功能,接收数据以换行符为结束标志(\r\n)。

串口的详细解说可参考《STM32F4XXX中文参考手册》,资料有详细的讲解和说明,文档可跟作者联系索取,或百度搜索也可。

话不多说,开始写代码吧。。

一、打开STM32CubeMX选择对应的芯片型号,后进入开发界面;
详细步骤可参考:
(1)<STM32>STM32CubeMX-工程创建及定时器控制LED灯闪烁(2)
(2)<STM32>STM32CubeMX-基础工程创建及LED灯控制 (1)

二、开始配置操作
1、配置RCC,即晶振的选择配置;
选择"Pinout&Configuration"->“System Core”->“RCC”,如下图步骤1、2、3;
High Speed Clock(HSE):表示外部高速晶振;
High Speed Clock(HSE):表示外部低速晶振,使用RTC实时时钟是一般用这个;
在步骤4、5可选择晶振的配型,“BYPASS Clock Source”和“Crystal/Ceramic Resonator”两种,第一个是旁路时钟源,第二个是晶体/陶瓷谐振器,一般电路使用的是“Crystal/Ceramic Resonator”。
本教程作者选用的高速和低速都是“Crystal/Ceramic Resonator”。
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第1张图片
2、配置SYS,即DEBUG的方式选择

选择"Pinout&Configuration"->“System Core”->“SYS”,如下图步骤1、2、3;
下图步骤4则是选择Debug的方式,一般选择SDW的方式能满足使用,如果想用JTAG也可选择JTAG。

本教程在这里作者选中SDW的方式即“Serial Wire”。
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第2张图片
3、配置串口参数
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第3张图片本次使用的是串口1,串口1默认引脚是PA9和PA10;
配置参数入上图所示:
步骤1,2,3:选择到对应的配置串口,选择后出现中间部分框图;
步骤4:可选择项分为一下几种:
1)Asynchronous:异步通信
2)synchronous :同步通信
3)single Wire(Half-Duplex):单线(半双工)通信
4)Multiprocessor Communication:多处理器通信
5)LrDA :红外通信
6)LIN :LIN通信
7)SmartCard:智能卡

本次教程选用Asynchronous:异步通信即可,主要是做普通串口使用;

步骤5:串口参数配置:
步骤6:参数设置,包含:波特率:115200、字长:8位、校验位:无、停止位:1位;
步骤7:数据方向:接收和发送 、 16位采样;
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第4张图片
步骤8:勾选中断使能

三、工程配置
1、时钟配置:
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第5张图片
如上图所示:选择 步骤1选项,然后再步骤2位置输入系统的主频时钟值,回车确认即可,自动完成。F4系列一般是 168或180,F1系列一般是72.

2、工程输出属性配置
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第6张图片
工程属性配置,如上图所示:
步骤1、2:进入配置界面;
步骤3:输入工程名称;
步骤4:工程存放的目录路径;
步骤5:工程的DMK 和对应的版本选择;使用Keil5的选择”MDK-ARM“
步骤6:堆栈大小的设置,一般用的不大的话,使用默认即可。

3、代码生成器配置
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第7张图片
代码生成器配置如上图:
步骤1、2:进入配置界面;
步骤3:拷贝所以使用到的库到工程中;
步骤4:生成单独的.c和.h文件,方便后续功能添加修改管理;
建议初学者按上图配置即可。

四、代码生成和功能补充测试

1、代码生成
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第8张图片
在以上所有都配置完成后,电机上图 红色1位置,即可生成代码,并在弹出的对话框选择“Open Project”打开项目。

2、代码补充
在打开的工程中补充修改完善代码;
补充修改代码分别在4个文件中进行,根据配置后生成的工程目录如下图所示:
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第9张图片
补充修改完善代码分别对应的文件是“main.c”、“stm32f4xx_it.c”、“usart.c"和"usart.h”,这四个文件,下面分别说明具体修改内容。

1)"stm32f4xx_it.c"文件修改:主要是注释掉,自动生成的串口中断函数,按找下图注释掉,具体如下:
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第10张图片
2)"usart.h"文件修改:主要是添加一些定义等,具体如下所示:

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

extern UART_HandleTypeDef huart1;

/* USER CODE BEGIN Private defines */
#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define RXBUFFERSIZE   			1 //缓存大小
extern uint8_t  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern uint16_t USART_RX_STA;         		//接收状态标记	

/* USER CODE END Private defines */

void MX_USART1_UART_Init(void);

/* USER CODE BEGIN Prototypes */
uint8_t API_USART1_SendData(uint8_t *pData,uint16_t len);
/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif

#endif /* __USART_H__ */

3)"usart.c"修改:主要是定义变量、增加中断处理函数、中断公共回调函数、以及重定向输出函数(用以使用printf),还有一个则是在初始化函数内添加接收中断buf。

变量定义如下:

/* USER CODE BEGIN 0 */
#include "stdio.h"

uint8_t USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
uint16_t USART_RX_STA=0;       //接收状态标记	
uint8_t aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
/* USER CODE END 0 */

初始化函数内添加接收中断buf:如下:

void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
	HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);//开启接收数据
  /* USER CODE END USART1_Init 2 */

}

中断函数如下:

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	uint32_t timeout=0;
	uint32_t maxDelay=0x1FFFF;
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
	timeout=0;
    while (HAL_UART_GetState(&huart1) != HAL_UART_STATE_READY)//等待就绪
	{
	 timeout++;超时处理
     if(timeout>maxDelay) break;		
	}
     
	timeout=0;
	while(HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1
	{
	 timeout++; //超时处理
	 if(timeout>maxDelay) break;	
	}
  /* USER CODE END USART1_IRQn 1 */
}

中断公共回调函数如下:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)//如果是串口1
	{
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了0x0d
			{
				if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到0X0D
			{	
				if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}
	}
	
}

发送函数如下:

uint8_t API_USART1_SendData(uint8_t *pData,uint16_t len)
{
	uint8_t ret = 0;

    if(HAL_UART_Transmit(&huart1,pData,len,5000) != HAL_OK)
    {
		ret = 1;
    }

	return ret;
}

重定向输出如下:

//重定向输出,可用printf函数
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
        
        HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
        return ch;
}

**代码放置位置,建议放在有标识的位置如“USER CODE BEGIN X”和“USER CODE END X”,其中X代表数值1.2.3…;将代码放置于这两句话之间的效果就是,如果重新用STM32CubeMX重新配置这个工程,那么在这两句话之间书写的代码,不会被清理掉,会保留;如果在之两句话之外的位置书写代码,则会被清理掉。**本次工程放置效果如下图所示:
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第11张图片
4)“main.c”文件修改:主要是对输入输出数据进行操作,具体如下:

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	uint16_t RevLen;
	uint8_t i;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(USART_RX_STA&0x8000)	//判断接收到数据
		{
			RevLen = USART_RX_STA&0x3fff;//获取接收数据的长度
			
			printf("接收数据长度为:%d \r\n",RevLen);			//打印输出长度
			printf("接收数据内容为:%s \r\n",USART_RX_BUF);//打印输出接收的数据(字符串的形式)
			
			USART_RX_STA=0;												//清除接收的标志
			memset(USART_RX_BUF,0,USART_REC_LEN);//清除接收的内容
			
		}
		
		i++;
		if(i>=10)	//循环10次
		{
			i=0;
			printf("请输入数据,以回车键结束\r\n");
		}
		HAL_Delay(100);		//延时100ms
		
  }
  /* USER CODE END 3 */
}

3、编译代码和下载运行
1)编译:编译后无错误,如下图所示,如果有错误,根据错误修改错误的位置,然后重新编译,直至编译成功。
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第12张图片
2)下载:点击下载按钮,等待下载完成即可;如下图:
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第13张图片
4、测试

将板子的PA9和PA10 接到串口转TTL模块,并将模块的USB接口接到电脑,然后打开串口调试助手(网上有很多可以下载,或者可以联系作者索要),根据模块识别的串口号,打开对应的串口,注意波特率、数据为、停止位、校验位等参数,要与代码设置的参数保持一致。 有些开发板可能会带有串口转TTL芯片,有的,则直接将对应接口的USB口,接到电脑即可(根据具体使用的开发板情况而定)。

打开串口后,在输入框输入发送的数据如:“123abc”,注意勾选“换行”,并点击发送;可在接收窗口看待对应输出的输出信息;
如下图:
<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)_第14张图片
至此串口收发功能以实现;
如有不理解、不明白指出可联系作者;
如有错误遗漏等,还望指教说明,多促进交流;

联系方式:QQ759521350
…本文属原创作品,转载表明出处…

你可能感兴趣的:(STM32,STM32CubeMX,stm32,c语言,串口通信)