串口通信实验源码讲解

笔记基于正点原子官方视频
视频连接https://www.bilibili.com/video/BV1Wx411d7wT?p=71&spm_id_from=333.1007.top_right_bar_window_history.content.click
如有侵权,联系删除

在工程文件中,位置:工程文件-SYSTEM-usart.c文件下定义好了串口通讯的库文件,可以直接用printf函数调用

一、printf函数

//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{ int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
_sys_exit(int x)
{ x = x; }
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
}
#endif

下面是摘抄百度百科的关于C语言中printf函数的知识
printf()函数的调用格式为:
printf("<格式化字符串>", <参量表>);
其中格式化字符串包括两部分内容: 一部分是正常字符, 这些字符将按原样输出; 另一部分是格式化规定字符, 以"%“开始, 后跟一个或几个规定字符,用来确定输出内容格式。参量表是需要输出的一系列参数, 其个数必须与格式化字符串所说明的输出参数个数一样多, 各参数之间用”,"分开, 且顺序一一对应, 否则将会出现意想不到的错误。

  • 规定符
    %d 十进制有符号整数
    %u 十进制无符号整数
    %f 浮点数
    %s 字符串
    %c 单个字符
    %p 指针的值
    %e 指数形式的浮点数
    %x, %X 无符号以十六进制表示的整数
    %o 无符号以八进制表示的整数
    %g 把输出的值按照%e或者%f类型中输出长度较小的方式输出
    %p 输出地址符
    %lu 32位无符号整数
    %llu 64位无符号整数
  • 说明
    (1).可以在“%”和字母之间插进数字表示最大场宽。例如:%3d表示输出3位整型数,不够3位右对齐。%9.2f表示输出场宽为9的浮点数,其中小数位为2,整数位为6,小数点占一位,不够9位右对齐。%8s表示输出8个字符的字符串,不够8个字符右对齐。如果字符串的长度、或整型数位数超过说明的场宽,将按其实际长度输出。但对浮点数,若整数部分位数超过了说明的整数位宽度,将按实际整数位输出;若小数部分位数超过了说明的小数位宽度,则按说明的宽度以四舍五入输出。另外,若想在输出值前加一些0,就应在场宽项前加个0。
    例如:%04d表示在输出一个小于4位的数值时,将在前面补0使其总宽度为4位。如果用非浮点数表示字符或整型量的输出格式,小数点后的数字代表最大宽度,小数点前的数字代表最小宽度。
    例如:%6.9s表示显示一个长度不小于6且不大于9的字符串。若大于9,则第9个字符以后的内容将被删除。
    (2).可以在“%”和字母之间加小写字母l,表示输出的是长型数。
    例如:%ld表示输出long整数%lf表示输出double浮点数
    (3).可以控制输出左对齐或右对齐,即在"%“和字母之间加入一个”-"号可说明输出为左对齐, 否则为右对齐。
    例如:%-7d 表示输出7位整数左对齐%-10s 表示输出10个字符左对齐
  • 一些特殊规定字符作用
    \n 换行
    \f 清屏并换页
    \r 回车
    \t Tab符
    \xhh 表示一个ASCII码用16进表示,
    其中hh是1到2个16进制数

二、实验例子

1.实验现象

从电脑串口助手发送长度为200以内任意长度的字符串给STM32串口1(字符串以回车换行标识结束),STM32接收到字符串之后,一次性通过串口1把所有数据返回给电脑。

2.实验过程

把每个接收到的数据保存在一个程序定义的Buffer数组中(数组长度为200),同时把接收到的数据个数保存在定义的变量中。程序通过对接收到的每个数据进行结束判断(接收到回车0x0d之后再接收到换行0x0a),程序接收结束之后,设置相应的标记位,标记结束。。。外部 循环通过判断标志位来判断程序结束,然后一次性通过串口1发送出来。发送完成之后,所有标志位和数据量都清零。

#define USART_REC_LEN 200        //定义最大接收字节数 200
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
u16 USART_RX_STA;               //接收状态标记

注意: 回车的ASCII码为0X0D,即系统判断当收到回车时表示这一次串口数据输入完毕,即将发送,在接收完成时,系统返回0X0A

这一讲建议看视频,网址: https://www.bilibili.com/video/BV1Wx411d7wT?p=36

三、usart.c文件源码

#include "usart.h"
#include "delay.h"
//
//如果使用os,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"                 //os 使用
#endif//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
//#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{ int handle;
}; FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{ x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{   while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   USART1->DR = (u8) ch;      return ch;
}
#endif #if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0,   接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记 u8 aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
UART_HandleTypeDef UART1_Handler; //UART句柄//初始化IO 串口1
//bound:波特率
void uart_init(u32 bound)
{   //UART 初始化设置UART1_Handler.Instance=USART1;                     //USART1UART1_Handler.Init.BaudRate=bound;                 //波特率UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式UART1_Handler.Init.StopBits=UART_STOPBITS_1;      //一个停止位UART1_Handler.Init.Parity=UART_PARITY_NONE;         //无奇偶校验位UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控UART1_Handler.Init.Mode=UART_MODE_TX_RX;           //收发模式HAL_UART_Init(&UART1_Handler);                        //HAL_UART_Init()会使能UART1HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量}//UART底层初始化,时钟使能,引脚配置,中断配置
//此函数会被HAL_UART_Init()调用
//huart:串口句柄void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{//GPIO端口设置GPIO_InitTypeDef GPIO_Initure;if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化{__HAL_RCC_GPIOA_CLK_ENABLE();         //使能GPIOA时钟__HAL_RCC_USART1_CLK_ENABLE();           //使能USART1时钟GPIO_Initure.Pin=GPIO_PIN_9;           //PA9GPIO_Initure.Mode=GPIO_MODE_AF_PP;        //复用推挽输出GPIO_Initure.Pull=GPIO_PULLUP;         //上拉GPIO_Initure.Speed=GPIO_SPEED_FAST;        //高速GPIO_Initure.Alternate=GPIO_AF7_USART1;    //复用为USART1HAL_GPIO_Init(GPIOA,&GPIO_Initure);      //初始化PA9GPIO_Initure.Pin=GPIO_PIN_10;          //PA10HAL_GPIO_Init(GPIOA,&GPIO_Initure);       //初始化PA10#if EN_USART1_RXHAL_NVIC_EnableIRQ(USART1_IRQn);       //使能USART1中断通道HAL_NVIC_SetPriority(USART1_IRQn,3,3);    //抢占优先级3,子优先级3
#endif  }}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;//接收数据错误,重新开始接收     }      }}}
}//串口1中断服务程序
void USART1_IRQHandler(void)
{ u32 timeout=0;u32 maxDelay=0x1FFFF;
#if SYSTEM_SUPPORT_OS       //使用OSOSIntEnter();
#endifHAL_UART_IRQHandler(&UART1_Handler);  //调用HAL库中断处理公用函数timeout=0;while (HAL_UART_GetState(&UART1_Handler) != HAL_UART_STATE_READY)//等待就绪{timeout++;超时处理if(timeout>maxDelay) break;      }timeout=0;while(HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1{timeout++; //超时处理if(timeout>maxDelay) break;  }
#if SYSTEM_SUPPORT_OS       //使用OSOSIntExit();
#endif
}
#endif  /*下面代码我们直接把中断控制逻辑写在中断服务函数内部。说明:采用HAL库处理逻辑,效率不高。*/
/*
//串口1中断服务程序
void USART1_IRQHandler(void)
{ u8 Res;
#if SYSTEM_SUPPORT_OS       //使用OSOSIntEnter();
#endifif((__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_RXNE)!=RESET))  //接收中断(接收到的数据必须是0x0d 0x0a结尾){HAL_UART_Receive(&UART1_Handler,&Res,1,1000); if((USART_RX_STA&0x8000)==0)//接收未完成{if(USART_RX_STA&0x4000)//接收到了0x0d{if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始else USART_RX_STA|=0x8000; //接收完成了 }else //还没收到0X0D{   if(Res==0x0d)USART_RX_STA|=0x4000;else{USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;USART_RX_STA++;if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收   }      }}          }HAL_UART_IRQHandler(&UART1_Handler);
#if SYSTEM_SUPPORT_OS       //使用OSOSIntExit();
#endif
}
#endif
*/

27.串口通信实验源码讲解相关推荐

  1. RS485/RS232串口通信实现源码

    之前贴出了代码,但是本地源码已经找不到了:本篇补充了一些使用说明 一.参考代码 1.不方便下载的同学可以参考贴出来的源代码链接:RS485 2.工程链接:RS485 二.基本知识 1.RS485通信讲 ...

  2. Android串口通信apk源码

    1.SerialPortHelper「Android串口通信」介绍 原项目地址 https://github.com/freyskill/SerialPortHelper Android串口通讯助手可 ...

  3. 【正点原子FPGA连载】第十四章 串口通信实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

    1)实验平台:正点原子新起点V2开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609758951113 2)全套实验源码+手册+视频下载地址:ht ...

  4. 【正点原子FPGA连载】 第十七章 RS485串口通信实验 -摘自【正点原子】领航者ZYNQ之FPGA开发指南_V2.0

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  5. 【正点原子MP157连载】 第十六章 UART串口通信实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  6. 基于FPGA Uart串口通信实验

    基于FPGA Uart串口通信实验 首先需要了解uart串口通信协议,根据个人专业需求不同,了解的层面可以不同. UART简介 通用异步收发传输器(Universal Asynchronous Rec ...

  7. USART串口通信实验

    整理自:正点原子PPT 文章目录 串口简介 串口通信基本原理 常用串口相关寄存器 串口操作相关函数 硬件连接 串口配置一般步骤 例程参考 升级版 串口简介 详情见STM32F4开发指南 串口通信基本原 ...

  8. 【转】Qt编写串口通信程序全程图文讲解

    Qt编写串口通信程序全程图文讲解 本文章原创于www.yafeilinux.com 转载请注明出处. (说明:我们的编程环境是windows xp下,在Qt Creator中进行,如果在Linux下或 ...

  9. 基于FPGA的UART串口通信实验(VHDL语言实现)

    一.前言: 最近在做UART串口通信的相关实验时,在网上查了很多资料,发现网上的大部分文章只注重理论,不注重代码,很多代码有错误不说,而且难以理解.故在完成此实验后,起了写一篇博客的心思,以供有想做相 ...

最新文章

  1. c#输出一个平行四边形_如果Java 和 C# 同时出现,生态也差不多,你选择谁?
  2. 2.4g 无线键鼠对码软件_无线路由器的2.4G和5G同时开速度有影响吗?
  3. [LeetCode]547. Friend Circles朋友圈数量--不相邻子图问题
  4. CSS光标cursor
  5. python基础(正则表达式)
  6. Xcode中常见的错误,警告和解决方法
  7. 校验用户登录手机端还是PC端,是否微信浏览器打开
  8. python输出100到200的素数_python输出2到100之间的素数
  9. 利用matlab将位图转为SVG矢量图
  10. matlab绘图工具
  11. 如何取得AS400访问,一窥究竟
  12. 在linux启动docker时,报告XIO: fatal IO error 错误
  13. 【聚类】算法及其评估指标
  14. 高质量代码的几大标准
  15. 最优化:拟牛顿法、最速下降法、共轭梯度法、信赖域法、协同优
  16. Bootstrap3基础 table-striped 表格实现隔行换色(浅灰色与白色交替)
  17. JPA中的@Embedded和@Embeddable注释的使用
  18. 极限编程(Extreme Programming)—走向极限
  19. EXSi 无法更改主机配置
  20. 软件测试面试题集锦(问题+回答)

热门文章

  1. 关于分布式存储,这是你应该知道的(图文详解)(关于存储的一些好文转载--1)
  2. 【蓝桥杯选拔赛真题02】python奇偶数 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析
  3. UltraEdit文本编辑器下载适用于Win/Mac和Linux
  4. 什么企业可以申报高新技术企业
  5. Atitit 支出分类表 会计科目(1)资产(2)负债(3)资本(4)收益(5)费用(成本) 资产分类表 attilax总结...
  6. Win7安装kb4474419补丁(附补丁连接)
  7. 贵州六盘水市新农合一卡通工作启动
  8. Mac OS X 10.10 + WineBottler + XQuartz 成功运行 诛仙3
  9. mysql 结构化数据库_【MySQL】——MySQL数据库和SQL结构化查询语言概述
  10. 想要骑驴找马,这些事一定要注意!