stm32 串口

news2024/11/28 23:53:19

目录

简介

串口通讯协议的物理层

电平标准

协议层

USART框图

总结

hal库代码

标准库代码


简介

        USARTUniversal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步收发器。USARTSTM32内部集成的硬件外设,STM32F103系列最多有3个通用同步异步收发器(USART), 2个通用异步收发器( UART)。 USART和UART的主要区别在于, USART支持同步通信,该模式有一根时钟线提供时钟。串口在嵌入式中经常使用,一般使用UART就足够了

串口通讯协议的物理层

        串口通讯的物理层有很多标准及变种,经常提到TTL、 RS232、 RS422、 RS485等标准,简单的说,就是为了适应不同的环境条件,使用了不同的电平标准。一般就使用TTL电平,引脚直接连接即可,假如微处理器在工业现场,需要连接一个几十米外的装置,则应该考虑将TTL电平转为RS232、 RS422、 RS485

        RS-232 电平等标准的信号不能直接被控制器直接识别,所以这些信号会经过一个“电平转换芯片”转换成控制器能识别的“TTL 标准”的电平信号,才能实现通讯

电平标准

        一般常使用 TTL 的电平标准,为了加大传输距离,可以增加电压、差分传输等方式

TTL接口的串口,硬件连接如下

        TX:数据发送;RX:数据接收;

协议层

        串口通信的数据包由发送设备的 TXD 接口传输到接收设备的 RXD 接口。在串口通信的协
议层中,规定了数据包的内容,它由起始位、主体数据、校验位以及停止位组成,通讯双方的
数据包格式要约定一致才能正常收发数据。

        波特率:一般选波特率都会有9600,19200,115200等选项。其实意思就是每秒传输这么多个比特位数(bit);
        起始位: 先发出一个逻辑”0”的信号,表示传输数据的开始;
        数据位:可以是5~8位逻辑”0”或”1”,先传输bit 0,在传输bit 1,依次类推;
        校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。 校验位是可选的,可以不传输;                        
        停止位:它是一个字符数据的结束标志,数据线变回逻辑”1”;

        一般使用的是8位数据位,1位起始位,1位停止位,无校验位

USART框图

        ① 引脚:主要是tx\rx数据发收,CK:在同步模式时,用于输出时钟;SW_RX:在单线和智能卡模式下接收数据,属于内部引脚,没有具体外部引脚;在硬件流控制时,RTS用于指示本设备准备好可接收数据,低电平说明本设备可以接收数据,CTS则是在低电平说明可以发数据

        ② 波特率发生器:计算波特率公式:波特率=外设时钟频率/USART_BRR寄存器的值*16

USART1挂载APB2上, USART2/3和USART4/5挂载APB1上。APB1时钟最大为36MHz, APB2时钟最大为72MHz。所以要配置USART1波特率为115200则寄存器USART_BRR为72000000/(115200*16)=39.0625

        ③发送器/接收器控制单元:向控制寄存器CR1、 CR2、 CR3和状态寄存器SR写入相应的位,可实现对USART数据的发送和接收控制。

        ④数据收发寄存器单元:发送移位寄存和接收移位寄存器,分别负责将发送数据并串转换和接收数据串并转换,从而实现数据在传输时,是一位一位的发送和接收。

总结

        比如发送一字节数据“ A”? “A”的ASCII值是0x41, 二进制就是01000001。事先双方约定好波特率、数据格式,如115200,数据位是8,停止位是1,不设校验位和流控

        初始电平为1(也就是高电平),发送方输出逻辑0(也就是低电平),并保持1位的时间,接收方检测到逻辑0,就知道对方准备发送数据了;

        发送方根据数据的bit 0-7设置引脚电平,并保持1位的时间,接收方读取引脚电平,得到bit 0-7;

        如果设置校验位还需要计算校验值,这里不设置可以省略这步

        最后发送方输出逻辑1,并保持1位的时间;接收方读取引脚电平, 直到数据传输结束

hal库代码

#define UARTx    USART1
#define UARTx_TX_PIN     GPIO_PIN_9
#define UARTx_RX_PIN     GPIO_PIN_10
#define UARTx_PORT       GPIOA

/*使能 USARTx 的输入输出引脚(GPIO)的时钟*/
#define USARTx_GPIO_CLK_EN() __HAL_RCC_GPIOA_CLK_ENABLE()
/*使能 USARTx 的时钟*/
#define USARTx_CLK_EN() __HAL_RCC_USART1_CLK_ENABLE()

#define USARTx_CLK_DIS() __HAL_RCC_USART1_CLK_DISABLE()

uint8_t buf[1]={0};

/*UART句柄*/
UART_HandleTypeDef g_uart1_hanle;

/*UART1初始化函数*/
void uart1_init(uint32_t baudrate)
{
    /*USART寄存器及地址:选择 USART1*/
    g_uart1_hanle.Instance = UARTx;
    /*配置波特率*/
    g_uart1_hanle.Init.BaudRate = baudrate;
    /*每次发送的字节长度:配置数据有效位为 8bit*/
    g_uart1_hanle.Init.WordLength = UART_WORDLENGTH_8B;
    /*每次发送后停止位长度: 一位停止位*/
    g_uart1_hanle.Init.StopBits = UART_STOPBITS_1;
    /*奇偶校验:不设校验位*/
    g_uart1_hanle.Init.Parity = UART_PARITY_NONE;
    /*流控设置:通常设置为None*/
    g_uart1_hanle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    /*收发模式:可收可发*/
    g_uart1_hanle.Init.Mode = UART_MODE_TX_RX;
    /*使用库函数初始化 USART1 的参数*/
    if(HAL_UART_Init(&g_uart1_hanle) != HAL_OK)
    {
        Error_Handler();
    }
    /*开启中断异步接收*/
    HAL_UART_Receive_IT(&g_uart1_hanle,(uint8_t *)buf,1);
}
/*重定义串口MSP回调函数,使能 USART1 的时钟,使能引脚时钟,并配置引脚的复用功能*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    /*保存GPIO参数设置;*/
    GPIO_InitTypeDef gpio_init_uart_struct = {0};
    /*判断是否想要的为USARTx(宏定义对应USART1)*/
    if(huart->Instance == UARTx)
    {
        /*使能 USART1 的时钟*/
        USARTx_CLK_EN();
        /*使能 USART1 的输入输出引脚的时钟*/
        USARTx_GPIO_CLK_EN();
        /*USART1 GPIO配置*/
        gpio_init_uart_struct.Pin  = UARTx_TX_PIN;/*选择 USART1 的 TX 引脚*/
        gpio_init_uart_struct.Mode = GPIO_MODE_AF_PP;/*配置为复用推挽功能*/
        gpio_init_uart_struct.Speed = GPIO_SPEED_FREQ_HIGH;/*引脚翻转速率快*/
        HAL_GPIO_Init(UARTx_PORT, &gpio_init_uart_struct);
        
        gpio_init_uart_struct.Pin = UARTx_RX_PIN;/*选择 RX 引脚*/
        gpio_init_uart_struct.Pull = GPIO_PULLUP;/*时序空闲时候为高电平,所以上拉*/
        gpio_init_uart_struct.Mode = GPIO_MODE_AF_INPUT;/*配置为复用输入功能*/
        HAL_GPIO_Init(UARTx_PORT, &gpio_init_uart_struct);
        /*中断优先级,使能中断*/
        HAL_NVIC_SetPriority(USART1_IRQn,0,0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
    }
}

/*中断服务函数*/
void USART1_IRQHandler(void)
{
    HAL_UART_IRQHandler(&g_uart1_hanle);
    HAL_UART_Receive_IT(&g_uart1_hanle,(uint8_t *)buf,1);
    
}
/*回调函数*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    printf("\r\ninput: %c\r\n",buf[0]);
}
//printf重定义
/*printf和scanf会分别调用“ fputc()”和“ fgetc()”,因此这里重写这两个函数
 *使用HAL提供的函数实现收发数据
- huart:UART外设的句柄,用于标识具体的UART外设。
- pData:一个指向待发送数据的缓冲区的指针。
- Size:待发送数据的长度,以字节为单位。
- Timeout:发送超时时间,如果数据在超时时间内没有发送完成,则函数会返回错误。
 */
int fputc(int ch, FILE *f)
{
    HAL_UART_Transmit(&g_uart1_hanle,(uint8_t*)&ch, 1, 10);
    return ch;
}
int fgetc(FILE *f)
{
    uint8_t ch = 0;
    HAL_UART_Receive(&g_uart1_hanle, (uint8_t*)&ch, 1, 10);
    return (int)ch;
}

标准库代码

// 串口1-USART1
#define  USART_BAUDRATE           115200
#define  USARTx                   USART1
#define  USARTx_CLK               RCC_APB2Periph_USART1
#define  USARTx_GPIO_CLK           (RCC_APB2Periph_GPIOA)
//apb时钟线使能函数
#define  USARTx_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  USARTx_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd

 USART GPIO 引脚宏定义
#define  USART_TX_GPIO_PIN        GPIO_Pin_9
#define  USART_RX_GPIO_PIN        GPIO_Pin_10
#define  USART_RX_GPIO_PORT       GPIOA
//中断相关
#define  USARTx_IRQ                USART1_IRQn
#define  USARTx_IRQHandler         USART1_IRQHandler

uint8_t rx_data[1]={0};

void uart_init(void)
{
    /*开启时钟*/
    USARTx_APBxClkCmd(USARTx_CLK,ENABLE);
    USARTx_GPIO_APBxClkCmd(USARTx_GPIO_CLK,ENABLE);

    /*初始化GPIO*/
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;/*发送引脚,输出模式:复用推挽输出*/
    GPIO_InitStruct.GPIO_Pin = USART_TX_GPIO_PIN;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(USART_RX_GPIO_PORT,&GPIO_InitStruct);
    
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;/*接收引脚,输入模式:上拉输入*/
    GPIO_InitStruct.GPIO_Pin = USART_RX_GPIO_PIN;
    GPIO_Init(USART_RX_GPIO_PORT,&GPIO_InitStruct);
    
    /*初始化uart接收*/
    USART_InitTypeDef USART_InitStruct;
    USART_InitStruct.USART_BaudRate = USART_BAUDRATE;/*波特率*/
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;/*不使用硬件流控*/
    USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;/*收发模式*/
    USART_InitStruct.USART_Parity = USART_Parity_No;/*不使用校验*/
    USART_InitStruct.USART_StopBits = USART_StopBits_1;/*一位停止位*/
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;/*8位字长*/
    USART_Init(USARTx,&USART_InitStruct);
    /*使能中断,开启EX标志位到NVIC的输出*/
    USART_ITConfig(USARTx, USART_IT_RXNE,ENABLE);
    /*配置NVIC*/
    /*分组*/
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    /*初始化NVIC的USART通道*/
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = USARTx_IRQ;/*中断通道*/
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;/* 使能中断 */
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; /* 抢断优先级*/
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;  /* 子优先级 */
    NVIC_Init(&NVIC_InitStruct);
    /*开启USART*/
    USART_Cmd(USARTx,ENABLE);
}

/*中断服务函数*/
void USARTx_IRQHandler(void)
{
    if(USART_GetITStatus(USARTx,USART_IT_RXNE) == SET)
    {
        rx_data[0] = USART_ReceiveData(USARTx);
        printf("\r\ninput: %c\r\n",rx_data[0]);
        /*清除中断标志位*/
        USART_ClearITPendingBit(USARTx,USART_IT_RXNE);
    }
}

//重定位printf
/*printf和scanf会分别调用“ fputc()”和“ fgetc()”,因此这里重写这两个函数 
 *通过printf输出到串口打印,默认打印到屏幕,但是只支持一个串口使用*/
int fputc(int ch, FILE *f)
{
    uart_send_byte(ch);
    return ch;
}

int fgetc(FILE *f)
{
    return  USART_ReceiveData(USARTx);
}

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

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

相关文章

在职一年多,一个29岁软件测试工程师的心声

简单的先说一下,坐标西安,16届本科毕业,目前在跳槽,算上国庆节前的面试,一共有面试了5家公司(因为不想请假,因此只是每个晚上去其他公司面试,所以面试的公司比较少)其中成…

如何打造一支敏捷测试团队

文章目录 摘要01 从测试角度理解敏捷理念什么是敏捷?测试人员应该怎样理解敏捷理念?敏捷宣言对于测试活动的启发与思考总结如下。敏捷原则12条敏捷实践框架为什么要做敏捷 02 什么是敏捷测试03 敏捷测试为什么会失败04 诊断脑暴会的成果示例敏捷测试原则…

微信小程序自定义弹窗阻止滑动冒泡catchtouchmove之后弹窗内部内容无法滑动

自定义弹窗 如图所示: 自定义弹窗内部有带滚动条的盒子区域 问题: 在盒子上滑动,页面如果超出一屏的话,也会跟着一起上下滚动 解决方案:给自定义弹窗 添加 catchtouchmove 事件,阻止冒泡即可 网上不少…

复杂任务也不怕!上海AI Lab提出增强型LLM框架—ControlLLM,大模型可操控多模态工具

多模态交互的一个新兴的实现方式是工具增强语言模型,这些模型将大型语言模型(LLM)作为主要控制器,并将具有不同功能的工具作为插件进行整合。这有助于解决各种多模态任务,并为多模态交互中的创新应用打开了大门。 尽管…

6-5 先序输出叶结点 分数 10

void PreorderPrintLeaves(BinTree BT) {if (!BT)return;if (!BT->Left && !BT->Right)printf(" %c", BT->Data);PreorderPrintLeaves(BT->Left);PreorderPrintLeaves(BT->Right); }

ICLR 2022)ODConv:即插即用的动态卷积 (附代码)

论文地址:Omni-Dimensional Dynamic Convolution | OpenReview 代码地址:https://github.com/OSVAI/ODConv/blob/main/modules/odconv.py 1.是什么? ODConv是一种动态卷积算法,它的原理是在卷积过程中,根据输入数据的…

第五章 I/O管理 十一、减少磁盘延迟时间的方法

目录 一、交替编号 1、定义: 二、磁盘地址结构的设计 三、错位命名 四、总结 一、交替编号 1、定义: 若采用交替编号的策略,即让逻辑上相邻的扇区在物理上有一定的间隔,可以使读取连续的逻辑扇区所需要的延迟时间更小。 二、…

AI智能语音识别模块(二)——基于Arduino的语音控制MP3播放器

文章目录 简介离线语音控制模块Mini MP3模块0.96寸 OLED模块实验准备安装库接线定义主要程序实验效果注意事项总结 简介 在前面一篇文章里我们对AI智能语音识别模块进行了介绍,并对离线语音模组下载固件的过程进行了一个简单描述,不知道大家还记不记得&…

Nginx+keepalived实现七层的负载均衡

1.keepalived VRRP 介绍 keepalived是什么? keepalived是集群管理中保证集群高可用的一个服务软件,用来防止单点故障。 keepalived工作原理 keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol&…

视频AI智剪,批量剪辑助力高效创作

视频AI智剪是一种基于人工智能技术的自动化剪辑工具,它可以自动对视频素材进行分析、筛选、剪辑和优化,从而生成一部高质量的视频作品。而批量剪辑则是指利用AI智剪技术,同时对多个视频素材进行自动化剪辑,大大提高了剪辑效率。本…

NI‑9237国产化50 kS/s/ch,桥模拟输入,4通道C系列应变/桥输入模块

50 kS/s/ch,桥模拟输入,4通道C系列应变/桥输入模块 NI‑9237提供了所有的信号调理功能来实现多达四个基于桥的传感器的供电和测量。该模块提供通道间零相位延迟的应变或负载测量。它还具有60 VDC隔离和1,000 Vrms瞬态隔离,提供高…

操作系统 day03(运行机制)

机器指令 二进制机器指令就是处理器(CPU)能识别、执行的最基本命令 程序运行的过程就是CPU执行一条一条的机器指令的过程 应用程序和内核程序 操作系统的最重要角色是:系统资源的管理者,而操作系统的对系统资源的管理工作就是…

Mysql系列 -索引模型数据结构

索引就是排好序的数据结构,可以帮助我们快速的查找到数据,那么底层的数据到底是如何存储的呢? 为什么InnoDB 用的是Btree 存储结构? 大家可以看看这个可视化的网站 数据结构和算法的可视化工具 可以看到数据结构里面有链表&…

JVM虚拟机:垃圾回收算法和垃圾回收器之间的关系

GC垃圾回收算法 在前面的课程中我们学习了GC垃圾回收算法,分别为: 引用回收算法 复制算法 标记清除算法 标记整理算法 这些垃圾回收算法是理论,有多种垃圾回收器可以实现这些理论。目前为止没有最完美的垃圾回收器,只能针对具体的情况选择最合适的垃圾回收器,进行分代收集…

高校教务系统登录页面JS分析——天津大学

高校教务系统密码加密逻辑及JS逆向 本文将介绍天津大学教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文,你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习,勿用于非法用途。 一、密…

MFC网络通信-Udp服务端

目录 1、UI的布局 2、代码的实现: (1)、自定义的子类CServerSocket (2)、重写OnReceive事件 (3)、在CUdpServerDlg类中处理 (4)、在OnInitDialog函数中 &#xff0…

Leetcode刷题详解——Pow(x, n)

1. 题目链接:50. Pow(x, n) 2. 题目描述: 实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,xn )。 示例 1: 输入:x 2.00000, n 10 输出:1024.00000示例 2:…

Mozilla Firefox 119 现已可供下载

Mozilla Firefox 119 开源网络浏览器现在可以下载了,是时候先看看它的新功能和改进了。 Firefox 119 改进了 Firefox View 功能,现在可以提供更多内容,如最近关闭的标签页和浏览历史,你可以按日期或网站排序,还支持查…

项目知识点总结-住房图片信息添加-Excel导出

(1)住房信息添加 Controller: RequestMapping("/add")public String add(Home home, Model model) throws IOException{String sqlPath null;//定义文件保存的本地路径String localPath"D:\\AnZhuang\\Java项目\\选题\\Xin-…

YOLOv5 分类模型的加载

YOLOv5 分类模型的加载 flyfish 版本 6.2 yolov5s分类模型 python classify/train.py --model resnet18.pt --data cifar100 --epochs 5 --img 224resnet18模型 python classify/train.py --model resnet18.pt --data cifar100 --epochs 5 --img 128导出模型看一下结构 p…