stm32串口通信协议(标准库 and HAL库)

刚入门32,接触的第一个通信协议就是串口通信,所谓通信协议,就是指两个设备之间互联,将两个设备关联起来,使其可以相互之间传输数据,利用串口通信最常见的例子就是蓝牙模块。

下面为学习串口之后的一些简单的小总结:

1.串口一般都有固定的引脚,比如c8t6上USART1的TX为PA9,RX为PA10,当然,也可以将某些特定的引脚复用成USART1的TX,RX,两个设备之间进行串口通信时,TX与RX要互相交叉连接,且一定要共地,如果两个设备有单独供电的话,可以不用连接VCC

2.使用串口的时候,如果要与电脑端通信将数据打印再串口调试助手上,则电脑端要安装CH340驱动,且stm32端如果没有内置CH340模块的话,则必须用CH340将32与电脑端连接

3.串口基本结构:

4.串口初始化:

开启时钟,将所需的USART与GPIO的时钟打开,然后GPIO初始化,将TX配置为复用输出,RX为输入,最后利用USART的初始化结构体,将其余参数全部配置好,如果选择通过中断的方式接受,则需要配置NVIC中断优先级与开启中断

void USART_Init(void){//GPIO初始化结构体GPIO_InitTypeDef GPIO_InitStructure;//USART初始化结构体USART_InitTypeDef USART_InitStructure;// 打开串口GPIO的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);// 打开串口外设的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 将USART Tx的GPIO配置为推挽复用模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 将USART Rx的GPIO配置为浮空输入模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置串口的工作参数// 配置波特率USART_InitStructure.USART_BaudRate = 115200;// 配置 针数据字长USART_InitStructure.USART_WordLength = USART_WordLength_8b;// 配置停止位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(DEBUG_USARTx, &USART_InitStructure);/*//当需要中断的时候// 串口中断优先级配置NVIC_Configuration();// 使能串口接收中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
*/	// 使能串口USART_Cmd(USART1, ENABLE);	    
}

5.串口发送一个字节

void Usart_SendByte(USART_TypeDef* pUSARTx,uint8_t data){//调用库函数发送一个字节的数据USART_SendData(pUSARTx, data);//判断发送标志位,若数据没来得及发送,下一个数据就过来了,则会产生数据覆盖,所以要用标志位来 //判断是否能进行下一次发送while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE)==RESET);
}

6.将fputc函数重定向,使用print打印数据

int fgetc(FILE *f){/* 等待串口输入数据 */while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);return (int)USART_ReceiveData(USART1);
}

使用print时,注意,需要在魔术棒里面勾选使用微库,并在USART头文件里引用头文件<stdio.h>

只能重定向fputc到一个串口,若多个串口需要使用print,则可以使用sprint

char String[100];
sprintf(String,"Num=%d\r\n",666);
Usart_SendString(String);

7.利用阻塞的方式,读取串口数据(没成功读取数据就一直占用CPU)

while(1){if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET){RxData = USART_ReceiveData(USART1);}
}

读完DR之后不用手动清除标志位

8.通过中断的方式读取串口数据

在初始化USART时,配置NVIC,开启中断

void NVIC_Configuration(void){NVIC_InitTypeDef NVIC_InitStructure;/* 嵌套向量中断控制器组选择 *//* 提示 NVIC_PriorityGroupConfig() 在整个工程只需要调用一次来配置优先级分组*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);/* 配置USART为中断源 */NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;/* 抢断优先级*/NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;/* 子优先级 */NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;/* 使能中断 */NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/* 初始化配置NVIC */NVIC_Init(&NVIC_InitStructure);
}
// 串口中断优先级配置NVIC_Configuration();// 使能串口接收中断(USART_IT_RXNE标志位一旦置1,就会向NVIC申请中断,然后在中断服务函数里面接收数据)USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

之后在中断服务函数里面执行用户所需代码

void USART1_IRQHandler(void){if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET){//执行用户所需中断代码(可以直接读取DR)//RxData = USART_ReceiveData(USART1);//清除标志位USART_ClearITPendingBit(USART1,USART_IT_RXNE);}	 
}

9.通过将数据打包进行发送,和将打包的数据解码出来

根据内容,数据包通常分为HEX数据包与文本数据包;根据长度,数据包分为固定包长的数据包与可变包长的数据包。

发送HEX数据包:

//已经打包好的数据包
uint8_t USART_TxPacket[4];void USART_SendPacket(){//发送帧头Usart_SendByte(0xFF);//发送数据包Usart_SendArray(USART_TxPacket,4);//发送帧尾Usart_SendByte(0xFE);
}

接受HEX数据包(定义中断服务函数):

void USART1_IRQHandler(){//定义静态变量,使用状态机,来控制数据的接受static uint8_t RxState =0;static uint8_t pRxPacket =0;if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET)){uint8_t RxData = USART_ReceiveData(USART1);//判断帧头if(RxState == 0 && RxData == 0xFF){RxState = 1;pRxPacket = 0;}//接收数据else if(RxState == 1){USART_RxPacket[pRxPacket] = RxData;pRxPacket++;if(pRxPacket >= 4)RxState = 2;}//判断帧尾else if(RxState == 2 && RxData == 0xFE){RxState = 0;}//清除标志位USART_ClearITPendingBit(USART1,USART_IT_RXNE);}
}

接受文本数据包(与接受HEX数据包类似):

void USART1_IRQHandler(){//定义静态变量,使用状态机,来控制数据的接受static uint8_t RxState =0;static uint8_t pRxPacket =0;if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET)){uint8_t RxData = USART_ReceiveData(USART1);//判断帧头if(RxState == 0 && RxData == '@'){RxState = 1;pRxPacket = 0;}//接收数据else if(RxState == 1){if(RxData == '\r'){RxState = 2;}else{USART_RxPacket[pRxPacket] = RxData;pRxPacket++;}}//判断帧尾else if(RxState == 2 && RxData == '\n'){RxState = 0;//在数据末尾加上'\0',将数据处理成完整的字符串USART_RxPacket[pRxPacket] = '\0';}//清除标志位USART_ClearITPendingBit(USART1,USART_IT_RXNE);}
}

HAL库外设初始化MSP回调机制:

在HAL库里,一般采用HAL_USART_Init()来初始化某一个具体的外设,HAL_USART_Init()待传入的参数是一个USART的句柄结构体,其最主要的部分就是Instance成员和Init成员,Instance作为一个指针指向一个具体的外设,比如

UartHandle.Instance = USART1;

而Init就是USART初始化结构体,将参数配置好后,调用Init函数即可完成初始化。

void USART_Config(void){ UartHandle.Instance          = USART1;UartHandle.Init.BaudRate     = 115200;UartHandle.Init.WordLength   = UART_WORDLENGTH_8B;UartHandle.Init.StopBits     = UART_STOPBITS_1;UartHandle.Init.Parity       = UART_PARITY_NONE;UartHandle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;UartHandle.Init.Mode         = UART_MODE_TX_RX;HAL_UART_Init(&UartHandle);/*使能串口接收断 */__HAL_UART_ENABLE_IT(&UartHandle,UART_IT_RXNE);  
}

在HAL库里调用HAL_UART_Init()之后,程序会自动调用HAL_UART_MspInit()(在HAL库被__weak修饰,用户可自行选择是否定义),用户可在该函数里面配置UART外设所用到的硬件:GPIO,NVIC以及时钟

void HAL_UART_MspInit(UART_HandleTypeDef *huart){  GPIO_InitTypeDef  GPIO_InitStruct;__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**USART1 GPIO Configuration    PA9     ------> USART1_TXPA10    ------> USART1_RX *//* 配置Tx引脚为复用功能  */GPIO_InitStruct.Pin = GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed =  GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* 配置Rx引脚为复用功能 */GPIO_InitStruct.Pin = GPIO_PIN_10;GPIO_InitStruct.Mode=GPIO_MODE_AF_INPUT;	//模式要设置为复用输入模式!	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_NVIC_SetPriority(USART1_IRQn ,0,1);	//抢占优先级0,子优先级1HAL_NVIC_EnableIRQ(USART1_IRQn );		    //使能USART1中断通道  
}

HAL库中断回调机制:

HAL_UART_IRQHandler():用户在中断服务函数中调用HAL库共用中断函数,然后再调用一系列中断回调函数(都被__weak修饰,用户自行选择定义与否)

HAL库配置串口步骤:

开启串口接受中断:

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size)

发送数据(以阻塞的方式,占用CPU):

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart,
uint8_t *pData, uint16_t Size, uint32_t Timeout)

第一个参数为一个串口句柄结构体,第二个参数为指向发送数据缓冲区,第三个参数为要发送的数据大小,以字节为单位,第四个参数为超时时间,以ms为单位

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3266689.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

快速入门了解Ajax

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;JavaWeb关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Ajax的初识 意义&#xff1a;AJAX&#xff08;Asynchronous JavaScript and…

相关性模型-正态分布均值假设检验★★★

该博客为个人学习清风建模的学习笔记&#xff0c;部分课程可以在B站&#xff1a;【强烈推荐】清风&#xff1a;数学建模算法、编程和写作培训的视频课程以及Matlab等软件教学_哔哩哔哩_bilibili 目录 1双侧检验 2单侧检验 3t检验 4两个正态总体均值差的检验 5逐对比较法 …

基于JSP、java、Tomcat、mysql三层交互的项目实战--校园交易网(1)-项目搭建(前期准备工作)

这是项目的初始页面 接下来我先写下我的初始项目搭建 技术支持&#xff1a;JAVA、JSP 服务器&#xff1a;TOMCAT 7.0.86 编程软件&#xff1a;IntelliJ IDEA 2021.1.3 x64 首先我们打开页面&#xff0c;准备搭建项目的初始准备 1.New Project 2.随后点击Next&#xff0c;勾…

【C++经典面试题】字符串类String的接口代码实现(重点考察对浅拷贝与深拷贝的理解)

在C++程序中会频繁地使用到字符串,很多信息是作为字符串保存在内存中的。字符串类是C++程序中常用的类之一,比如MFC中的CString类、C++标准库中的string(ANSI窄字节版本)和wstring(UNICODE宽字节版本)类。 C++程序员在面试时时常会遇到字符串相关的问题,比如一个…

Python酷库之旅-第三方库Pandas(046)

目录 一、用法精讲 161、pandas.Series.cumsum方法 161-1、语法 161-2、参数 161-3、功能 161-4、返回值 161-5、说明 161-6、用法 161-6-1、数据准备 161-6-2、代码示例 161-6-3、结果输出 162、pandas.Series.describe方法 162-1、语法 162-2、参数 162-3、功…

visual studio 配置路径中 用户宏的修改(备忘)

visual studio 2013 开发工具界面中&#xff1a;视图 --> 其它窗口 --> 属性管理器 &#xff08;如下图&#xff09; 接着开发工具界面会显示出“属性管理器”的界面 &#xff08;如下图&#xff09; 在‘属性管理器’界面中&#xff0c;找到‘opencv’右击&#xff…

ctfshow-web入门-php特性(web132-web136)

目录 1、web132 2、web133 3、web134 4、web135 5、web136 1、web132 存在 robots.txt 访问 /admin 需要传三个参数&#xff0c;并且需要满足&#xff1a; if($code mt_rand(1,0x36D) && $password $flag || $username "admin"){if($code admin){ech…

shell-awk文本处理工具

1、awk概述 AWK 是一种处理文本文件的语言&#xff0c;是一个强大的文本分析工具。 它是专门为文本处理设计的编程语言&#xff0c;也是行处理软件&#xff0c;通常用于扫描、过滤、统计汇总工作 数据可以来自标准输入也可以是管道或文件 在 linux 上常用的是 gawk,awk …

【Gitlab】SSH配置和克隆仓库

生成SSH Key ssh-keygen -t rsa -b 4096 私钥文件: id_rsa 公钥文件:id_rsa.pub 复制生成的ssh公钥到此处 克隆仓库 git clone repo-address 需要进行推送和同步来更新本地和服务器的文件 推送更新内容 git push <remote><branch> 拉取更新内容 git pull &…

【Django】django模板与前端技术(html模板)

文章目录 “python包html”还是“html包python”?1.新建模板2.模板语法3.views.py测试 “python包html”还是“html包python”? 在前端页面中html代码比python多得多&#xff0c;所以一定是html包python最优&#xff01;于是引出今天的模板。 大体分为三个步骤&#xff1a;…

CPU350% JVM GC频繁并GC不掉EXCEL导出

背景&#xff1a; 有个Excel导出的需求&#xff0c;测试的时候&#xff0c;只要连续导出大量的数据就会导致FAT机器反请求反应迟钝&#xff0c;甚至卡死&#xff0c;无法恢复。 排查&#xff1a; 1 跳板机跳到机器上&#xff0c;查看 项目 ipd 执行ps -ef | grep 项目名称.j…

解决学生技能短板:泰迪智能科技2024年中职大数据实验室,全面提升学生实践能力

一、中职院校现状及实验室建设背景 在当今信息化时代&#xff0c;大数据技术已成为国家战略发展的重要方向。中职院校作为我国职业教育体系的重要组成部分&#xff0c;肩负着培养高素质技术技能人才的重任。然而&#xff0c;目前我国中职院校在大数据教育方面存在以下问题&…

Django Web开发:构建强大RBAC权限管理系统的实战指南

文章目录 前言一、rbac 基于角色的权限管理1.acl 基于用户的权限管理2.rbac 基于角色的权限管理 二、应用示例1.配置角色资源a.分析表b.核心逻辑c.使用transfer在前端实现资源配置d.页面效果 2.登录时获取对应权限a.员工登录b.中间件c.前端请求d.效果图 3.前端-路由守卫-页面权…

鸿蒙HarmonyOS开发:如何灵活运用动画效果提升用户体验

文章目录 一、动画概述1、动画的目的 二、显式动画 (animateTo)1、接口2、参数3、AnimateParam对象说明4、示例5、效果 三、属性动画 (animation)1、接口2、参数3、AnimateParam对象说明4、系统可动画属性4、示例5、效果 一、动画概述 动画的原理是在一个时间段内&#xff0c;…

IDEA缓存和索引

IDEA缓存和索引 —2020年06月10日 IntelliJ IDEA首次加载项目的时候。都会创建索引&#xff0c;而创建索引的时间根项目的文件多少成正比。 IntelliJ IDEA的缓存和索引主要是用来加快文件查询&#xff0c;从而加快各种查找、代码提示等操作的速度。 某些特殊情况下&#xf…

剑和沙盒 1 - Windows Sandbox 简介

Windows Sandbox 提供了一个轻量级桌面环境&#xff0c;可以安全地独立运行应用程序。安装在 Windows Sandbox 环境中的软件仍处于“沙盒”状态&#xff0c;独立于主机运行。 沙盒是临时的。关闭后&#xff0c;所有软件、文件和状态都会被删除。每次打开应用程序时&#xff0c…

scrapy 爬取旅游景点相关数据(一)

第一节 Scrapy 练习爬取穷游旅游景点 本项目为scrapy 练手项目&#xff0c;爬取的是穷游旅游景点列表数据 0 系统的环境 现在网上可以找到很多scrapy版本的视频或者代码&#xff0c;为避免混淆&#xff0c;下面列出本文开发过程中使用的软件版本。 scrapy 和 selenium 新版本和…

【NPU 系列专栏 3.1 -- - NVIDIA 的 Orin 和 Altan 和 Thor 区别】

请阅读【嵌入式及芯片开发学必备专栏】 文章目录 NVIDIA Orin、Altan 和 ThorNVIDIA Orin 简介NVIDIA Orin 主要特点NVIDIA Orin 应用场景 NVIDIA Altan 简介NVIDIA Altan 主要特点NVIDIA Altan 应用场景 NVIDIA Thor 简介NVIDIA Thor 主要特点NVIDIA Thor 应用场景 与 Hopper …

重生之“我打数据结构,真的假的?”--5.堆(无习题)

1.堆的概念与结构 如果有⼀个关键码的集合 &#xff0c;把它的所有元素按完全⼆叉树的顺序存储⽅ 式存储&#xff0c;在⼀个⼀维数组中&#xff0c;并满⾜&#xff1a; &#xff08; 且 &#xff09;&#xff0c; i 0、1、2... &#xff0c;则称为⼩堆(或⼤堆)。将根结点最⼤的…

【数组中的 k-diff 数对】python刷题记录

R2-哈希表。 有点easy的感觉 class Solution:def findPairs(self, nums: List[int], k: int) -> int:#查找对的方式是查找xk&#xff0c;不查找x-k是避免查找重复#此外&#xff0c;需要注意k0的问题mp{}for x in nums:if x in mp:mp[x]1else:mp[x]1ret0for x,cnt in mp.ite…