STM32入门教程——串口通讯

article/2025/10/16 15:43:29

目录

1.认识串口

2.stm32串口介绍

2.1 查询方式

2.1 中断方式

2.2 DMA方式

3.使用stm32串口实现printf


        串口作为嵌入式设备最常用的外设之一,被广泛的应用。本文介绍STM32串口的如何使用。从以下几个方面介绍:

1.认识串口

        常用串口的引脚主要由TX,RX,RTS,CTS,GND组成。RTS与CTS用于硬件流控,TX与RX为数据通讯引脚。两个串口通信连接示意图如下(GND未体现):

         RTS与CTS主要是为了进行通讯流控制的,在实际应用中可以选择开启或关闭流控功能,如果流控打开,当usart1需要发送数据时,会先判断CTS的电平信号,当CTS为低电平时,表示usart2可以的FIFO未满,可以继续接收,usart1就可以发送数据,当usart2的FIFO中数据未被及时读走,即FIFO满了,usart2就会其RTS引脚将usart1的CTS引脚拉高,此时usart1就不再发送数据。虽然流控可以控制硬件的发送,保证接收的FIFO不溢出,但是实际使用中,很少会用到,由软件来保证FIFO数据被及时取走。

        串口通讯通常需要设置的参数有:起始位,停止位,数据位,校验位,波特率,有无流控。根据需要配置成什么样的参数需要两个通讯设备保持一致才可正常通讯。

2.stm32串口介绍

        以STM32F103为例介绍,STM32F103支持多路串口,串口支持硬件校验,硬件控制,帧错误检测,空闲状态检测等功能,支持查询方式收发,中断方式,以及DMA方式传输。空闲帧检测功能为应用开发提供了许多方便之处。串口特征如下:

         STM32F103同一串口可以配置使用不同的GPIO。如UART1即可使用PA9,PA10也可以使用PB6与PB7。具体根据硬件选择。

        串口通讯常见的有3种方式,查询方式,中断方式,DMA方式。以下分别介绍这三种通讯方式。为使用串口功能,我们需要将stm32官方提供的usart相关SDK添加进工程中,添加方法可参照STM32入门教程——点亮一个LED_单片机的码农的博客-CSDN博客一文中的方法。进入manage run-time enviorenment对话框,选中usart即可。当然串口需要用到GPIO,后面也会用介绍中断传输与DMA传输,所以可以一并把GPIO,EXTI,DMA一并加入到工程中。

        无论使用何种方式通讯,GPIO的配置及串口参数配置都一样,这里以STM32F103使用USART1为例,REMPA为0时,PA9与PA10分别作为USART1的发送与接受,则串口的GPIO初始化如下:

#define  USART1_TX_GPIO_PORT       GPIOA
#define  USART1_TX_GPIO_PIN        GPIO_Pin_9
#define  USART1_RX_GPIO_PORT       GPIOA
#define  USART1_RX_GPIO_PIN        GPIO_Pin_10void uart_gpio_init(void){GPIO_InitTypeDef GPIO_InitStructure;// 打开串口GPIO的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 将USART Tx的GPIO配置为推挽复用模式GPIO_InitStructure.GPIO_Pin = USART1_TX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(USART1_TX_GPIO_PORT, &GPIO_InitStructure);// 将USART Rx的GPIO配置为浮空输入模式GPIO_InitStructure.GPIO_Pin = USART1_RX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(USART1_RX_GPIO_PORT, &GPIO_InitStructure);
}

 串口参数配置如下:

#define USART1_BAUDRATE   115200
void usart_param_init(void)
{USART_InitTypeDef USART_InitStructure;// 配置串口的工作参数// 配置波特率USART_InitStructure.USART_BaudRate = USART1_BAUDRATE;// 配置针数据长度为8位USART_InitStructure.USART_WordLength = USART_WordLength_8b;// 配置停止位为1位停止位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(USART1, &USART_InitStructure);// 使能串口USART_Cmd(DEBUG_USARTx, ENABLE);
}

        此时,串口1的配置已经完成。

2.1 查询方式

        查询方式使用最为简单,只需要配置串口的基本属性,通过上述配置后直接写串口寄存器即可。串口发送函数如下:


/*****************  查询方式发送数据 **********************/
void usart1_send(char *buff,int32_t len)
{unsigned int k=0;for(int32_t k = 0;i < len;k++){/* 发送一个字节数据到USART */USART_SendData(USART1,buff[k]);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);}
}
uint32_t usart1_read(uint8_t *buff,uint32_t len,uint32_t time_out)
{uint32_t tick = 0;tick = get_system_tick();for(uint32_t i = 0;i < len;i++){while((RESET == USART_GetFlagStatus(usart1,USART_FLAG_RXNE))&&(get_system_tick() < (tick + time_out)));buff[i] = USART_ReceiveData(usart1);}
}

2.1 中断方式

        stm32串口支持的中断类型有很多种,具体如下:

  *     @arg USART_IT_CTS:  CTS change interrupt (not available for UART4 and UART5)
  *     @arg USART_IT_LBD:  LIN Break detection interrupt
  *     @arg USART_IT_TXE:  Transmit Data Register empty interrupt
  *     @arg USART_IT_TC:   Transmission complete interrupt
  *     @arg USART_IT_RXNE: Receive Data register not empty interrupt
  *     @arg USART_IT_IDLE: Idle line detection interrupt
  *     @arg USART_IT_PE:   Parity Error interrupt
  *     @arg USART_IT_ERR:  Error interrupt(Frame error, noise error, overrun error)

        使用比较多的是TC中断与RXNE中断,即发送完成中断与接收中断。为使用中断方式通讯,在完成串口基本参数配置后,还需要进行中断相关的初始化。在需要发送数据时开启串口TC中断,需要接收时开启RXNE中断,当然,实际应用过程中,MCU可能是要随时接收数据,所以RXNE中断可以在初始化后一直开启。开启中断与关闭中断的代码如下:

USART_ITConfig(USART1, USART_IT_TC, ENABLE);//开启TC中断
USART_ITConfig(USART1, USART_IT_TC, DISABLE);//关闭TC中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启RXNE中断
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);//开启TC中断

        以上操作的中断仅是控制串口外设是否会产生中断请求,那么外设的中断请求是否要被MCU响应,还需要开启串口的中断。串口中断初始化如下:

void usart1_irq_init(void)
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}

        当程序中开启了中断且有中断产生时,程序需要定义中断处理函数,否则中断产生后,会导致程序死机。串口中断也一样。中断函数函数的定义中startup.s中有定义。如下图:

因此,我们需要定义usart1的中断处理函数,中断进行数据发送参考代码如下:

#define USART1_TX_BUFF_SIZE 100
static uint8_t usart1_tx_buff[USART1_TX_BUFF_SIZE] = {0};
static uint32_t usart1_tx_buff_write_idx = 0;
static uint32_t usart1_tx_buff_read_idx = 0;void usart1_sendbytes_irq(uint8_t *buff,uint32_t len)
{uint8_t flag = 0;if(usart1_tx_buff_write_idx == usart1_tx_buff_read_idx){flag = 1;}for(uint32_t i = 0;i < len;i++){usart1_tx_buff[usart1_tx_buff_write_idx] = buff[i];usart1_tx_buff_write_idx ++;if(usart1_tx_buff_write_idx >= USART1_TX_BUFF_SIZE){usart1_tx_buff_write_idx = 0;}}if(flag){USART_SendData(USART1,usart1_tx_buff[usart1_tx_buff_read_idx]);USART_ITConfig(USART1, USART_IT_TC, ENABLE);//开启TC中断}
}void USART1_IRQHandler(void)
{uint8_t temp = 0;if(SET == USART_GetITStatus(USART1, USART_IT_TC)){usart1_tx_buff_read_idx++;if(usart1_tx_buff_read_idx >= USART1_TX_BUFF_SIZE){usart1_tx_buff_read_idx = 0;}if(usart1_tx_buff_read_idx== usart1_tx_buff_write_idx ){//all data sendUSART_ITConfig(USART1, USART_IT_TC, DISABLE);}else{temp = usart1_tx_buff[usart1_tx_buff_read_idx];	USART_SendData(USART1, temp);  //send one byte}}if(SET == USART_GetITStatus(USART1, USART_IT_RXNE)){temp = USART_ReceiveData(usart1);//receice one byte}
}

2.2 DMA方式

        stm32串口支持DMA方式进行数据收发。不同的串口使用的DMA通道不同,具体使用哪一个DMA通道需要根据芯片定义确定,如下图所示:

         由上图知,usart1的发送使用的是DMA1通道4,接收使用DMA1的通道5,因此初始化时要选对正确的通道。DMA的初始化主要是设置数据方向(外设到MEMORY,MEMORY到外设,外设到外设等),起始地址,数据传输大小,地址是否递增等。串口发送,DMA方向为memory到外设,接收时方向为外设到memory,以下是串口1使用DMA发送的初始化代码:

#define USART1_DMA_TX_SIZE  100
static uint8_t gUartDmaTxBuffer[USART1_DMA_TX_SIZE] = {0};
static DMA_InitType DMA_InitStructure;
void usart1_dma_init(void)
{USART_InitType USART_InitStructure;DMA_DeInit(DMA1_Channel4);DMA_StructInit(&DMA_InitStructure);DMA_InitStructure.PeriphAddr     = USART1_DR_Base;DMA_InitStructure.MemAddr        = (uint32_t)gUartDmaTxBuffer;DMA_InitStructure.Direction      = DMA_DIR_PERIPH_DST;DMA_InitStructure.BufSize        = USART1_DMA_TX_SIZE;    DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE;DMA_InitStructure.DMA_MemoryInc  = DMA_MEM_INC_ENABLE;DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE;DMA_InitStructure.MemDataSize    = DMA_MemoryDataSize_Byte;DMA_InitStructure.CircularMode   = DMA_MODE_NORMAL;DMA_InitStructure.Priority       = DMA_PRIORITY_VERY_HIGH;DMA_InitStructure.Mem2Mem        = DMA_M2M_DISABLE;DMA_Init(DMA1_Channel4, &DMA_InitStructure);USART_EnableDMA(USART1, USART_DMAREQ_TX, ENABLE);
}

        通过上述DMA初始化后,即可通过DMA进行数据发送,DMA发送数据代码如下:

void usart1_send_by_dma(uint8_t *buff,uint31_t size)
{memcpy(gUartDmaTxBuffer,buff,size);DMA_InitStructure.MemAddr    = (UINT32)gUartDmaTxBuffer;DMA_InitStructure.BufSize    = size;DMA_Init(DMA1_Channel4, &DMA_InitStructure);  DMA_EnableChannel(DMA1_Channel4, ENABLE);
}

        至此,串口3种通讯方式已经介绍完毕。

3.使用stm32串口实现printf

        在使用STM32做项目时,经常需要使用串口打印日志,那么如何快速使用stm32串口实现日志打印呢?只需要实现fputc函数即可。

int fputc(int ch, FILE *f)
{uint16_t tmp = ch;USART_SendData(USART1,tmp);while(RESET == USART_GetFlagStatus(USART1,USART_FLAG_TXC));return (ch);
}

        只需要将函数串口初始化,并实现上述fputc函数就可以实现串口日志打印,和window中的printf使用方法完全一样,是不是很方便呢。


http://chatgpt.dhexx.cn/article/HpvQT0jt.shtml

相关文章

STM32—串口

串口介绍 串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方式的扩展接口。串行接口&#xff08;Serial Interface&#xff09;是指数据一位一位地顺序传送。其特点是通信线路简单&#xff0c;只…

【stm32】串口通信

串口通信 一、串口通信协议原理二、usart功能框图三、stm32库的配置 一、串口通信协议原理 串口在嵌入式系统当中是一类重要的数据通信接口&#xff0c;其本质功能是作为 CPU 和串行设备间的编码转换器。当数据从 CPU 经过串行端口发送出去时&#xff0c;字节数据转换为串行的…

STM32-串口通信详解

目录 前言 一、通信接口背景知识 1. 并行通信和串行通信 2. 串行通信的分类 二、STM32的串口通信基础 1. 串口通信接口 2. 串口通信框图 3. 串口通信相关寄存器 4. 波特率计算方法 三、库函数配置 1. 串口配置一般步骤 总结 前言 众所周知&#xff0c;串口通信是MC…

STM32串口通信

STM32串口通信 一、串口 1.串口概述 串口是单片机中最常用也是最简单的一种通信方式通信&#xff1a;两个或两个以上的设备进行数据交换 串口是用于两个设备之间的异步全双工通信 异步——》两个设备不需要共时钟 全双工——》两个设备之间服务于数据交换的“线”有两根 Tx&…

STM32-串口通信(串口的接收和发送)

文章目录 STM32的串口通信一、STM32里的串口通信二、串口的发送和接收串口发送串口接收 三、串口在STM32中的配置四、串口接收的两种实现方式1. 需要更改的地方2. 查询RXNE标志位3. 使用中断 总结 STM32的串口通信 本文在于记录自己的学习过程中遇到的问题和总结&#xff0c;各…

STM32串口通信详解

✅作者简介&#xff1a;嵌入式入坑者&#xff0c;与大家一起加油&#xff0c;希望文章能够帮助各位&#xff01;&#xff01;&#xff01;&#xff01; &#x1f4c3;个人主页&#xff1a;rivencode的个人主页 &#x1f525;系列专栏&#xff1a;玩转STM32 &#x1f4ac;保持学…

MacOS 安装 Matlab R2021b 手记

MacOS 安装 Matlab R2021b Maci64手记 1.下载MATLAB R2021b 安装包 2.双击MatlabR2021b_Mac64.dmg打开安装包,双击InstallForMacOSX.app开始安装程序 3.出现「install_unix想要进行更改」,出入开机密码,点击好 4.出现安装界面,点击「高级选项」,选择「我有文件安装密…

linux安装matlabRuntime

1.找到自己需要的文件夹&#xff0c;下载压缩包&#xff0c;版本自己发挥 wget https://ssd.mathworks.com/supportfiles/downloads/R2021a/Release/6/deployment_files/installer/complete/glnxa64/MATLAB_Runtime_R2021a_Update_6_glnxa64.zip 2.解压 unzip MATLAB_Runtim…

四步离线安装matlab工具包

四步离线安装matlab工具包 把刚才的压缩包解压在matlab 工具包的文件夹。&#xff08;其实哪里都行&#xff0c;防止误删&#xff09; 我的是matlab安装目录下面 打开Matlab --“主页” --“设置路径” 3. 添加文件夹-选择工具包文件夹 4. 点击切换路径按钮到工具包目录&am…

安装Matlab R2022a/64位

Matlab R2022a/64位下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1pb_523QrMvu–nOcmV1bqQ 提取码&#xff1a;lbcc 上面失效的看看这个 链接&#xff1a;https://pan.baidu.com/s/14cVeXQOLBqGfq3aKT45vPw 提取码&#xff1a;piq7 怎么快速下可以私信我。…

如何安装matlab?官网下载详细教程

MATLAB下载和安装教程&#xff08;官网下载&#xff09; 很多人在遇到专业数据处理时都得用到专业的数学软件&#xff0c;matlab就是这样一款对于数据处理非常有帮助的支持数据分析、算法开发和建模的专业工科数学软件。那么&#xff0c;怎么可以快速的正确安装&#xff1f;下…

【首发】 ubuntu20.04安装matlab2021b/matlab2020b

文章目录 一、下载地址1.1 2021b下载链接(BT)1.2 2021a下载链接1.3 2020b CSDN下载链接 二、MATLAB2021b安装方法2.1 Mount .iso文件2.2 通过./install 启动安装程序2.3 输入正版Key安装2.4 直接下一步2.5 选安装文件夹&#xff08;权限够&#xff09;2.6 选需要的包2.7 选link…

服务器远程安装Matlab2015

因为在windows上跑matlab实验&#xff0c;出现内存不足的情况&#xff0c;因此&#xff0c;希望能在服务器上安装一个matlab。然后出现各种问题&#xff0c;花了一天时间才装好&#xff0c;特此记录下。因为对于没装过的童靴来说&#xff0c;每一个步骤都很关键&#xff0c;因此…

从零开始在linux服务器设置matlab-1.安装matlab

目录 0.安装matlab (1)安装x11客户端 1.下载ssh工具 MobaXterm 2.创建ssh连接 3.配置服务器x11转发 (1)安装matlab 1.上传安装包 2.挂载iso 3.安装 4.弹出gui&#xff0c;按照gui的指引操作 到此安装完成 0.安装matlab 安装matlab时因为需要gui 而linux服务器默认没有所以…

Ubuntu18.04安装Matlab2019b

1.下载Matalab2019b 链接: https://pan.baidu.com/s/1yEOnDnm0XqqyY2-jkPOQZQ 提取码: qwer 2.创建挂载文件目录 // 在任意目录下创建挂载文件目录&#xff08;我是在temp目录&#xff09; sudo mkdir matlab3.挂载镜像 sudo mount -o loop [镜像文件的路径] [指定的…

Ubuntu安装matlab2018a

一. 安装文件 链接: https://pan.baidu.com/s/1H2JWXVZjoNOkLhhpVj8gzg 提取码: rb21 文件目录&#xff1a; 二. 安装步骤 1. 解压Matlab2018aLinux64Crack.tar.gz文件&#xff1a; $ tar -xzvf Matlab2018aLinux64Crack.tar.gz 解压后的文件目录&#xff1a; 2. 建立挂…

如何安装matlab2016b

如何安装matlab2016b,详细步骤教程 首先下载软件R2016b_win64.iso&#xff0c;然后解压&#xff0c;或者挂载到光驱中&#xff0c;点击setup.exe运行。如果出现错误&#xff0c;cannot find appropriate setup file表示解压或者挂载出错了。重新解压或者挂载一下。 license选择…

Ubuntu20.04安装matlab详细教程

这里安装的是MATLAB2015b版本&#xff0c;其他版本也可参照这个安装步骤&#xff01; 1. matlab2015b版本安装文件下载链接 链接: https://pan.baidu.com/s/1Xr1TFSrqDZAbhvyEff28rQ 密码: ojj0 2. MATLAB2015安装过程详解 下载的文件夹应该包含如下东西 第一步&#xff0c…

ubuntu18.04安装matlab2018

1. 一. 安装前的准备工作 将下载好的文件R2018a_glnxa64_dvd1.iso, R2018a_glnxa64_dvd2.iso, Crack放到目录/home/zzw/Downloads下 在该目录下新建dvd文件夹&#xff1a;mkdir dvd 二. 挂载镜像文件并安装Matlab 原文链接&#xff1a;https://blog.csdn.net/qq_37643960/a…

Ubuntu18.04 安装Matlab2021b

Ubuntu18.04/Linux下 安装Matlab2021b 1、软件下载2、安装3、安装matlab-support4、安装Troubleshotting5、安装成功开始使用6、更改系统默认快捷键7、可能出现的错误 1、软件下载 链接: https://pan.baidu.com/s/1e2w_ZXIoibMG6PfqVbf-6Q 提取码: dmfu解压后共有俩文件 2、…