当前位置: 首页 > news >正文

3.串口(UART)

串口理论部分可看51部分:链接

数据帧 = 帧头(2字节,例如AA、BB) + 数据长度(2字节)+ 数据 + CRC16校验(2字节) + 帧尾(2字节)

代码编写

串口一发送命令控制LED灯(PB5、PE5)

LED灯、串口、串口打印浮点数据、串口重定向配置

LED灯配置请看:链接

串口配置:

串口配置

配置中断NVIC(嵌套向量中断控制器)

配置中断NVIC

配置DMA:

配置DMA

Cube IDE中串口打印浮点数据配置方法(参考):进入“Project→Properties”;显示界面如下。按照图片中的设置完成即可!

打印浮点数配置

串口重定向配置:

uint8_t u_buf[256];	//usart.c,24行#include <stdio.h>	//usart.h,32行
extern uint8_t u_buf[256];	//usart.h,38行
#define printf(...)  HAL_UART_Transmit(&huart1, (uint8_t *)u_buf, sprintf((char*)u_buf, __VA_ARGS__), 0xffff)	//usart.h,39行

轮询方式

缺点:

    必须要等待数据发送完或者等待时间超时,代码才会往下走

    必须要等待数据接收到固定的字节长度,超时,代码才往下走

Cube IDE代码

mian.c

/* USER CODE BEGIN Includes */
#include <string.h>	//26行
#include <stdio.h>	//27
/* USER CODE END Includes *//* USER CODE BEGIN PV */
uint8_t UART_Recv[5];	//48行
char UART_Str[30];		//49行
/* USER CODE END PV *///参数1:UART 模块的配置信息的指针,参数2:数据缓冲区的指针,参数3:接收字节长度,参数4:接收超时时间(单位为毫秒)
HAL_UART_Receive(&huart1, UART_Recv, 4, 1000);	//接收数据函数
if(strcmp("LED1", (char *)UART_Recv) == 0)	//字符串比较函数
{HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);memset(UART_Recv,'\0',5);	//替换字符函数,常用于清除指定空间
}if(!strcmp("LED2", (char *)UART_Recv))	//字符串比较函数
{HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);memset(UART_Recv,'\0',5);
}sprintf(UART_Str, "%f\n", 666.6);
//参数1:UART 模块的配置信息的指针,参数2:发送的字符串或字符数组,参数3:发送字节长度,参数4:接收超时时间(单位为毫秒)
HAL_UART_Transmit(&huart1, (char *)UART_Str, strlen(UART_Str), 1000);	//发送数据
printf("xinzai\n");	//配置串口重定向后才可使用

中断(IT)方式

Cube IDE代码


HAL_UART_RxCpltCallback(huart);	//stm32f1xx_hal_uart.c,3660行//stm32f1xx_hal_uart.c,2619行
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)	//中断回调函数

main.c

/* USER CODE BEGIN Includes */
#include <string.h>	//26行
#include <stdio.h>	//27行
/* USER CODE END Includes *//* USER CODE BEGIN PV */
uint8_t UART_Recv_IT[5];	//48行
char UART_Str[30];	//49行
/* USER CODE END PV *//* USER CODE BEGIN 2 */
//参数1:UART 模块的配置信息的指针,参数2:数据缓冲区的指针,参数3:接收字节长度
HAL_UART_Receive_IT(&huart1, UART_Recv_IT, 4);	//串口中断接收函数,95行
/* USER CODE END 2 *///while函数里
sprintf(UART_Str, "%d\n", 666);	//102
HAL_UART_Transmit_IT(&huart1, UART_Str, strlen(UART_Str));	//串口中断发送函数,103
HAL_Delay(1000);	//104//151行开始
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)	//串口中断接收触发函数
{if(huart == &huart1)	//判断传进来的串口是哪个{if(strcmp("LED1", (char *)UART_Recv_IT) == 0)	//字符串比较函数{HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);memset(UART_Recv_IT,'\0',5);	//替换字符函数,常用于清除指定空间}if(!strcmp("LED2", (char *)UART_Recv_IT))	//字符串比较函数{HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);memset(UART_Recv_IT,'\0',5);}//因为只能接受一次串口中断,所以在串口中断触发函数需要重新调用HAL_UART_Receive_IT(&huart1, UART_Recv_IT, 4);}
}
/* USER CODE END 4 */

空闲中断(IDLE) + DMA

不受接收字符长度影响,可以随意接收字符长度并判断

空闲状态:在多个字节传输结束后,通信线路将会维持高电平,这个状态称为空闲状态(没有数据传输时的空闲状态,数据传输刚结束的空闲状态)

空闲中断产生条件:在数据传输过程中,当CPU检测到通信线路处于空闲状态时,且空闲状态的持续时间大于一个字节传输时间时,空闲状态标志IDLE将由硬件置1,产生空闲中断

Cube IDE代码

//stm32f1xx_hal_uart.h,2710行
__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)	//空闲中断接收回调函数

main.c

/* USER CODE BEGIN Includes */
#include <string.h>		//27行
/* USER CODE END Includes *//* USER CODE BEGIN PD */
#define RECV_Size 100	//37行
/* USER CODE END PD *//* USER CODE BEGIN 2 */
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, UART_Recv_IDLE, RECV_Size);	//空闲中断接收函数,94行
//数据接收RECV_Size一半时会重新触发中断,需要关闭DMA接收中断使能
HAL_NVIC_DisableIRQ(DMA1_Channel5_IRQn);	//96行
/* USER CODE END 2 *///150行
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)	//空闲中断接收触发函数
{if(huart == &huart1)	//判断传进来的串口是哪个{if(strcmp("LED1", (char *)UART_Recv_IDLE) == 0)	//字符串比较函数{HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);memset(UART_Recv_IDLE,'\0',Size);	//替换字符函数,常用于清除指定空间}if(!strcmp("LED2ON", (char *)UART_Recv_IDLE))	//字符串比较函数{//HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, 0);memset(UART_Recv_IDLE,'\0',Size);}else if(!strcmp("LED2OFF", (char *)UART_Recv_IDLE)){HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, 1);memset(UART_Recv_IDLE,'\0',Size);}//因为只能接受一次串口中断,所以在串口中断触发函数需要重新调用HAL_UARTEx_ReceiveToIdle_DMA(&huart1, UART_Recv_IDLE, RECV_Size);}}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 写一个获取cookie方法
  • 我的cesium for UE踩坑之旅(蓝图、UI创建)
  • Genymotion adb shell
  • 程序员短视频上瘾综合症
  • Linux Tcp 连接 状态 检测 处理
  • HTML前端面试基础(一)
  • MySQL总体功能
  • 学习!胖东来秋季陈列欣赏
  • <数据集>agv仓储机器人识别数据集<目标检测>
  • python实现小游戏随机猜数
  • 西门子s7通信协议
  • C++类别之Static成员
  • 代码分支管理规范
  • 远程桌面管理软件,如何使用远程桌面管理软件来远程控制服务器
  • C++:类和对象(上)
  • [ JavaScript ] 数据结构与算法 —— 链表
  • CentOS7 安装JDK
  • Java超时控制的实现
  • Java应用性能调优
  • nginx 配置多 域名 + 多 https
  • Redis学习笔记 - pipline(流水线、管道)
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 从输入URL到页面加载发生了什么
  • 对JS继承的一点思考
  • 分布式任务队列Celery
  • 配置 PM2 实现代码自动发布
  • 前端自动化解决方案
  • 小程序开发中的那些坑
  • 自制字幕遮挡器
  • ​比特币大跌的 2 个原因
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • (20050108)又读《平凡的世界》
  • (9)STL算法之逆转旋转
  • (done) 两个矩阵 “相似” 是什么意思?
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (二)正点原子I.MX6ULL u-boot移植
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (七)Activiti-modeler中文支持
  • (全部习题答案)研究生英语读写教程基础级教师用书PDF|| 研究生英语读写教程提高级教师用书PDF
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (算法)大数的进制转换
  • (图)IntelliTrace Tools 跟踪云端程序
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)LINQ之路
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • .Net IE10 _doPostBack 未定义
  • .NET MAUI Sqlite程序应用-数据库配置(一)
  • .net 提取注释生成API文档 帮助文档
  • .NetCore部署微服务(二)
  • .NET单元测试使用AutoFixture按需填充的方法总结