stm32串口的使用

我们先简单介绍一下基本的概念

1数据的通信方式:

2 这里三种数据传输方向分类大家需要记住。后面的通信都会涉及到。

3

我们来看一下常见的通信,这里我们使用usart

一什么是串口

1.1概述 :

指按位发送和接收的接口

但是,rs233的电平逻辑和其他的是否一致呢? 我们知道在单片机我们是通过电平的变化来区分逻辑1和逻辑0 然后进行分析得到的数据

那我们来看一下RS232的逻辑电平和COMS和TTL的,这里CMOS和TTL是我们控制器的电平

不一致,所以需要进行转换,一般是需要使用串口工具进行转换的,但是我使用版子上有usb转串口所以就不需要外接串口工具了。

usart和uart都是全双工异步通信

二分析原理图

三stm32cubemx配置

在LED的基础上进行配置

配置为Asynchronous(异步)波特率是115200

四代码分析

这里说个题外的

如果我们想使用printf输出相关数据到屏幕上好方便定位问题我们在usart.c里面加

#include "stdio.h" //不能忘记
#if 1#if (__ARMCC_VERSION >= 6010050)            /* 使用AC6编译器时 */
__asm(".global __use_no_semihosting\n\t");  /* 声明不使用半主机模式 */
__asm(".global __ARM_use_no_argv \n\t");    /* AC6下需要声明main函数为无参数格式,否则部分例程可能出现半主机模式 */#else
/* 使用AC5编译器时, 要在这里定义__FILE 和 不使用半主机模式 */
#pragma import(__use_no_semihosting)struct __FILE
{int handle;/* Whatever you require here. If the only file you are using is *//* standard output using printf() for debugging, no file handling *//* is required. */
};#endif/* 不使用半主机模式,至少需要重定义_ttywrch\_sys_exit\_sys_command_string函数,以同时兼容AC6和AC5模式 */
int _ttywrch(int ch)
{ch = ch;return ch;
}/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{x = x;
}char *_sys_command_string(char *cmd, int len)
{return NULL;
}/* FILE 在 stdio.h里面定义. */
FILE __stdout;/* MDK下需要重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{while ((USART1->SR & 0X40) == 0);     /* 等待上一个字符发送完成 */USART1->DR = (uint8_t)ch;             /* 将要发送的字符 ch 写入到DR寄存器 */return ch;
}
#endif

 记住一定要在BEGIN 和END之间添加不然下次配置的时候就会消失

这里就是串口的基础配置

我们来看几个HAL函数

1 我复制了一部分 其中函数名和函数的官方解释 

/*** @brief  Sends an amount of data in blocking mode.* @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),*         the sent data is handled as a set of u16. In this case, Size must indicate the number*         of u16 provided through pData.* @param  huart Pointer to a UART_HandleTypeDef structure that contains*               the configuration information for the specified UART module.* @param  pData Pointer to data buffer (u8 or u16 data elements).* @param  Size  Amount of data elements (u8 or u16) to be sent* @param  Timeout Timeout duration* @retval HAL status*/
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)

 函数的意思是以阻塞发送串口数据 第一个变量是串口几 这里我们使用是串口1 

第二个变量是一个指针,指向发送数据的一个指针 类型是uint8_t uint16_t 如果不是这俩个类型需要加强制类型转换

第三个是发送数据的大小 

第四个是发送的最大时间

4.1比如我们使用串口发送hello 使用printf输出aaa

 这里hello不是函数要求得数据类型,所以我们需要进行强制类型转换

我们打开串口工具,这里我使用的正点原子的,大家也可以使用其他的都一样

 可以看到正常发送数据到串口助手上了

4.2 接收数据并将接收到得数据发送

这里我们还是先介绍一个HAL库函数

/*** @brief  Receives an amount of data in blocking mode.* @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),*         the received data is handled as a set of u16. In this case, Size must indicate the number*         of u16 available through pData.* @param  huart Pointer to a UART_HandleTypeDef structure that contains*               the configuration information for the specified UART module.* @param  pData Pointer to data buffer (u8 or u16 data elements).* @param  Size  Amount of data elements (u8 or u16) to be received.* @param  Timeout Timeout duration* @retval HAL status*/
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

函数的作用:在阻塞模式下接收大量数据

这里参数和上面的类似 我就不一一说明了

代码如下

这里我发送的是www,串口接收到放到uart里面,然后再发送出来 

 到这里基本知识已经结束,但是大家想一想如果每次都需要在主函数里面去执行接收语句是不是很浪费时间,并且如果发送数据的时候,在执行其他的语句就会导致无法接收到数据。

其次阻塞的发送,太浪费CPU了

所以我们结合上节课使用的中断(触发某个条件的时候)执行串口语句

即当有数据过来,触发中断,告诉cpu需要处理中断(串口的数据)然后再执行其他的

同理我们也可以通过串口接收的数据进行判断,该数据是要表达出什么意思

五中断方式的串口接收数据

在上面配置的基础打开串口1的中断。

这个时候我们可以看到关于中断的一些配置,同理我们找到中断回调函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

我们在这里去编写代码

同理我们先介绍HAL库函数

1 函数得作用是以中断得形式接收数据

/*** @brief  Receives an amount of data in non blocking mode.* @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),*         the received data is handled as a set of u16. In this case, Size must indicate the number*         of u16 available through pData.* @param  huart Pointer to a UART_HandleTypeDef structure that contains*               the configuration information for the specified UART module.* @param  pData Pointer to data buffer (u8 or u16 data elements).* @param  Size  Amount of data elements (u8 or u16) to be received.* @retval HAL status*/
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

2 函数作用:以中断得形式发送数据

/*** @brief  Sends an amount of data in non blocking mode.* @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),*         the sent data is handled as a set of u16. In this case, Size must indicate the number*         of u16 provided through pData.* @param  huart Pointer to a UART_HandleTypeDef structure that contains*               the configuration information for the specified UART module.* @param  pData Pointer to data buffer (u8 or u16 data elements).* @param  Size  Amount of data elements (u8 or u16) to be sent* @retval HAL status*/
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)

这里需要注意,以中断得形式接收数据是需要我们去打开得即

我们在初始化得时候,需要设置一下接收。然后我们看中断回调函数

这里我把回调函数放在了uart.c里面去写 

代码实现得比较简单 先接收数据 然后发送 根据接收得数据是否为1 是则进行led0得电平翻转

这里 可以看到为什么代码里面写得是 ==49 因为我们通过串口发送的1 实际上对计算机来说是‘1’

即字符1 通过ascall码表 可以知道对应的十进制数是49

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【“状态机” 解析UART不定长度的协议帧】

【“状态机” 解析UART不定长度的协议帧】 1. 数据帧格式2. 状态机原理3. 代码实现 通信设计中考虑协议的灵活性,经常把协议设计成“不定长度”。如果一个系统接收上述“不定长度”的协议帧,将会有一个挑战–如何高效接收与解析。一个实例如下图&#xf…

【蓝桥杯嵌入式】11届程序题刷题记录及反思

一、题目介绍 按键输入:短按 模拟电压输出:ADC LCD显示 PWM输出:PA6,PA7 二、usr.c #include "usr.h" #include "lcd.h" #include "stdio.h" #include "tim.h" #include "adc.h" /*v…

道本科技智慧合规助力企业转型升级

在当今这个快速变化的商业世界里,企业合规管理已经从一项基本的监管要求转变为推动企业持续发展的关键动力。合规不仅是避免法律麻烦的盾牌,它还充当着引领企业向更高效、更可靠和更可持续方向发展的催化剂。而在实现这一目标的过程中,智慧合…

隐私计算实训营第六讲-隐语PIR介绍及开发实践

隐私计算实训营第六讲-隐语PIR介绍及开发实践 文章目录 隐私计算实训营第六讲-隐语PIR介绍及开发实践1.隐语实现PIR总体介绍1.1按服务器数量分类1.2按查询类型分类 2. Index PIR - SealPIR3. Keyword PIR - Labeled PSI4.隐语PIR功能分层5.隐语PIR后续计划PIR协议开发PIR调用框…

ndk ffmpeg

报错: 解决办法: 报错 解决办法:

干货教程【AI篇】| AI大模型文字生成视频环境部署小白级教程

只需要一个主题、一个词语,或者一段描述,就可以生成一个完整的短视频的工具来啦! 在文章下方公众号中回复关键词【aivd】即可获取完整代码和配套软件 工具获取 ps:本文不涉及任何代码开发工作,仅仅作为软件推荐。 如…

洛谷P1000超级玛丽游戏题解[Python, Rust, Go]

题目 打印超级玛丽字符图像 小技巧 直接复制题目的超级玛丽符号首行会有空格问题,一直AC不过,一行一行地复制就OK了👌。 Rust 题解 fn main() {println!(" ********************####....#.#..###.....##....###...…

Linux:冯·诺依曼结构 OS管理机制

Linux:冯诺依曼结构 & OS管理机制 冯诺依曼结构OS管理机制OS对下层硬件的管理OS对上层用户的服务 冯诺依曼结构 我们常见的计算机,比如笔记本,台式电脑。以及一下不常见的计算机,比如服务器,几乎都遵循冯诺依曼体…

element-ui 修改el-form-item样式

文章目录 form结构修改el-form-item所有样式只修改label只修改content只修改input只修改button form结构 <el-form :model"formData" label-width"80px"> <el-form-item label"label1"> <el-input v-model"formData.valu…

深度学习500问——Chapter05: 卷积神经网络(CNN)(4)

文章目录 5.18 卷积神经网络凸显共性的方法 5.18.1 局部连接 5.18.2 权值共享 5.18.3 池化操作 5.19 全连接、局部连接、全卷积与局部卷积 5.20 局部卷积的应用 5.21 NetVLAD池化 参考文献 5.18 卷积神经网络凸显共性的方法 5.18.1 局部连接 我们首先了解一个概念&#xff0c…

2024年03月CCF-GESP编程能力等级认证Scratch图形化编程二级真题解析

本文收录于专栏《Scratch等级认证CCF-GESP真题解析》,专栏总目录・点这里. 一、单选题(共 10 题,每题 3 分,共 30 分) 第1题 小杨的父母最近刚刚给他买了一块华为手表,他说手表上跑的是鸿蒙,这个鸿蒙是?( )。 A、小程序 B、计时器 C、操作系统 D、神话人物 答案:…

【QT学习】4.浮动窗口

结果&#xff1a; 代码&#xff1a; //制作核心控件&#xff1a;文本编辑框QTextEdit* pTextEditnew QTextEdit;//制作浮动控件connect(pMenu1,&QMenu::triggered,[](QAction* pAction){qDebug()<<pAction->text()<<endl;if(pAction->text()"浮动…