串口介绍
串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口(Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢是设备间接线通信的一种方式数据一位一位地顺序传送双向通信,全双工传送速度相对较慢
UART是异步串行接口,通信双方使用时钟不同,因为双方硬件配置不同,但是需要约定通信 速度,叫做波特率。对于单片机和pc之间通信,pc端用软件配置,则单片机需要用代码完成配置,也可以用波特率配置软件直接生成
常用函数的介绍
串口发送/接收函数:
- HAL_UART_Transmit();//串口发送数据,使用超时管理机制
- HAL_UART_Receiver();//串口接收数据,使用超时管理机制
-
- HAL_UART_Transmit_IT();//串口中断模式发送
- HAL_UART_Receive_IT();//串口中断模式接收
作用:以中断的方式接收指定字节的数据
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
参数1:UART_HandleTypeDef 结构体类型指针变量
参数2:指向要发送的数据地址
参数3:要发送的数据大小,以字节为单位
参数4:设置的超时时间,ms为单位
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
参数1:UART_HandleTypeDef 结构体类型指针变量
参数2:指向接收数据缓存区
参数3:要接收的数据大小,以字节为单位
参数4:设置的超时时间,ms为单位
串口中断回调函数
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)//串口中断处理函数
__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)//发送中断回调函数
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//接受中断回调函数
状态标志变量
USART_RX_STA
从0开始,串口中断接收到一个数据(一个字节)就自增1。当数据读取全部OK的时候(回车和换行符来的时候),那么USART_RX_STA的最高位置置1,表示串口数据接收全部完毕了。然后main函数里面可以处理数据了。
串口接收中断流程
串口实验(非中断)
需求:接收串口工具发送的字符串,并且将其发送回串口工具
TX——PA10 RX——PA9(交叉接线)
使用CubeMX配置工程,串口配置
1.选定串口
2.选择模式
异步通信
效果:
如何使用printf打印数据到串口调试助手
1.重写fputc函数
int fputc(int ch,FILE *f)
{
unsigned char temp[1] = {ch};
HAL_UART_Transmit(&huart1,temp,1,0xffff);
return ch;
}
2.添加#include stdio.h头文件,使用MicroLIB库
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//HAL_UART_Transmit(&huart1,"hello\n",strlen("hello\n"),100);
HAL_UART_Receive(&huart1,buff,19,100);
// HAL_UART_Transmit(&huart1,buff,strlen(buff),100);
// printf("hello wrold\n");
printf(buff);//打印到串口调试助手
memset(buff,0,20);//清空buff
}
/* USER CODE END 3 */
串口实验(中断)
需求:通过中断的方法接收串口工具发送的字符串,并将其发送回串口工具
串口配置
1.选定串口
2.选择模式
异步通信
前面步骤与上面一样
打开串口中断
根据中断接收流程可知,最后会在UART_Receive_IT函数中调用HAL_UART_RxCpltCallback函数,该函数为一个虚函数,我们可以在main.c中重写,接收到一个数据,就在函数中处理
//定义最大接收字节数200
#define USART_REC_LEN 200
//接收缓冲,串口接收到的数据放到这个数组里面,最大USART_REC_LEN字节
uint8_t UART1_RX_Buffer[USART_REC_LEN];
uint8_t buf = 0;
uint16_t USART_RX_STA = 0;
//接收完成回调函数,收到一个数据后,在这里处理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//1.判断中断是由哪个串口触发
if(huart->Instance == USART1){
//判断接收是否完成(USART_RX_STA的bit15位置为1)
if((USART_RX_STA & 0x8000) == 0){//等于0则表示没有接收完成
//如果收到了0x0d(回车),看bit14是否为1
if(USART_RX_STA & 0x4000){
//则继续判断是否收到0x0a(换行)
if(buf == 0x0a){
//如果0x0a和0x0d都收到,则将bit15位置置1
USART_RX_STA |= 0x8000;
}else {
//否则认为接收错误,USART_RX_STA置0
USART_RX_STA = 0;
}
}else { //如果没有收到0x0d回车
//先判断这个字符是否是0x0d回车
if(buf == 0x0d){
//是的话就将bit14置1
USART_RX_STA |= 0x4000;
}else {
//不是的话,就将接收到的数据保存到缓存数组里面去
UART1_RX_Buffer[USART_RX_STA & 0x3FFF] = buf;
USART_RX_STA++;
//如果接收数据大于USART_REC_LEN(200字节),则重新开始接收
if(USART_RX_STA > USART_REC_LEN - 1 ){
USART_RX_STA = 0;
}
}
}
}
//重新开启中断
HAL_UART_Receive_IT(&huart1,&buf,1);
}
}
参考博文:http://t.csdn.cn/q4IPk
解释:从串口接收到的数据只有一个字节的,也就是串口是一个字节一个字节进行判断的,每次buf里面都是最新的字节,所以我们要读到一条完整的或者指定的数据长度,我们就要用UART1_RX_Buffer来存储,而USART_RX_STA就是辅助判断数据状态的。
两个表对应看,想要知道触发串口中断后,串口是否接收完成所有数据(0代表没有接收完成,1代表完成。)
UART1_RX_Buffer是专门存放数据的,串口接收到一个字节的数据,USART_RX_STA就会累加,UART1_RX_Buffer[USART_RX_STA]=buf就可以按顺序保存数据,但是bit15和bit14位指定进行两个判断功能,就不能拿来使用保存数据,所以我们这里&0X3FFF来截断数据。
//不是的话,就将接收到的数据保存到缓存数组里面去
UART1_RX_Buffer[USART_RX_STA & 0x3FFF] = buf;
USART_RX_STA++;
//如果接收数据大于USART_REC_LEN(200字节),则重新开始接收
if(USART_RX_STA > USART_REC_LEN - 1 ){
USART_RX_STA = 0;
}
main函数
int main(void)
{
/* USER CODE BEGIN 1 */
// unsigned char buff[20] = {0};
/* 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 */
HAL_UART_Receive_IT(&huart1,&buf,1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//判断串口是否接收完成
if(USART_RX_STA & 0x8000){
printf("收到数据:");
//将收到的数据发送到串口
HAL_UART_Transmit(&huart1,UART1_RX_Buffer,USART_RX_STA & 0x3FFF,0xffff);
//等待发送完成
while(huart1.gState != HAL_UART_STATE_READY);
printf("\r\n");
//重新开始下一次接收
USART_RX_STA = 0;
}
printf("hello world\n");
HAL_Delay(1000);
}
/* USER CODE END 3 */
}