通用同步异步收发器USART
1、USART 介绍
通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter)是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。有别于 USART 还有一个UART(Universal Asynchronous Receiver and Transmitter),它是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是 UART。
串行通信一般是以帧格式传输数据,即是一帧一帧的传输,每帧包含有起始信号、数 据信息、停止信息,可能还有校验信息。USART 就是对这些传输参数有具体规定,当然也 不是只有唯一一个参数值,很多参数值都可以自定义设置,只是增强它的兼容性。
USART 满足外部设备对工业标准 NRZ 异步串行数据格式的要求,并且使用了小数波 特率发生器,可以提供多种波特率,使得它的应用更加广泛。USART 支持同步单向通信和半双工单线通信;还支持局域互连网络 LIN、智能卡(SmartCard)协议与 lrDA(红外线数据 协会) SIR ENDEC 规范。
USART 支持使用 DMA,可实现高速数据通信,有关 DMA 具体应用将在 DMA 章节 作具体讲解。
USART 在 STM32 应用最多莫过于“打印”程序信息,一般在硬件设计时都会预留一 个 USART 通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端 的串口调试助手工具上,从而了解程序运行是否正确、如果出错哪具体哪里出错等等。
2、串口通讯协议简介
串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单 便捷,因此大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通 讯方式输出调试信息。
在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和 片上外设;STM32 标准库则是在寄存器与用户代码之间的软件层。对于通讯协议,我们也 以分层的方式来理解,最基本的是把它分为物理层和协议层。物理层规定通讯系统中具有 机械、电子功能部分的特性,确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑, 统一收发双方的数据打包、解包标准。简单来说物理层规定我们用嘴巴还是用肢体来交流, 协议层则规定我们用中文还是英文来交流。
下面我们分别对串口通讯协议的物理层及协议层进行讲解。
2.1、物理层
串口通讯的物理层有很多标准及变种,我们主要讲解 RS-232 标准 ,RS-232 标准主要 规定了信号的用途、通讯接口以及信号的电平标准。
在上面的通讯方式中,两个通讯设备的“DB9 接口”之间通过串口信号线建立起连接, 串口信号线中使用“RS-232 标准”传输数据信号。由于 RS-232 电平标准的信号不能直接被控制器直接识别,所以这些信号会经过一个“电平转换芯片”转换成控制器能识别的 “TTL 标准”的电平信号,才能实现通讯。
2.1.1、电平标准
根据通讯使用的电平标准不同,串口通讯可分为 TTL 标准及 RS-232 标准,见下表 TTL 电平标准与 RS232 电平标准:
我们知道常见的电子电路中常使用 TTL 的电平标准,理想状态下,使用 5V 表示二进制逻辑 1,使用 0V 表示逻辑 0;而为了增加串口通讯的远距离传输及抗干扰能力,它使用-15V 表示逻辑 1,+15V 表示逻辑 0。使用 RS232 与 TTL 电平标准准表示同一个信号时的对比。
因为控制器一般使用 TTL 电平标准,所以常常会使用 MAX232 芯片对 TTL 及 RS-232电平的信号进行互相转换。
2.1.2、RS-232 信号线
在最初的应用中,RS-232 串口标准常用于计算机、路由与调制调解器(modem,俗称“猫”)之间的通讯 ,在这种通讯系统中,设备被分为数据终端设备 DTE(计算机、路由)和数据通讯设备 DCE(调制调解器)。我们以这种通讯模型讲解它们的信号线连接方式及各个
信号线的作用。
在旧式的台式计算机中一般会有 RS-232 标准的 COM 口(也称 DB9 接口),如下图:
其中接线口以针式引出信号线的称为公头,以孔式引出信号线的称为母头。在计算机中一般引出公头接口,而在调制调解器设备中引出的一般为母头,使用上图中的串口线即可把它与计算机连接起来。通讯时,串口线中传输的信号就是使用前面讲解的 RS-232 标准调制的。
在这种应用场合下,DB9 接口中的公头及母头的各个引脚的标准信号线接法见下图:
下面对各个信号线进行说明
上表中的是计算机端的 DB9 公头标准接法,由于两个通讯设备之间的收发信号(RXD与 TXD)应交叉相连,所以调制调解器端的 DB9 母头的收发信号接法一般与公头的相反,两个设备之间连接时,只要使用“直通型”的串口线连接起来即可,见下图:
串口线中的 RTS、CTS、DSR、DTR 及 DCD 信号,使用逻辑 1 表示信号有效,逻辑 0 表示信号无效。例如,当计算机端控制 DTR 信号线表示为逻辑 1 时,它是为了告知远端的 调制调解器,本机已准备好接收数据,0 则表示还没准备就绪。
在目前的其它工业控制使用的串口通讯中,一般只使用 RXD、TXD 以及 GND 三条信 号线,直接传输数据信号,而 RTS、CTS、DSR、DTR 及 DCD 信号都被裁剪掉了。
2.2、协议层
串口通讯的数据包由发送设备通过自身的 TXD 接口传输到接收设备的 RXD 接口。在 串口通讯的协议层中,规定了数据包的内容,它由启始位、主体数据、校验位以及停止位 组成,通讯双方的数据包格式要约定一致才能正常收发数据,其组成见下图。
- 总线在发送或接收前应处于空闲状态
- 一个起始位
- 一个数据字(8或9位),最低有效位在前
- 一个校验位
- 一个或两个停止位
以上为在普通UART模式下串行数据的发送接收数据帧结构组成,但通常情况下,我们是采用一个起始位、一个8位的数据字、无校验位,1个停止位来组成一帧数据,如下图:
2.2.1、波特率
波特率是指串行异步通信时的传输速率,由于异步通讯中没有时钟信号,所以两个通讯设备之间需要约定好波特率,即每个码元的长度,一遍对信号进行解码。而串行同步通信在通信的两个设备之间是有一根时钟信号线的,双方的通信是基于这根时钟信号线上的时钟的。传送速率用于说明数据传送的快慢。在串行通信中,数据是按位进行传送的,因此传送速率用每秒钟传送格式位的数目来表示,称之为波特率(band rate)。每秒传送一个格式位就是1波特。常见的波特率为4800、9600、115200等。
2.2.2、通讯的起始和停止信号
串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一 个逻辑 0 的数据位表示,而数据包的停止信号可由 0.5、1、1.5 或 2 个逻辑 1 的数据位表示, 只要双方约定一致即可。
2.2.3、有效数据
在数据包的起始位之后紧接着的就是要传输的主体数据内容,也称为有效数据,有效 数据的长度常被约定为 5、6、7 、8或9 位长。
2.2.4、数据校验
在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰 导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验 (odd)、偶校验(even)、0 校验(space)、1 校验(mark)以及无校验(noparity)。
奇校验要求有效数据和校验位中“1”的个数为奇数,比如一个 8 位长的有效数据为: 01101001,此时总共有 4 个“1”,为达到奇校验效果,校验位为“1”,最后传输的数据 将是 8 位的有效数据加上 1 位的校验位总共 9 位。
偶校验与奇校验要求刚好相反,要求帧数据和校验位中“1”的个数为偶数,比如数据 帧:11001010,此时数据帧“1”的个数为 4 个,所以偶校验位为“0”。
0 校验是不管有效数据中的内容是什么,校验位总为“0”,1 校验是校验位总为“1”。
3、RS232串口通信配置
3.1、【标准库】的配置方式
步骤:
1、初始化USART1的GPIO引脚以及初始化操作
/*-------------------------------------------------- usart.h --------------------------------------------------*/
/**
******************************** STM32F0xx *********************************
* @文件名 : usart.h
* @作者 : JayYang
* @库版本 : V1.5.0
* @文件版本 : V1.0.0
* @日期 : 2020年08月11日
* @摘要 : USART头文件
******************************************************************************/
/* 定义防止递归包含 ----------------------------------------------------------*/
#ifndef _USART_H
#define _USART_H
/* 包含的头文件 --------------------------------------------------------------*/
#include "stm32f0xx.h"
/* 函数申明 ------------------------------------------------------------------*/
void USART_Initializes(void);
void USART1_SendByte(uint8_t Data);
void USART1_SendNByte(uint8_t *pData, uint16_t Length);
void USART1_Printf(uint8_t *String);
#endif /* _USART_H */
/**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/
/*-------------------------------------------------- usart.c --------------------------------------------------*/
/**
******************************** STM32F0xx *********************************
* @文件名 : usart.c
* @作者 : JayYang
* @库版本 : V1.5.0
* @文件版本 : V1.0.0
* @日期 : 2020年08月11日
* @摘要 : USART源文件
******************************************************************************/
/*----------------------------------------------------------------------------
更新日志:
2020-08-11 V1.0.0:初始版本
----------------------------------------------------------------------------*/
/* 包含的头文件 --------------------------------------------------------------*/
#include "usart.h"
/* 函数申明 ------------------------------------------------------------------*/
static void USART_GPIO_Configuration(void);
static void USART_Configuration(void);
/* 函数定义 ------------------------------------------------------------------*/
/************************************************
函数名称 : USART_GPIO_Configuration
功 能 : USART所使用管脚输出输入定义
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
static void USART_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); //配置PA9引脚使用复用功能:USART1_TX
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1); //配置PA10引脚使用复用功能:USART1_RX
/* 定义USART TX_RX 引脚为复用输出 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //高速
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推完输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉(空闲状态为高电平)
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化引脚
}
/************************************************
函数名称 : USART_Configuration
功 能 : 配置USART
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
static void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
/******************************************************************
USART参数初始化: 波特率 传输位数 停止位数 校验位数
115200 8 1 0(NO)
*******************************************************************/
USART_InitStructure.USART_BaudRate = 115200; //设定传输速率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //设定传输数据位数,8位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //设定停止位个数
USART_InitStructure.USART_Parity = USART_Parity_No ; //不用校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不用硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //使用接收和发送功能
USART_Init(USART1, &USART_InitStructure); //初始化USART1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能USART1接收中断
USART_Cmd(USART1, ENABLE); //使能USART1
}
/************************************************
函数名称 : USART_Initializes
功 能 : 串口初始化
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
void USART_Initializes(void)
{
USART_GPIO_Configuration();
USART_Configuration();
}
/************************************************
函数名称 : USART1_SendByte
功 能 : 串口1发送一字节数据
参 数 : Data --- 数据
返 回 值 : 无
作 者 : JayYang
*************************************************/
void USART1_SendByte(uint8_t Data)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); //等待发送寄存器为空
USART_SendData(USART1,Data); //发送数据
}
/************************************************
函数名称 : USART1_SendNByte
功 能 : 串口1发送N个字符
参 数 : pData ----- 字符串
Length --- 长度
返 回 值 : 无
作 者 : JayYang
*************************************************/
void USART1_SendNByte(uint8_t *pData, uint16_t Length)
{
while(Length--)
{
USART1_SendByte(*pData);
pData++;
}
}
/************************************************
函数名称 : USART1_Printf
功 能 : 串口1打印输出
参 数 : String --- 字符串
返 回 值 : 无
作 者 : JayYang
*************************************************/
void USART1_Printf(uint8_t *String)
{
while((*String) != '\0')
{
USART1_SendByte(*String);
String++;
}
USART1_SendByte(0x0A);
}
/**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/
2、开启USART外设的时钟以及所用引脚GPIOA的时钟,以及接收中断函数的处理
/*-------------------------------------------------- bsp.h --------------------------------------------------*/
/**
********************************* STM32F0xx ********************************
* @文件名 : bsp.h
* @作者 : JayYang
* @库版本 : V1.5.0
* @文件版本 : V1.0.0
* @日期 : 2020年08月11日
* @摘要 : BSP板级支持包头文件
******************************************************************************/
/* 定义防止递归包含 ----------------------------------------------------------*/
#ifndef _BSP_H
#define _BSP_H
/* 包含的头文件 --------------------------------------------------------------*/
#include "stm32f0xx.h"
/* 自定义的头文件 --------------------------------------------------------------*/
#include "usart.h"
/* 宏定义 --------------------------------------------------------------------*/
/* 函数申明 ------------------------------------------------------------------*/
void BSP_Initializes(void);
#endif /* _BSP_H */
/**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/
/*-------------------------------------------------- bsp.c --------------------------------------------------*/
/**
******************************** STM32F0xx *********************************
* @文件名 : bsp.c
* @作者 : JayYang
* @库版本 : V1.5.0
* @文件版本 : V1.0.0
* @日期 : 2020年08月11日
* @摘要 : BSP板级支持包源文件
******************************************************************************/
/*----------------------------------------------------------------------------
更新日志:
2020-06-24 V1.0.0:初始版本
----------------------------------------------------------------------------*/
/* 包含的头文件 --------------------------------------------------------------*/
#include "bsp.h"
/* 函数申明 ------------------------------------------------------------------*/
static void RCC_Configuration(void);
static void NVIC_Configuration(void);
/* 函数定义 ------------------------------------------------------------------*/
/************************************************
函数名称 : BSP_Initializes
功 能 : 底层初始化
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
void BSP_Initializes(void)
{
RCC_Configuration(); //时钟配置
USART_Initializes(); //串口1初始化
NVIC_Configuration(); //外设中断配置
}
/************************************************
函数名称 : NVIC_Configuration
功 能 : NVIC配置
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 外设中断 */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //IRQ通道:串口1
NVIC_InitStructure.NVIC_IRQChannelPriority = 1; //优先级 :1级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能IRQ通道
NVIC_Init(&NVIC_InitStructure);
}
/************************************************
函数名称 : RCC_Configuration
功 能 : 时钟配置
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
static void RCC_Configuration(void)
{
/* 使能AHB时钟:USART1的引脚为 PA9-TX P10-RX */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/* 使能APB2时钟:开启USART1的时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
}
/**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/
/*------------------------------------------------ stm32f0xx_it.c ------------------------------------------------*/
/******************************************************************************/
/* STM32F0xx Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
/* available peripheral interrupt handler's name please refer to the startup */
/* file (startup_stm32f0xx.s). */
/******************************************************************************/
/************************************************
函数名称 : USART1_IRQHandler
功 能 : USART1中断
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
void USART1_IRQHandler(void)
{
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET) //判断是否接收完成
{
USART1_SendByte((uint8_t)(USART_ReceiveData(USART1))); //发送接收到的字符数据
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
3、调用打印函数进行测试
/*-------------------------------------------------- main.c --------------------------------------------------*/
/**
******************************** STM32F0xx *********************************
* @文件名 : main.c
* @作者 : JayYang
* @库版本 : V1.5.0
* @文件版本 : V1.0.0
* @日期 : 2020年06月24日
* @摘要 : 主函数 - 工程模板
******************************************************************************/
/*----------------------------------------------------------------------------
更新日志:
2020-06-24 V1.0.0:初始版本
----------------------------------------------------------------------------*/
/* 包含的头文件 --------------------------------------------------------------*/
#include "bsp.h"
unsigned char str[6]={'A','B','C','D','\r','\n'};
/************************************************
函数名称 : SoftwareDelay
功 能 : 软件延时
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
void SoftwareDelay(uint32_t nCount)
{
for(; nCount != 0; nCount--);
}
/************************************************
函数名称 : main
功 能 : 主函数入口
参 数 : 无
返 回 值 : int
作 者 : JayYang
*************************************************/
int main(void)
{
BSP_Initializes();
while(1)
{
//测试发送一个字节
// USART1_SendByte(0xF0);
// SoftwareDelay(0x3FFFFF);
//测试发送一串字符
// USART1_SendNByte(str,6);
// SoftwareDelay(0x3FFFFF);
USART1_Printf((uint8_t*)"串口打印测试\r\n");
SoftwareDelay(0x3FFFFF);
}
}
/**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/
3.2、【HAL库】的配置方式
步骤:
1、配置RCC时钟,使用外部8MHz,然后PLL倍频到48MHz
2、在STM32CubeMX中配置USART1的相关参数
3、 编辑驱动代码
/*-------------------------------------------------- rs232.h --------------------------------------------------*/
/**
********************************* STM32F0xx ********************************
* @文件名 : rs232.h
* @作者 : JayYang
* @库版本 : V1.5.0
* @文件版本 : V1.0.0
* @日期 : 2020年06月24日
* @摘要 : RS232驱动头文件
******************************************************************************/
/* 定义防止递归包含 ----------------------------------------------------------*/
#ifndef _RS232_H
#define _RS232_H
/* 包含的头文件 --------------------------------------------------------------*/
#include "stm32f0xx_hal.h"
/* 宏定义 --------------------------------------------------------------------*/
#define rs232_Buf_Max 20
/* 变量声明 --------------------------------------------------------------------*/
extern uint8_t rs232_Buf;
extern uint8_t rs232_Buf_count;
extern uint8_t rs232_Buf_try[rs232_Buf_Max];
/* 函数声明 --------------------------------------------------------------------*/
void RS232_RecvData(void);
void RS232_Demo1(void);
#endif /* _RS232_H */
/**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/
/*-------------------------------------------------- rs232.c --------------------------------------------------*/
/**
******************************** STM32F0xx *********************************
* @文件名 : rs232.c
* @作者 : JayYang
* @库版本 : V1.5.0
* @文件版本 : V1.0.0
* @日期 : 2020年06月24日
* @摘要 : RS232驱动源文件
******************************************************************************/
/*----------------------------------------------------------------------------
更新日志:
2020-06-24 V1.0.0:初始版本
----------------------------------------------------------------------------*/
/* 包含的头文件 --------------------------------------------------------------*/
#include "bsp.h"
uint8_t rs232_Buf=0;
uint8_t rs232_Buf_count=0;
uint8_t rs232_Buf_try[rs232_Buf_Max];
/************************************************
函数名称 : RS232_RecvData
功 能 : 接收数据
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
void RS232_RecvData(void)
{
if(rs232_Buf_count<rs232_Buf_Max)
{
rs232_Buf_try[rs232_Buf_count++]=rs232_Buf;
}
else
{
rs232_Buf_count=0;
}
HAL_UART_Receive_IT(&huart1,&rs232_Buf,1);
}
/************************************************
函数名称 : RS232_Demo1
功 能 : 将接收到的数据返回
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
void RS232_Demo1(void)
{
uint8_t i=0;
if(rs232_Buf_count>0)
{
HAL_Delay(20);
for(i=0;i<rs232_Buf_count;i++)
{
HAL_UART_Transmit(&huart1,&rs232_Buf_try[i],1,1000);
}
rs232_Buf_count=0;
}
}
/**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/
/*-------------------------------------------------- bsp.h --------------------------------------------------*/
/**
********************************* STM32F0xx ********************************
* @文件名 : bsp.h
* @作者 : JayYang
* @库版本 : V1.5.0
* @文件版本 : V1.0.0
* @日期 : 2020年06月24日
* @摘要 : BSP板级支持包头文件
******************************************************************************/
/* 定义防止递归包含 ----------------------------------------------------------*/
#ifndef _BSP_H
#define _BSP_H
/* 包含的头文件 --------------------------------------------------------------*/
#include "main.h"
#include "stm32f0xx_hal.h"
#include "gpio.h"
#include "usart.h"
#include "string.h"
#include "rs232.h"
/* 宏定义 --------------------------------------------------------------------*/
/* 函数申明 ------------------------------------------------------------------*/
void BSP_Configuration(void);
#endif /* _BSP_H */
/**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/
/*-------------------------------------------------- bsp.c --------------------------------------------------*/
/**
******************************** STM32F0xx *********************************
* @文件名 : bsp.c
* @作者 : JayYang
* @库版本 : V1.5.0
* @文件版本 : V1.0.0
* @日期 : 2020年06月24日
* @摘要 : BSP板级支持包源文件
******************************************************************************/
/*----------------------------------------------------------------------------
更新日志:
2020-06-24 V1.0.0:初始版本
----------------------------------------------------------------------------*/
/* 包含的头文件 --------------------------------------------------------------*/
#include "bsp.h"
/************************************************
函数名称 : BSP_Configuration
功 能 : 初始化程序
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
void BSP_Configuration(void)
{
HAL_UART_Receive_IT(&huart1,&rs232_Buf,1);
}
/************************************************
函数名称 : HAL_UART_RxCpltCallback
功 能 : 串口接收中断回调函数
参 数 : 无
返 回 值 : 无
作 者 : JayYang
*************************************************/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart==&huart1)
{
RS232_RecvData();
}
}
/**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/
/*-------------------------------------------------- main.c --------------------------------------------------*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
uint8_t str[6]={'A','B','C','D','\r','\n'};
/* 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 */
uint32_t sysclk,pck1,pck2;
/* 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 */
/* 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 */
BSP_Configuration(); //板级初始化
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
RS232_Demo1(); //将上位机发送过来接收到的数据回发
HAL_Delay(500);
HAL_UART_Transmit(&huart1,(uint8_t *)0xFF,1,1000); //发送一个字节
HAL_Delay(500);
HAL_UART_Transmit(&huart1,str,6,1000); //发送字符数组
HAL_Delay(500);
HAL_UART_Transmit(&huart1,(uint8_t *)"测试字符串\r\n",sizeof("测试字符串\r\n"),1000);
}
/* USER CODE END 3 */
}
3、串口实现 printf 打印
步骤:
1、引入头文件
#include "stdio.h"
2、在Keil中点击魔术棒设置,把这个选项勾选 Options for Target ->Target->Use MicroLIB
3.1、标准库重定向printf函数
int fputc(int ch, FILE *f)
{
USART1_SendByte((uint8_t)ch);
return ch;
}
//下面的代码可以省略
int fgetc(FILE *f)
{
/* Loop until received a char */
while(!(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET));
/* Read a character from the USART and RETURN */
return (USART_ReceiveData(USART1));
}
3.2、HAL库重定向printf函数
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
return ch;
}