串口
文章目录
1.轮询方式
1.固定长度数据收发:
/* USER CODE BEGIN PM */
uint8_t RecBuf[10]; //接收缓冲区定义
/* USER CODE END PM */
/* USER CODE BEGIN 3 */
if ( HAL_UART_Receive(&haurt2, RecBuf, 5, 100) == HAL_OK )
//5: 数据数量, 100: 超时时间100ms
{
HAL_UART_Transmit (&haurt2, RecBuf, 5, 100); //把接受到的字符原样发回
}
}
/* USER CODE END 3 */
2.串口重定向:
添加stdio.h
/* USER CODE BEGIN Includes */
#include "stdio.h" //在main.h中添加标准输入输出头文件
/* USER CODE END Includes */
重定义fputc与fgetc函数:
/* USER CODE BEGIN 4 */
//重定义fputc函数
int fputc(int ch, FILE *f) {
//采用轮询方式发送1字节数据,超时时间设置为无限等待
HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, HAL_MAX_DELAY);
return ch;
}
//重定义fgetc函数
int fgetc(FILE *f) {
uint8_t ch;
//采用轮询方式接收1字节数据,超时时间设置为无限等待
HAL_UART_Recieve( &huart2, (uint8_t*) &ch, 1, HAL_MAX_DELAY );
return ch;
}
/* USER CODE END 4 */
用户变量定义:
/* USER CODE BEGIN PV */
uint8_t RecData; //存放接收数据
/* USER CODE END PV */
用户初始化代码:
/* USER CODE BEGIN 2 */
printf("UART Retarget: \r \n"); //发送提示信息
/* USER CODE END 2 */
用户应用代码:
/* USER CODE BEGIN 3 */
if ( scanf("%c", &Recdata) == 1) //正确接收到数据
//scanf 函数的返回值表示正确接收的数据个数
{
if( Recdata == 'y')
{
printf("Received y!\r\n"); //发送回复信息
}
else
{
printf("Received others! \r\n");
}
}
}
/* USER CODE END 3 */
2.中断方式
1.固定长度数据收发:
用户宏定义及变量定义:
/* USER CODE BEGIN PD */
#define LENGTH 10 //接收缓冲区大小
/* USER CODE END PD */
/* USER CODE BEGIN PV */
uint8_t RxBuffer[LENGTH]; //接收缓冲区
uint8_t RxFlag = 0; //接收完成标志
/* USER CODE END PV */
用户初始化代码:
/* USER CODE BEGIN 2 */
printf("Please enter 10 characters: \r \n"); //发送提示信息
HAL_UART_Receive_TI(&huart2, (uint8_t *)RxBuffer, LENGTH); //使能接收中断
/* USER CODE END 2 */
用户应用代码:
/* USER CODE BEGIN 3 */
if ( RxFlag == 1 ) //判断接收是否完成
{
RxFlag == 0; //清除标志位
printf("Received success! \r\n");
//将接收到的字符原样发回
HAL_UART_Transmit_IT(&huart2, (uint8_t *)RxBuffer, LENGTH);
}
}
/* USER CODE END 3 */
接收中断回调函数:
/* USER CODE BEGIN 4 */
//接收中断回调函数
void HAL_UART_RxCpltCallback ( UART_HandleTypeDef *huart )
{
if (huart -> Instance == haurt2) //判断发生接收中断的串口
{
RxFlag = 1; //置位接收完成标志
HAL_UART_Receive_IT (&huart2, (uint8_t *)RxBuffer, LENGTH);
//重新使能接收中断,以便接收下一次中断
}
}
/* USER CODE END 4 */
2.简单的帧格式通讯
用户变量定义:
/* USER CODE BEGIN PV */
uint8_t RxBuffer[4]; //接收缓冲区
uint8_t RxFlag = 0; //接收完成标志 0: 未完成, 1: 完成
uint8_t ErrFlag = 0; //指令错误标志 0: 正确, 1: 错误
/* USER CODE END PV */
用户初始化代码:
/* USER CODE BEGIN 2 */
printf("Please enter instruction: \r \n"); //发送提示信息
HAL_UART_Receive_TI(&huart2, (uint8_t *)RxBuffer, 4); //使能接收中断
/* USER CODE END 2 */
用户应用代码:
/* USER CODE BEGIN 3 */
if ( RxFlag == 1 ) //判断接收是否完成
{
RxFlag == 0; //清除标志位
//帧格式解析
if ( RxBuffer[0] == 0xaa && RxBuffer[3] == 0x55 ) //判断帧头帧尾
{
if ( RxBuffer[1] == 0x01 ) //判断设备码
{
if ( RxBuffer[2] == 0x00 ) //判断功能码
{
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
printf("LD2 is closed! \r\n");
}
else if ( RxBuffer[2] == 0x01 )
{
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
printf("LD2 is open! \r\n");
}
else //功能码错误
{
ErrFlag = 1; //错误标志
}
}
else //设备码错误
{
ErrFlag = 1;
}
}
else //帧头帧尾错误
{
ErrFlag = 1;
}
if ( ErrFlag == 1 )
{
printf( "Communication Error!\r\n" );
}
//清除接收缓冲区和错误标志, 准备下一次接收
ErrFlag = 0;
RxBuffer[0] = 0;
RxBuffer[1] = 0;
RxBuffer[2] = 0;
RxBuffer[3] = 0;
}
}
/* USER CODE END 3 */
接收中断回调函数:
/* USER CODE BEGIN 4 */
//接收中断回调函数
void HAL_UART_RxCpltCallback ( UART_HandleTypeDef *huart )
{
if (huart -> Instance == haurt2) //判断发生接收中断的串口
{
RxFlag = 1; //置位接收完成标志
HAL_UART_Receive_IT (&huart2, (uint8_t *)RxBuffer, LENGTH);
//重新使能接收中断,以便接收下一次中断
}
}
/* USER CODE END 4 */
3.DMA
添加空闲中断的处理:
void USART2_IRQHandler(void) 函数在 stm32f1xx_it.c 文件中
/* USER CODE BEGIN USART2_IRQn 1 */
if (__HAL_UART_GET_FLAG ( &huart2, UART_FLAG_IDLE ) != RESET )
//是否发生IDLE中断
{
__HAL_UART_GLEAR_IDLEFLAG( &huart2 ); //清除IDLE中断标志
HAL_UART_IdleCptlCallback( &huart2 ); //用户编写的IDLE中断回调函数
}
/* USER CODE END USART2_IRQn 1 */
用户宏定义及变量定义:
/* USER CODE BEGIN PM */
#define LENGTH 10 //接收缓冲区大小, 需大于一帧数据的总字符数
/* USER CODE END PM */
/* USER CODE BEGIN PV */
uint8_t RxBuffer[ LENGTH ]; //接收缓冲区
uint8_t RecCount = 0; //接收数据个数
uint8_t RxFlag = 0; //接收完成标志
/* USER CODE END PV */
用户初始化代码:
/* USER CODE BEGIN 2 */
printf("Please enter : \r \n"); //发送提示信息
_HAL_UART_ENABLE_IT( &haurt, UART_IT_IDLE ); //使能IDLE中断
HAL_UART_Receive_DMA( &huart2, (uint8_t *)RxBuffer, LENGTH ); //启动DMA接收
/* USER CODE END 2 */
用户应用代码:
/* USER CODE BEGIN 3 */
if ( RxFlag == 1 ) //判断接收是否完成
{
RxFlag == 0; //清除标志位
//发生空闲中断时,已接收数据个数等于数据总量减去DMA数据流中待接收的数据个数
RecCount = LENGTH - _HAL_DMA_GET_COUNTER ( &hdma_usart2_rx );
//采用DMA方式将接收的数据原样发送到PC
HAL_UART_Transmit_DMA(&huart2, (uint8_t *)RxBuffer, RecCount);
RecCount = 0;
//设置DMA Disable, 触发 DMA 中断,调用接收中断回调函数启动下一次 DMA 接收
__HAL_DMA_DISABLE( &hdma_usart2_rx );
}
/* USER CODE END 3 */
接收中断回调函数:
void HAL_UART_RxCpltCallback ( UART_HandleTypeDef *huart )
{
if (huart -> Instance == USART2) //判断发生接收中断的串口
{
RxFlag = 1; //置位接收完成标志
HAL_UART_Receive_DMA (&huart2, (uint8_t *)RxBuffer, LENGTH);
//重新使能接收中断,以便接收下一次中断
}
}
/*----------------------------空闲中断回调函数-----------------------------------*/
void HAL_UART_IdleCpltCallback ( UART_HandleTypeDef *huart )
{
RxFlag = 1; //设置接收完成标志
}
}
/* USER CODE END 4 */