STM32入门——串口通信原理

前言

本文采用了正点原子STM32F1mini开发板, 依据正点原子F103的教学视频进行学习笔记的整理和自己对串口通信的一些理解进行知识的整合。参考资料是《STM32不完全手册-库函数版本》的第8章串口实验和5.3usart串口文件夹介绍,官方资料参考《STM32中文参考手册V10》-第25张通用同步异步收发器(USART)。

一、串口通信接口知识

1.1 通信方法

  • 并行通信
    • 传输原理:数据各个位同时传输。
    • 优点:速度快
    • 缺点:占用引脚资源多
  • 串行通信
    • 传输原理:数据按位顺序传输。
    • 优点:占用引脚资源少
    • 缺点:速度相对较慢

1.2 串行通信的三种传送方式

按照数据传送方向,分为:

        单工:数据传输只支持数据在一个方向上传输

        半双工:允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;

         全双工:允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接受设备都有独立的接受和发送能力。

1.3 串行通信的通信方式

  • 同步通信:带时钟同步信号传输。-SPI,IIC通信接口
  • 异步通信:不带时钟同步信号。-UART(通用异步收发器),单总线

上面是比较常见的一些串行通信接口,其中UART与单总线是属于异步通信,也就是不需要SCL同步时钟引脚,区别在于UART是全双工通信,分别有TXD与RXD引脚,而单总线输入与输出共用一个DQ引脚;

SPI与I2C属于同步通信,区别同样在于通信方向上,这里SPI是全双工即包含一个MISO输出和一个MOSI输入两个引脚,而I2C为半双工也就是输入输入共用一个SDA引脚。

1.4 STM32的串口通信接口

  • UART:通用异步收发器
  • USART:通用同步异步收发器

大容量STM32F10x系列芯片,包含3个USART和2个UART。也就是说如果单论异步收发器,F10x系列芯片有5个UART可供使用,而这5个当中有2个USART可供同步通信使用。

二、STM32F1串口通信基础

2.1 UART异步通信方式引脚连接方法

—RXD:数据输入引脚,数据接收

—TXD:数据发送引脚,数据发送

若两端设备无转化器,则两端输入输出都为TTL电平,引脚连接需要反向连接,RXD连TXD,TXD连RXD。而当STM32芯片与电脑连接时,相互间则需要RS232转换器对两端引脚的输入输出进行转换,此时TxD与TxD分别通过转换器对应相连,这里不可以直接相连,因为两端电平是不兼容的。

单片机与单片机之间如果需要通过DB9相连接的话同样需要通过串口电平转换,都转换为232电平后才能进行连接。

2.2 UART异步通信方式引脚

2.3 UART异步通信方式特点

1. 全双工异步通信

2. 分数波特率发生器系统,提供精确的波特率

    -发送和接受共用的可编程波特率,最高可达4.5Mbits/s

3. 可编程的数据字长度(8位或者9位)

4. 可配置的使用DMA多缓冲器通信

5. 单独的发送器和接收器使能位

6. 检测标志:①接受缓冲器②发送缓冲器空③传输结束标志

7. 多个带标志的中断源。触发中断

8. 其他:校验控制,四个错误检测标志

2.4 串口通信过程

这里串口通信的原理图里,数据发送与接受经过的寄存器类似于GPIO原理图里的寄存器,不同的是这里输入输出数据寄存器是在MCU内核的第一个经过位置,而在GPIO里数据首先从MCU出发要通过位设置/清除寄存器。

2.5 STM32串口异步通信需要定义的参数:

①起始位

②数据位(8位或者9位)

③奇偶校验位(第9位)

④停止位(1,15,2位)

⑤波特率设置

2.6 STM32USART框图

①RX接收:数据从RX引脚进来通过编解码模块沿下方电路到接收移位寄存器,寄存器一位一位接收完数据后会一次性写到接收数据存储器(RDR),然后CPU进入RDR读取数据。

②TX发送:数据从CPU出发一次性到达发送数据寄存器(TDR),数据一次性发送给发送移位寄存器,发送移位寄存器按照事先约定好的波特率一位一位的将数据移出。

发送和接收都需要事先需要约定好波特率来控制,发送和接受的波特率分别由下方的发送器控制和接收器控制两个模块定义。两个模块的时钟共用一个波特率发生器。

大容量的f103芯片有五个USART串口,串口1时钟来源是PCLK2,串口2到5时钟来源是PCK1,相应的时钟会经过USARTDIV值,该值由USART_BRR来配置,USART_BRR的作用是可以用来配置小数或整数分频的波特率。由USART_BRR输出的值经过USARTDIV对小数进行16分之1整数倍的除法运算配置后再除以16得到最终波特率。

发送器控制与接收器控制连接着两个寄存器,分别是CR1、SR和中断控制。

SR寄存器主要用来存储一些传输过程中的状态标志位;

CR1寄存器一半用来对接收和发送进行使能,一半是中断使能,下面连接着中断控制可以产生中断。

三、STM32串口常用寄存器和库函数

3.1 常用的串口相关寄存器

  • USART_SR状态寄存器
  • USART_DR数据寄存器
  • USART_BRR波特率寄存器

1.2 波特率计算方法

Tx|Rx(BAUD)=\frac{f_{PCLK_{x}}}{(16*USARTDIV))}

上式中,f_{PCLK_{x}}是给串口的时钟;USARTDIV是一个无符号定点数。我们只要得到USARTDIV的值,就可以得到串口波特率寄存器USART1->BRR的值,反之亦然。

下面介绍如何通过USARTDIV得到串口USART_BRR寄存器的值。假设串口1要设置为115200的波特率,而PCLK2的时钟为72M。这样根据上面的公式有:

USARTDIV=72000000/(115200*16) = 39.0625

那么得到:

DIV_Fraction = 16*0.0625 = 1 = 0X01;

DIV_Mantissa = 39 = 0X27;

这样就得到了USART1->BRR的值为0X0271。只要设置串口1的BRR寄存器值为0X0271就可以得到115200的波特率。

3.2 串口操作常用相关库函数(省略入口参数):

(1)使能串口、中断及串口初始化

void USART_Init();//串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能。

void USART_Cmd();//使能串口

(2)从DR发送、接受数据

void USART_SendData();//发送数据到串口,DR

uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据

(3)标志位操作

FlagStatus USART_GetFlagStatus();//获取状态标志位

void USART_ClearFlag();//清除状态标志位

ITStatus USART_GetITStatus();//获取中断状态标志位

void USART_ClearITPendingBit();//清除中断状态标志位

四、串口配置方法

4.1 串口配置的一般步骤

①串口时钟使能,GPIO时钟使能:RCC_APB2PeriphClockCmd();

②串口复位:USART_DeInit();//这一步不是必须的

③GPIO端口模式设置:GPIO_Init();//模式设置为GPIO_Mode_AF_PP

④串口参数初始化:USART_Init();

⑤开启中断并且初始化NVIC//(如果需要开启中断才需要这个步骤)

⑥使能串口:USART_Cmd();

⑦编写中断处理函数:USARTx_IRQHandler();

⑧串口数据收发:

void USART_SendData();//发送数据到串口,DR

uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据

⑨串口传输状态获取:

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FlAG);

void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

4.2 串口实验步骤讲解

第一步串口使能,在项目中首先需要引入stm32f10x_rcc.c与相关头文件,新建一个main函数文件,在文件里编写一个串口的定义函数,由于这里使用的是串口1(USART1),在头文件中找到使能函数分别对GPIOA和USART1进行使能。

void My_USART1_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

随后对GPIO进行初始化模式设置,创建一个初始化结构体变量对GPIO端口的相关参数进行赋值,分别对端口9输出与端口10输入进行配置。

    GPIO_InitTypeDef GPIO_InitStrue;


    GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;
    GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
    GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
    GPIO_Init(GPIOA,&GPIO_InitStrue);
    
    GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;
    GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
    GPIO_Init(GPIOA,&GPIO_InitStrue);

第三步对串口进行初始化,这里同样需要创建一个结构体变量对参数进行赋值,方法与上面GPIO配置大体相同,只是在结构体变量的参数上有些区别,这里串口参数包括波特率、硬件流控制、模式(发送或接受模式)、奇偶校验、停止位与字长。串口配置完后使能即可。

    USART_InitTypeDef USART_InitStrue;

    USART_InitStrue.USART_BaudRate=115200;
    USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFLowControl_None;
    USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
    USART_InitStrue.USART_Parity=USART_Parity_No;
    USART_InitStrue.USART_StopBits=USART_StopBits_1;
    USART_InitStrue.USART_WordLength=USART_WordLength_8b;

    USART_Init(USART1, &USART_InitStrue);
    USART_Cmd(USART1);
}

串口初始化完毕后接下来我们用到了中断,首先需要设置中断优先级分组,相关函数定义在misc.c文件中,先在main.c文件里新建一个main函数。设置中断优先级分组,随后在串口初始化函数开启中断并且初始化NVIC。NVIC参数包括通道选择、开启通道、抢占优先级、指令优先级,相应定义在stm32f10x.h顶层头文件里。

void My_USART1_Init(void)
{
    NVIC_InitTypeDef NVIC_InitStrue;
    
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);    //开启串口接收中断

    NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;
    NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStrue.NVIC_IRQChannelRreemptionPriority=1;
    NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;

    NVIC_Init(&NVIC_InitStrue);
}


int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

接下来编写中断服务函数,函数本身定义在stm32f10x启动文件中,对应查阅即可。在中断服务函数里需要先进行if判断中断的类型,若是对应的中断则在if里对中断内容进行操作,这里我们接收从串口发送来的数据,简单的对数据进行发送即结束函数。在main函数里调用串口初始化函数,随后进入死循环等待单片机接收到数据进入中断状态。

void USART1_IRQHandler(void)
{
    if(USART_GetStatus(USART1,USART_IT_RXNE))    //根据中断类型进行分析,调用中断的状态
    {
        res = USART_ReceiveData(USART1);
        USART_SendData(USART1,res);            //处理接收数据
    }
}

int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    My_USART1_Init();
    while(1);            
    //初始化后程序一直在此等待,当电脑发送数据给单片机后单片机进入中断,
    //进入中断后单片机把数据发送给电脑
}

系统文件夹里的usart.c文件包括了中断服务函数USART1_IRQHandler(),编译过程可能存在重复定义,这里将usart.c文件删除即可。

下面是串口通信实验的具体操作内容,这里协议与协议要对应一致,将选项配置完后发送数据可以看到串口将数据原封不动的传输回来,与程序实现功能相同。

五、串口通信实验

5.1 串口通信代码

在system文件夹中存在一个usart.c文件,这里我们将上面写好的uart_init(u32 bound)初始化函数带到这里来,在main.c文件中调用该函数。这里我们将串口中断服务程序USART1_IRQHander(void)更改一下带到usart.c文件中,以下是更改后的中断服务程序代码。

#if EN_USART1_RX                           //如果使能了接收
void USART1_IRQHandler(void)               //串口1中断服务程序
{
	u8 Res;
    #if SYSTEM_SUPPORT_OS                  //如果SYSTEM_SUPPORT_OS为真,则需要支持OS
	    OSIntEnter();    
    #endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{
		Res =USART_ReceiveData(USART1);	
		if((USART_RX_STA&0x8000)==0)
		{
			if(USART_RX_STA&0x4000)
			{
				if(Res!=0x0a)
                    USART_RX_STA=0;
				else 
                    USART_RX_STA|=0x8000;	
			}
			else 
			{	
				if(Res==0x0d)
                    USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))
                        USART_RX_STA=0;  
				}		 
			}
		}   		 
     } 
     #if SYSTEM_SUPPORT_OS                  //如果SYSTEM_SUPPORT_OS为真,则需要支持OS
	     OSIntExit();  											 
     #endif
} 
#endif	

 在USART串口协议文件usart.c里定义了三个不同的变量,第一个宏变量USART_REC_LEN是最大接收数,协议中限制了它最大是200。余下两个分别是8位无符号整型数据接收数组USART_RX_BUF[USART_REC_LEN],16位无符号整型接收状态标记USART_RX_STA。

协议里规定接收状态标记变量最高位bit15为接收完成标志,bit14是判断是否接收到回车0X0D标志。在接收数据的过程中,若单片机接收到0X0D后,会将bit14位置一,接下来进入下一次接收循环,如果下一次接收数据为0X0A,默认本段数据接收完毕,进行数据最终处理,最后程序跳出数据接收循环,并且标志位bit0~bit15置零,如果没有接收到0X0A则接收错误,接收完成标志设为0重新开始。

实验效果同上,发送前需要勾选发送新行,这样能够接收到回车,默认以回车键结束接收。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: MATLAB和STM32串口通信是指利用MATLAB软件和STM32单片机进行数据传输和通信的一种方式。串口通信是指通过串口接口上的数据线进行数据的收发和交换。 MATLAB是一种强大的科学计算软件,它具有丰富的函数库和工具箱,可以用于数据处理、信号处理、图像处理等各种科学计算任务。而STM32则是一种基于ARM Cortex-M处理器的微控制器系列,具有高性能、低功耗和丰富的外设接口,广泛应用于嵌入式系统和物联网等领域。 MATLAB和STM32串口通信一般通过串口通信协议进行数据交互。在STM32的程序中,需要配置串口的波特率、数据位、校验位和停止位等参数,以确保与MATLAB软件的通信兼容。在MATLAB中,可以利用串口通信工具箱来实现与STM32的数据传输和通信。 具体而言,MATLAB可以通过串口通信工具箱中的函数来打开串口连接,设置相关的串口参数,并发送和接收数据。STM32通过配置串口的相关寄存器和中断服务函数,实现与MATLAB的数据交互。在数据传输过程中,可以利用MATLAB的数据处理和分析功能,对接收到的数据进行各种操作和处理。 总之,MATLAB和STM32串口通信是一种常用的数据传输和通信方式,可以实现MATLAB软件和STM32单片机之间的数据共享和信息交换。通过串口通信,可以使MATLAB和STM32之间实现多种应用,如数据采集、监控控制、智能控制等。这种通信方式在科学研究、工程设计和教学实验等领域都有广泛的应用。 ### 回答2: Matlab和STM32是两种不同类型的工具,可以通过串口通信进行数据传输和交互。 Matlab是一种强大的数学计算软件,广泛应用于科学、工程和数据分析领域。Matlab提供了丰富的工具箱和函数,可以用于各种数学计算、数据处理、图像处理和控制系统设计等任务。通过Matlab,我们可以编写程序来处理数据、进行算法设计和仿真。 STM32是一款基于ARM Cortex-M内核的32位微控制器,由意法半导体(STMicroelectronics)公司生产。它具有丰富的外设和强大的计算能力,适用于各种嵌入式系统应用。STM32使用C编程语言,开发者可以编写程序控制其各种功能和外设。 串口通信是一种常见的数据传输方式,可以通过串口将数据从一个设备发送到另一个设备。在Matlab和STM32之间进行串口通信,我们可以使用Matlab的串口通信工具箱或STM32的UART(通用异步收发器)模块。 首先,我们需要在STM32上配置串口参数,如波特率、数据位数和校验位等。然后,在STM32的程序中编写代码,将要传输的数据发送到串口。同时,STM32也需要接收来自Matlab的数据,并进行处理。 在Matlab端,我们可以使用串口通信工具箱提供的函数来进行串口通信。首先,我们需要打开串口并设置与STM32相同的参数。然后,可以使用相应的函数来读取和写入串口数据。通过编写Matlab脚本,我们可以从STM32接收数据,进行数据处理和分析,并将结果发送回STM32。 通过Matlab和STM32之间的串口通信,我们可以实现数据的双向传输和实时交互。这对于开发嵌入式系统、进行实时控制和监测等应用非常有用。同时,我们可以利用Matlab强大的计算和分析能力来对数据进行处理和分析,从而实现更高级的功能。 ### 回答3: Matlab和STM32串口通信是指利用Matlab软件和STM32微控制器实现硬件设备和计算机之间的通信串口通信是一种常见的通信方式,它通过串行接口将数据以逐位的方式进行传输。 Matlab是一种高度集成的科学计算和数值分析软件,具有强大的数据处理和可视化功能。STM32是一款基于ARM Cortex-M内核的微控制器系列,具有丰富的外设资源和多种通信接口。 在Matlab中,我们可以使用Serial对象来实现串口通信。首先,我们需要创建一个Serial对象,并指定串口的端口号和波特率。然后,我们可以使用write函数向串口发送数据,使用read函数从串口接收数据。通过这种方式,我们可以实现与STM32之间的双向数据传输。 在STM32中,我们需要配置串口的相关参数。首先,我们需要设置串口通信参数,如波特率、数据位、停止位和校验位等。然后,我们可以使用串口发送和接收函数来进行数据的发送和接收。在发送数据时,我们需要将数据写入到串口数据寄存器,然后通过串口接口将数据发送出去。在接收数据时,我们可以从串口数据寄存器中读取数据,然后进行相应的处理。 通过Matlab和STM32的串口通信,我们可以实现很多应用,例如传感器数据采集、远程控制、数据监视等。这种通信方式具有简单、可靠、实时性好等特点,适用于各种嵌入式系统和数据分析应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值