为您推荐:
精华内容
最热下载
问答
  • 17.43MB u014393685 2021-06-16 15:16:57
  • 4星
    2.81MB zuoshaobi 2013-12-16 21:37:05
  • 第五章usart串口通信 USART:(UniversalSynchronous/Asynchronous Receiver/Transmitter)通用同步/异步串行接收/发送器 USART是一个全双工通用同步/异步串行收发模块,该接口是一个高度灵活的串行通信设备,串口通信...

    第五章usart串口通信

    USART:(UniversalSynchronous/Asynchronous Receiver/Transmitter)通用同步/异步串行接收/发送器
    USART是一个全双工通用同步/异步串行收发模块,该接口是一个高度灵活的串行通信设备,串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。
    串口分为公头和母头(有九针串口和二十五针串口)
    在这里插入图片描述

    其中接收数据,发送数据,信号地三个最为重要。
    数据速率用波特率表示:1200 2400 4800 9600 19200 115200等
    波特率越低传输距离越远


    USART由收发数据和收发控制两部分组成

    USART的引脚
    USART1在APB2总线上TX :PA9 RX:PA10
    USART2的TX :PA2 RX:PA3
    USART3的TX :PB10 RX:PB11
    USART4的TX :PC10 RX:PC11
    USART5的TX :PC12 RX:PD2

    HAL库函数对每个外设都建立了一个初始化结构体,比如 UART_InitTypeDef,结构体成员用于设置外设工作参数,并由外设初始化配置函数。
    *HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef huart)调用,这些设定参数将会设置外设相应的寄存器,达到配置外设工作环境的目的。
    HAL库函数一般会在某些头文件中,并不需要进行输入,仅需要调用即可,用户只需要输入自己的 控制代码,函数即可。
    在设置USART1时
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    fputc()函数
    在这里插入图片描述

    int fputc ( int ch, FILE *fp )
    
    

    ch 为要写入的字符,fp 为文件指针。fputc() 写入成功时返回写入的字符,失败时返回 EOF,返回值类型为 int 也是为了容纳这个负数。

    fputc('a', fp);
    

    strstr函数
    strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。
    在这里插入图片描述

    这句话的意思是LED1是收到低电平0没有返回NULL那么LED1处于熄灭状态。

    展开全文
    m0_56784737 2021-11-13 10:43:44
  • UART即通用异步收发器,它是在USART基础上裁剪掉了同步通信功能,同 步和异步主要看其时钟是否需要对外提供,这个前面也介绍了。我们开 发板上使用的STM32F103ZET6芯片含有3个USART,2个UART外设

    声明:所有资源均来自于普中STM32F103开发板相关资料,这是自己购买的一款开发板,如果原作者认为侵权,请联系我以便及时处理。

    STM32F1的USART介绍

    USART即通用同步异步收发器,它能够灵活地与外部设备进行全双工
    数据交换,满足外部设备对工业标准 NRZ 异步串行数据格式的要求。
    UART即通用异步收发器,它是在USART基础上裁剪掉了同步通信功能,同
    步和异步主要看其时钟是否需要对外提供,这个前面也介绍了。我们开
    发板上使用的STM32F103ZET6芯片含有3个USART,2个UART外设。它们都
    具有串口通信功能,USART它支持同步单向通信和半双工单线通信;还支
    持 LIN(域互连网络)、智能卡协议与 IrDA(红外线数据协会) SIR
    ENDEC 规范,以及调制解调器操作 (CTS/RTS)。而且,它还支持多处理
    器通信和DMA功能,使用 DMA 可实现高速数据通信。USART 通过小数波
    特率发生器提供了多种波特率。
    USART在STM32中应用最多的是printf输出调试信息,当我们需要了解
    程序内的一些变量数据信息时,可以通过printf输出函数将这些信息打
    印到串口助手上显示,这样一来就给我们调试程序带来了极大的方便。

    在这里插入图片描述

    串口通信配置步骤

    USART相关库函数在stm32f10x_usart.c和stm32f10x_usart.h文件中
    (1)使能串口时钟及GPIO端口时钟
    		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA时钟
    		RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟 2)GPIO端口模式设置,设置串口对应的引脚为复用功能                                
    		GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
    		GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;3)初始化串口参数,包含波特率、字长、奇偶校验等参数                                
    		void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
    		typedef struct
    		{
    		  uint32_t USART_BaudRate;            //波特率
    		  uint16_t USART_WordLength;          //字长
    		  uint16_t USART_StopBits;            //停止位
    		  uint16_t USART_Parity;              //校验位
    		  uint16_t USART_Mode;                //USART模式
    		  uint16_t USART_HardwareFlowControl; //硬件流控制
    		} USART_InitTypeDef;4)使能串口
    		void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
    		USART_Cmd(USART1, ENABLE);  //使能串口15)设置串口中断类型并使能                                
    		void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
    
    		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启接收中断
    
    		USART_ITConfig(USART1,USART_IT_TC, ENABLE);
    
    		对应的串口中断类型可在stm32f10x_usart.h中查找到
    
    (6)设置串口中断优先级,使能串口中断通道
    		NVIC初始化库函数是NVIC_Init()7)编写串口中断服务函数                               
    	USART1_IRQHandler
    
    	ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
    	
    	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    	{
    		...//执行USART1接收中断内控制
    	}
    	void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
    第二个参数为状态标志选项,可选参数可在stm32f10x_usart.h中查找到
    

    eg:

    	USART_InitTypeDef USART_InitStructure;
    	USART_InitStructure.USART_BaudRate = 9600;//波特率设置
    	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    	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); //初始化串口1
    
    void USART1_IRQHandler(void)                	//串口1中断服务程序
    {
    	u8 r;
    	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
    	{
    		r =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
    		USART_SendData(USART1,r);
    		while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
    	} 
    	USART_ClearFlag(USART1,USART_FLAG_TC);
    }
    

    硬件电路

    在这里插入图片描述

    编写串口通信控制程序

    STM32F1通过USART1实现与PC机通信,STM32F1的USART1收到PC机发来的数据后原封不动的返回给PC机显示。同时使用D1指示灯不断闪烁提示系统正常运行。

    程序框架如下:

    (1)初始化USART1,并使能串口接收中断等
    (2)编写USART1中断函数
    (3)编写主函数

    uart.h

    #ifndef __usart_H
    #define __usart_H
    
    #include "system.h" 
    
    void USART1_Init(u32 baud);
    
    #endif
    
    
    

    uart.c

    #include "usart.h"		 
    
    /*******************************************************************************
    * 函 数 名         : USART1_Init
    * 函数功能		     : USART1初始化函数
    * 输    入         : bound:波特率
    * 输    出         : 无
    *******************************************************************************/ 
    void USART1_Init(u32 baud)
    {
       //GPIO端口设置
    	GPIO_InitTypeDef GPIO_InitStructure;
    	USART_InitTypeDef USART_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
     
    	
    	/*  配置GPIO的模式和IO口 */
    	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX			   //串口输出PA9
    	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;	    //复用推挽输出
    	GPIO_Init(GPIOA,&GPIO_InitStructure);  /* 初始化串口输出IO */
    	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX			 //串口输入PA10
    	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;		  //浮空输入
    	GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化串口输入IO */
    	
       //USART1 初始化设置
    	USART_InitStructure.USART_BaudRate = baud;//波特率设置
    	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    	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); //初始化串口1
    	
    	USART_Cmd(USART1, ENABLE);  //使能串口1 
    	
    	USART_ClearFlag(USART1, USART_FLAG_TC);
    		
    	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
    
    	//Usart1 NVIC 配置
    	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、	
    }
    
    /*******************************************************************************
    * 函 数 名         : USART1_IRQHandler
    * 函数功能		     : USART1中断函数
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/ 
    void USART1_IRQHandler(void)                	//串口1中断服务程序
    {
    	u8 r;
    	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
    	{
    		r =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
    		USART_SendData(USART1,r);
    		while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
    	} 
    	USART_ClearFlag(USART1,USART_FLAG_TC);
    	
    } 	
    
    

    main.c

    #include "system.h"
    #include "SysTick.h"
    #include "led.h"
    #include "usart.h"
    
    int main()
    {
    	u8 i=0;  
    	SysTick_Init(72);
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组
    	LED_Init();
    	USART1_Init(115200);
    	
    	while(1)
    	{
    		i++;
    		if(i%20==0)
    		{
    			led1=!led1;
    		}
    		delay_ms(10);
    	}
    }
    
    

    测试结果

    在这里插入图片描述

    展开全文
    zxy131072 2020-12-02 14:37:18
  • 二、 学习和阅读“零死角玩转STM32F103--指南者”文档中的第20、21章内容,完成STM32的USART串口通讯程序三、重温C语言程序里全局变量、局部变量、堆、栈等概念,并在ubuntu系统中编程,输出信息进行验证;...

    一、寄存器与固件库

    基于寄存器与基于固件库的stm32 LED流水灯例子的编程方式差异比较:

    1、基于寄存器方式的开发特点

    (1)具体参数更直观
    (2)程序运行占用资源少
    (3)寄存器更贴近底层,对外设的工作原理和运行机理会有更深的理解
    (4)寄存器版式直接对内部寄存器进行操作,需要我们对寄存器非常熟悉

    它的缺陷也不可忽视,如下:
    (1)开发速度慢
    (2)程序可读性差
    (3) 维护复杂
    上述缺陷直接影响了开发效率,程序维护成本,交流成本。通常情况下,只有在频繁调用的中断服务函数时利用直接配置寄存器的方式

    2、基于固态库方式的开发特点

    基于固态库方式开发,也就是直接调用库函数,特点是:
    (1)外设交流方便
    (2)查错简单,易于理解,资料多
    (3)对主控制器STM32上手简单
    (4) 库函数–是用ST提供的库函数开发,有函数的集合,不需要与寄存器直接打教导,提供用户函数调用的API

    二、 STM32的USART串口通讯程序

    串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通讯方式输出调试信息。

    STM32 的 USART 简介

    1、通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter)是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。有别于 USART 还有一个UART(Universal Asynchronous Receiver and Transmitter),它是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是 UART。

    2、串行通信一般是以帧格式传输数据,即是一帧一帧的传输,每帧包含有起始信号、数据信息、停止信息,可能还有校验信息。USART 就是对这些传输参数有具体规定,当然也不是只有唯一一个参数值,很多参数值都可以自定义设置,只是增强它的兼容性。

    3、USART 在 STM32 应用最多莫过于 “打印”程序信息,一般在硬件设计时都会预留一个USART通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端的串口调试助手工具上,从而了解程序运行是否正确、如果出错哪具体哪里出错等等。

    4、USART接发通信过程:
    发送数据过程:数据先从PWDATA总线写入到发送数据寄存器(TDR),然后将数据一位一位的移到发送移位寄存器中,接着通过TX引脚发送出去。
    接收数据过程:数据从RX引脚发到接收移位寄存器,接着将数据放到接收数据寄存器(ADR)中,最后CPU或者DMA进行读操作。

    1、实验要求

    (1)设置波特率为115200,1位停止位,无校验位。

    (2)STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。

    (3)当上位机给stm32发送“stop,stm32”后,stm32停止发送。

    参考:
    STM32串口通信USART学习笔记

    2、实验环境

    1、开发板:野火指南者(STM32F103)

    2、代码编写工具:KEIL5

    3、STM32库版本:STM32F10x_StdPeriph_Lib_V3.5.0

    5、使用到的串口:USART1

    6、硬件原理图:
    在这里插入图片描述

    3、实验准备

    (1)因为本实验用到的开发板是野火指南者(STM32F103),因此首先在野火产品资料链接:https://ebf-products.readthedocs.io/zh_CN/latest/中下载好野火STM32F103指南者开发板的相关资料。
    在这里插入图片描述也可直接从以下链接中提取
    链接:https://pan.baidu.com/s/13bnrB-S8Y6JDRdXBbzzbjA#list/path=%2F
    提取码:pmf1

    (2)从下载好的资料中找到实验所需的相关软件并进行安装,keil5(版本最好在5.2及以上,由于有注册机,请关闭防火墙进行下载及安装)、USB串口驱动CH340以及野火串口调试助手等。
    在这里插入图片描述
    野火串口调试助手:
    在这里插入图片描述

    4、实验代码

    此处的代码在野火的代码模板上改动。
    (1)打开之前下好的资料
    在这里插入图片描述找到 USART串口通信 中的 USART1接发 并打开
    在这里插入图片描述在这里插入图片描述打开Project中的keil工程文件
    在这里插入图片描述

    (2)对其中stm32f10x_it.c文件的串口中断服务函数部分进行修改
    在这里插入图片描述

    改为如下代码:

    int i=0;
    uint8_t ucTemp[50];
    void DEBUG_USART_IRQHandler(void)
    {
    	if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
    	{
    		ucTemp[i] = USART_ReceiveData(USART1);	
    	}
      if(ucTemp[i] == '!')
    	{
    		if(ucTemp[i-1] == '2'&&ucTemp[i-2] == '3'&&ucTemp[i-3] == 'm'&&ucTemp[i-4] == 't'&&ucTemp[i-5] == 's'&&ucTemp[i-6] == ' ')
    			if(ucTemp[i-7] == 'p'&&ucTemp[i-8] == 'o'&&ucTemp[i-9] == 't'&&ucTemp[i-10] == 's')
    			{
    				printf("收 到!");
            while(1);
    			}
    	}
    	i++;
    }
    

    (3)再把main.c函数改为如下:

    #include "stm32f10x.h"
    #include "bsp_usart.h"
    
    
    void delay(uint32_t count)
    {
    	while(count--);
    }
    int main(void)
    {	
      USART_Config();
      while(1)
    	{	
    		printf("hello windows!\n");
    		delay(5000000);
    	}	
    }
    

    在这里插入图片描述

    (4)然后就可以编译生成hex文件。
    编译成功,没有错误:
    在这里插入图片描述生成.hex文件:
    在这里插入图片描述
    在这里插入图片描述

    5、程序烧录

    (1)用usb线把电脑和stm32开发板相连接,stm32端连接的 ‘usb转串口’这个接口,再打开stm32开关,可以看到红色的小灯亮起。
    在这里插入图片描述
    开发板上有黄色的跳帽,是相当于导线的作用,此处要求BOOT0和BOOT1接地,RXD接A9,TXD接A10,开发板买来默认就是这样接的,所以不需要改动。

    (2)打开串口调试助手,发现没有端口
    在这里插入图片描述
    此时就要安装驱动:打开资料中的USB串口驱动CH340并安装,显示安装成功即可。
    在这里插入图片描述
    注:驱动只有在电脑和开发板相连接的情况下才会显示安装成功。

    (3)然后打开串口下载助手mcuisp
    在这里插入图片描述并进行如下步骤的设置:
    ①搜索串口,设置波特率 115200
    ②选择要下载的 HEX 文件
    ③勾选校验、编程后执行
    ④DTR 低电平复位,RTS 高电平进入 bootloader
    ⑤开始编程。
    (前4步一定要调试正确,否则可能连接不上)
    在这里插入图片描述按照上面的方式就可以把hex文件烧录到stm32中了。

    6、实验结果

    打开串口调试助手,点击打开串口,即可以看到stm32发给电脑的信息。当上位机给stm32发送“Stop,stm32”后,stm32停止发送。
    在这里插入图片描述

    三、总结

    在电脑将程序烧录进开发板后,开发版的屏幕会熄掉,因为此时开发板在运行我们烧录进去的程序,而不是运行屏幕的程序。电脑在向stm32发送数据的时候,需要回车,数据才能够被正常接收,否则点击发送,不会有相应的反应。

    展开全文
    weixin_51087836 2020-12-03 15:50:43
  • 3KB aniywn 2019-08-14 09:34:16
  • USART 串口通信实验 我们知道STM32F1 内部含有非常多的通信接口,我们就来学习下USART 串口通信。要实现的功能是:STM32F1 通过USART1 实现与PC 机对话,STM32F1 的USART1 收到PC 机发来的数据后原封不动的返回给PC ...

    USART 串口通信实验

    我们知道STM32F1 内部含有非常多的通信接口,我们就来学习下USART 串口通信。要实现的功能是:STM32F1 通过USART1 实现与PC 机对话,STM32F1 的USART1 收到PC 机发来的数据后原封不动的返回给PC 机显示。分为如下几部分内容:

    1. 通信的基本概念
    2. STM32F4 的USART 介绍
    3. USART 串口通信配置步骤
    4. 硬件设计
    5. 软件设计

    1 . 通信的基本概念

    我们知道STM32F1 芯片内含有非常多的通信接口,学习这些通信接口前,我们很有必要了解下通信的基本概念。通信的方式可以分为多种:

    • 按照数据传送方式可分为串行通信和并行通信
    • 按照通信的数据同步方式,可分为异同通信和同步通信
    • 按照数据的传输方向又可分为单工、半双工和全双工通信
      下面我们就来简单介绍这几种通信方式:

    串行通信与并行通信
    (1)串行通信
    串行通信是指使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个固定的时间长度。其只需要少数几条线就可以在系统间交换信息,特别适用于计算机与计算机、计算机与外设之间的远距离通信。如图所示:
    在这里插入图片描述
    串行通信的特点:传输线少,长距离传送时成本低,且可以利用电话网等现成的设备,但数据的传送控制比并行通信复杂。

    (2)并行通信
    并行通信通常是将数据字节的各位用多条数据线同时进行传送,通常是8位、16 位、32 位等数据一起传输。如图所示:
    在这里插入图片描述
    并行通信的特点:控制简单、传输速度快;由于传输线较多,长距离传送时成本高且接收方的各位同时接收存在困难,抗干扰能力差。

    异步通信与同步通信
    (1)异步通信
    异步通信是指通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程。为使双方的收发协调,要求发送和接收设备的时钟尽可能一致。异步通信是以字符(构成的帧)为单位进行传输,字符与字符之间的间隙(时间间隔)是任意的,但每个字符中的各位是以固定的时间传送的,即字符之间不一定有“位间隔”的整数倍的关系,但同一字符内的各位之间的距离均为“位间隔”的整数倍。异步通信数据格式如图所示:
    在这里插入图片描述
    在这里插入图片描述

    异步通信的特点:不要求收发双方时钟的严格一致,实现容易,设备开销较小,但每个字符要附加2~3 位用于起止位,各帧之间还有间隔,因此传输效率不高。

    (2)同步通信
    同步通信时要建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。此时,传输数据的位之间的距离均为“位间隔”的整数倍,同时传送的字符间不留间隙,即保持位同步关系,也保持字符同步关系。发送方对接收方的同步可以通过两种方法实现。同步通信数据格式如图所示:
    在这里插入图片描述
    单工、半双工与全双工通信
    (1)单工通信
    单工是指数据传输仅能沿一个方向,不能实现反向传输。如下图所示:
    在这里插入图片描述

    (2)半双工通信
    半双工是指数据传输可以沿两个方向,但需要分时进行。如下图所示:
    在这里插入图片描述

    (3)全双工通信
    全双工是指数据可以同时进行双向传输。如下图所示:
    在这里插入图片描述

    通信速率
    衡量通信性能的一个非常重要的参数就是通信速率,通常以**比特率(Bitrate)**来表示。比特率是每秒钟传输二进制代码的位数,单位是:位/秒(bps)。如每秒钟传送240 个字符,而每个字符格式包含10 位(1 个起始位、1 个停止位、8个数据位),这时的比特率为:
    10 位×240 个/秒= 2400 bps
    在后面会遇到一个“波特率”的概念,它表示每秒钟传输了多少个码元。而码元是通信信号调制的概念,通信中常用时间间隔相同的符号来表示一个二进制数字,这样的信号称为码元。如常见的通信传输中,用0V 表示数字0, 5V 表示数字1,那么一个码元可以表示两种状态0 和1,所以一个码元等于一个二进制比特位,此时波特率的大小与比特率一致;如果在通信传输中,有0V、2V、
    4V 以及6V 分别表示二进制数00、01、10、11,那么每个码元可以表示四种状态,即两个二进制比特位,所以码元数是二进制比特位数的一半,这个时候的波特率为比特率的一半。由于很多常见的通信中一个码元都是表示两种状态,所以我们常常直接以波特率来表示比特率。

    STM32F1 的USART 介绍

    串口通信简介
    串口通信(Serial Communication),是指外设和计算机间通过数据信号线、地线等按位进行传输数据的一种通信方式,属于串行通信方式。串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的协议。
    (1)接口标准
    串口通信的接口标准有很多,有RS-232C、RS-232、RS-422A、RS-485 等。常用的就是RS-232 和RS-485。RS-232 其实是RS-232C 的改进,原理是一样的。这里我们就以RS-232C 接口进行讲解。RS-232C 是EIA(美国电子工业协会)1969 年修订RS-232C 标准。RS-232C定义了数据终端设备(DTE)与数据通信设备(DCE)之间的物理接口标准。RS-232C 接口规定使用25 针连接器,简称DB25,连接器的尺寸及每个插针的排列位置都有明确的定义,如图所示:
    在这里插入图片描述
    RS-232C 还有一种9 针的非标准连接器接口,简称DB9。串口通信使用的大多都是DB9 接口。DB25 和DB9 接头有公头和母头之分,其中带针状的接头是公头,而带孔状的接头是母头。9 针串口线的外观图如图所示:
    在这里插入图片描述
    中可以看到公头和母头的管脚定义顺序是不一样,这一点需要特别注意。这些管脚都有什么作用呢?9 针串口和25 针串口常用管脚的功能说明如图所示:
    在这里插入图片描述
    在串口通信中,通常我们只使用2、3、5 三个管脚,即TXD、RXD、SGND,其他管脚功能大家看不明白也没关系。RS-232C 对逻辑电平也做了规定

    在TXD 和RXD 数据线上:
    1.逻辑1 为-3~-15V 的电压
    2.逻辑0 为3~15V 的电压
    在RTS、CTS、DSR、DTR 和DCD 等控制线上:
    1.信号有效(ON 状态)为3~15V 的电压
    2.信号无效(OFF 状态)为-3~-15V 的电压

    由此可见,RS-232C 是用正负电压来表示逻辑状态与晶体管-晶体管逻辑集成电路(TTL)以高低电平表示逻辑状态的规定正好相反而我们STM32 芯片使用的就是TTL 电平,所以要实现STM32 与计算机的串口通信,需要进行TTL与RS-232C电平转换,通常使用的电平转换芯片是MAX3232。在串口通信中通常PC机的DB9 为公头,单片机上使用的串口DB9 为母头,通过一根直通串口线进行相连。串口线(COM)母头连接计算机DB9 的公头,串口线公头连接单片机上使用的DB9 母头,这样就是将2、3、5 管脚直接相连。如果你要实现两台计算机串口通信,那么就需要一根交叉串口线,将2 对3、3 对2、5 对5 连接,交叉串口线一般两头都是母头。串口通信中还需要注意的是,串口数据收发线要交叉连接,计算机的TXD要对应单片机的RXD,计算机的RXD 要对应单片机的TXD,并且共GND,如下图:有的朋友就会问了,在计算机与单片机进行串口通信时,使用的不是直通线吗,这时候怎么让TXD 与RXD 交叉连接?前面我们说了单片机处理的是TTL 电平,需要使用RS232 电平转换芯片,将RS232 电平转换芯片串行数据输出管脚交叉连接在DB9 母头上即可。

    (2)通信协议
    RS232 的通信协议比较简单,通常遵循96-N-8-1 格式。“96”表示的是通信波特率为9600。串口通信中通常使用的是异步串口通信,即没有时钟线,所以两个设备要通信,必须要保持一致的波特率,当然,波特率常用值还有4800、115200 等。“N”表示的是无校验位,由于串口通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、0 校验(space)、1 校验(mark)以及无校验(noparity)。“8”表示的是数据位数为8 位,其数据格式在前面介绍异步通信中已讲过。当然数据位数还可以为5、6、7 位长度。“1”表示的是1 位停止位,串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一个逻辑0 的数据位表示,而数据包的停止信号可由 0.5、1、1.5 或 2 个逻辑1 的数据位表示,只要双方约定一致即可。了解了串口通信的标准,我们就来看下STM32F1 芯片的串口USART。

    USART 简介
    USART 即通用同步异步收发器,它能够灵活地与外部设备进行全双工数据交换,满足外部设备对工业标准 NRZ 异步串行数据格式的要求。UART 即通用异步收发器,它是在USART 基础上裁剪掉了同步通信功能,同步和异步主要看其时钟是否需要对外提供,这个前面也介绍了, 我们平时使用的串口通信基本上都是UART。STM32F103ZET6 芯片含有3 个USART,2 个UART 外设,它们都具有串口通信功能。USART 支持同步单向通信和半双工单线通信;还支持LIN(域互连网络)、智能卡协议与IrDA(红外线数据协会) SIR ENDEC 规范,以及调制解调器操作(CTS/RTS)。而且,它还支持多处理器通信和DMA 功能,使用DMA 可实现高速数据通信。USART 通过小数波特率发生器提供了多种波特率。USART 在STM32 中应用最多的是printf 输出调试信息,当我们需要了解程序内的一些变量数据信息时,可以通过printf 输出函数将这些信息打印到串口助手上显示,这样一来就给我们调试程序带来了极大的方便。

    USART 结构框图
    其实USART 能够有这么多功能,取决于它的内部结构。其内部结构框图如图:

    在这里插入图片描述
    我们把图21.2.4 分为几个模块进行介绍:
    (1)标号1:功能引脚

    • TX:发送数据输出引脚。
    • RX:接收数据输入引脚。
    • SW_RX:数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚
    • nRTS:请求以发送(Request To Send),n 表示低电平有效。如果使能RTS 流控制,当USART接收器准备好接收新数据时就会将nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。
    • nCTS:清除以发送(Clear To Send),n 表示低电平有效。如果使能CTS 流控制,发送器在发送下一帧数据之前会检测nCTS引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。
    • SCLK:发送器时钟输出引脚。这个引脚仅适用于同步模式。前面我们说了,STM32F103ZET6 芯片具有5个串口外设,其对应的管脚可在芯片数据手册上查找到,也可以直接查看我们开发板原理图,我们已经将芯片所有的IO口功能都标注在管脚上了。
      USART1 挂接在APB2 总线上,其他的挂接在APB1 总线,由于UART4 和UART5只有异步传输功能,所以没有SCLK、nCTS 和nRTS脚,如下:
      在这里插入图片描述
      (2)标号2:数据寄存器
      USART 数据寄存器(USART_DR)只有低9 位有效,并且第9 位数据是否有效要取决于USART 控制寄存器1(USART_CR1)的M 位设置,当M 位为0 时表示8 位数据字长,当M 位为1 表示9 位数据字长,我们一般使用8 位数据字长。USART_DR 包含了已发送的数据或者接收到的数据。USART_DR 实际是包含了两个寄存器,一个专门用于发送的可写TDR,一个专门用于接收的可读RDR。当进行发送操作时,往USART_DR 写入数据会自动存储在TDR 内;当进行读取操作时,向USART_DR 读取数据会自动提取RDR 数据。TDR 和RDR 都是介于系统总线和移位寄存器之间。串行通信是一个位一个位传输的,发送时把TDR 内容转移到发送移位寄存器,然后把移位寄存器数据每一位发送出去,接收时把接收到的每一位顺序保存在接收移位寄存器内然后才转移到RDR。USART 支持DMA 传输,可以实现高速数据传输,具体DMA 使用在后面会更新介绍。
      (3)标号3:控制器
      USART 有专门控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等等。使用USART 之前需要向USART_CR1 寄存器的UE 位置1 使能USART。发送或者接收数据字长可选8 位或9 位,由USART_CR1 的M 位控制。
      1.发送器
      发送器可发送8 位或9 位的数据,具体取决于M 位的状态。发送使能位(TE) 置1 时,发送移位寄存器中的数据在TX 引脚输出,如果是同步通信模式,相应的时钟脉冲在SCLK 引脚输出。
      2.接收器
      如果将USART_CR1 寄存器的RE 位置1,使能USART 接收,使得接收器在RX 线开始搜索起始位。在确定到起始位后就根据RX 线电平状态把数据存放在接收移位寄存器内。接收完成后就把接收移位寄存器数据移到RDR 内,并把USART_SR 寄存器RXNE 位置1,同时如果USART_CR2 寄存器的RXNEIE 置1的话可以产生中断。
      3.中断控制
      USART 有多个中断请求事件,如下:
      在这里插入图片描述
      USART 中断事件被连接到相同的中断向量,如下:
      在这里插入图片描述
      (4)标号4:小数波特率生成
      波特率的概念在前面介绍比特率的时候已经提过,常用的串口通信中都把波特率当作比特率。波特率越大,传输速度就越快。接收器和发送器( Rx 和Tx)的波特率均设置为相同值。波特率计算公式如下:
      在这里插入图片描述
      其中,fCK 为USART 时钟频率,USARTDIV 是一个存放在波特率寄存器(USART_BRR)的一个无符号定点数。其中DIV_Mantissa[11:0]位定义USARTDIV的整数部分,DIV_Fraction[3:0]位定义USARTDIV 的小数部分。串口通信中常用的波特率为4800、9600、115200 等。

    USART 串口通信配置步骤

    在上面的介绍中,可能有的朋友很不理解,不过没有关系,下面我们讲解如何使用库函数对USART 进行配置。这个也是在编写程序中必须要了解的。具体步骤如下:(USART 相关库函数在stm32f10x_usart.c 和stm32f10x_usart.h 文件中)

    (1)使能串口时钟及GPIO 端口时钟

    前面说过STM32F103ZET6 芯片具有5 个串口,对应不同的引脚,串口1 挂接在APB2 总线上,串口2-串口5 挂接在APB1 总线上,根据自己所用串口使能总线时钟和端口时钟。例如使用USART1,其挂接在APB2 总线上,并且USART1 对应STM32F103ZET6 芯片管脚的PA9 和PA10,因此使能时钟函数如下:

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);// 使能USART1 时钟
    

    (2)GPIO 端口模式设置,设置串口对应的引脚为复用功能

    因为使用引脚的串口功能,所以在配置GPIO 时要将设置为复用功能,这里把串口的Tx 引脚配置为复用推挽输出, Rx 引脚为浮空输入,数据完全由外部输入决定。如下:

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX //串口输出PA9
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化串口输入IO */
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX // 串口输入PA10
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; // 模拟输入
    GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */
    

    (3)初始化串口参数,包含波特率、字长、奇偶校验等参数要使用串口功能,必须对串口通信相关参数初始化,其库函数如下:

    void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef*USART_InitStruct);
    

    想必不用说,大家也知道第一个参数是什么意思,它是用来选择串口。第二个参数是一个结构体指针变量,结构体类型是 USART_InitTypeDef,其内包含了串口初始化的成员变量。下面我们就来看下这个结构体:

    typedef struct
    {
    uint32_t USART_BaudRate; //波特率
    uint16_t USART_WordLength; //字长
    uint16_t USART_StopBits; //停止位
    uint16_t USART_Parity; //校验位
    uint16_t USART_Mode; //USART 模式
    uint16_t USART_HardwareFlowControl; //硬件流控制
    } USART_InitTypeDef;
    

    下面就来简单介绍下每个成员变量的功能:
    USART_BaudRate: 波特率设置。常用的波特率为4800、9600、115200 。标准库函数会根据设定值计算得到USARTDIV 值, 并设置USART_BRR寄存器值。
    USART_WordLength: 数据帧字长。可以选择为8 位或者9 位,通过USART_CR1寄存器的M 位的值决定。如果没有使能奇偶校验控制,一般使用8 数据位;如果使能了奇偶校验则一般设置为9 数据位。
    USART_StopBits: 停止位设置。可选0.5 个、1 个、1.5 个和2 个停止位,它设定USART_CR2 寄存器的STOP[1:0]位的值,一般我们选择1 个停止位。
    USART_Parity: 奇偶校验控制选择。可选USART_Parity_No( 无校验) 、USART_Parity_Even( 偶校验) 以及USART_Parity_Odd( 奇校验) ,它设定USART_CR1 寄存器的PCE 位和PS 位的值。
    USART_Mode: USART 模式选择。可以为USART_Mode_Rx 和USART_Mode_Tx,允许使用逻辑或运算选择两个,它设定USART_CR1 寄存器的RE 位和TE 位。**USART_HardwareFlowControl:**硬件流控制选择。只有在硬件流控制模式才有效, 可以选择无硬件流USART_HardwareFlowControl_None 、RTS 控制USART_HardwareFlowControl_RTS、CTS 控制USART_HardwareFlowControl_CTS、RTS 和CTS 控制USART_HardwareFlowControl_RTS_CTS。

    了解结构体成员功能后,就可以进行配置,例如我们配置USART1,如下:

    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 9600;//波特率设置
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8 位数据格式
    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); //初始化串口1
    

    (5)使能串口

    配置好串口后,我们还需要使能它,使能串口库函数如下:

    void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
    

    例如我们要使能USART1,如下:

    USART_Cmd(USART1, ENABLE); //使能串口1
    

    (6)设置串口中断类型并使能

    对串口中断类型和使能设置的函数如下:

    void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT,FunctionalState NewState);
    

    第一个参数用来选择串口,第二个参数用来选择串口中断类型,第三个参数用来使能或者失能对应中断。由于串口中断类型比较多,所以使用哪种中断,我们就需要对它进行配置。比如在接收到数据的时候( RXNE 读数据寄存器非空),我们要产生中断,那么我们开启中断的方法是:

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启接收中断
    

    又比如我们发送完数据时,要产生中断,可以配置如下:

    USART_ITConfig(USART1,USART_IT_TC, ENABLE);
    

    对应的串口中断类型可在stm32f10x_usart.h 中查找到,如下:

    #define USART_IT_PE	 	((uint16_t)0x0028)
    #define USART_IT_TXE	 	((uint16_t)0x0727)
    #define USART_IT_TC		 ((uint16_t)0x0626)
    #define USART_IT_RXNE	 ((uint16_t)0x0525)
    #define USART_IT_IDLE	 ((uint16_t)0x0424)
    #define USART_IT_LBD 	((uint16_t)0x0846)
    #define USART_IT_CTS 	((uint16_t)0x096A)
    #define USART_IT_ERR	 ((uint16_t)0x0060)
    #define USART_IT_ORE	 ((uint16_t)0x0360)
    #define USART_IT_NE		 ((uint16_t)0x0260)
    #define USART_IT_FE		 ((uint16_t)0x0160)
    

    (7)设置串口中断优先级,使能串口中断通道

    在上一步我们已经使能了串口的接收中断,只要使用到中断,就必需对NVIC初始化,NVIC 初始化库函数是NVIC_Init(),这个在前面讲解STM32 中断时就已经介绍过,不清楚的可以回过头看下。

    (8)编写串口中断服务函数

    最后我们还需要编写一个串口中断服务函数,通过中断函数处理串口产生的相关中断。串口中断服务函数名在STM32F1 启动文件内就有,USART1 中断函数名如下:

    USART1_IRQHandler
    

    因为串口的中断类型有很多,所以进入中断后,我们需要在中断服务函数开头处通过状态寄存器的值判断此次中断是哪种类型,然后做出相应的控制。库函数中用来读取串口中断状态标志位的函数如下:

    ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_tUSART_IT);
    

    此函数功能是判断USARTx 的中断类型USART_IT 是否产生中断,例如我们要判断USART1 的接收中断是否产生,可以调用此函数:

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
    ...//执行USART1 接收中断内控制
    }
    

    如果产生接收中断,那么调用USART_GetITStatus 函数后返回值为1,就会进入到if 函数内执行中断控制功能程序。否则就不会进入中断处理程序。在编写串口中断服务函数时,最后通常会调用一个清除中断标志位的函数,如下:

    void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
    

    第二个参数为状态标志选项,可选参数可在stm32f10x_usart.h 中查找到,如下:

    #define USART_FLAG_CTS
    #define USART_FLAG_LBD
    #define USART_FLAG_TXE
    #define USART_FLAG_TC
    #define USART_FLAG_RXNE
    #define USART_FLAG_IDLE
    #define USART_FLAG_ORE
    #define USART_FLAG_NE
    #define USART_FLAG_FE
    #define USART_FLAG_PE
    

    比如本实验中判断串口进入接收中断后,我们就会把串口接收寄存器内数据读取出来,然后再通过串口发送至上位机,等待发送完成后我们就会清除发送完成标志位
    USART_FLAG_TC。代码如下:

    void USART1_IRQHandler(void) //串口1 中断服务程序
    {
    	u8 r;
    	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
    		{
    		r =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
    		USART_SendData(USART1,r);
    		while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
    		}
    	USART_ClearFlag(USART1,USART_FLAG_TC);
    }
    

    串口接收函数是:

    uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
    

    串口发送函数是:

    void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
    

    库函数中还有一个函数用来读取串口状态标志位:

    FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_tUSART_FLAG);
    

    USART_GetITStatus 与USART_GetFlagStatus 功能类似, 区别就是USART_GetITStatus 函数会先判断是否使能串口中断,使能后才读取状态标志,而USART_GetFlagStatus 函数直接读取状态标志。将以上几步全部配置好后,我们就可以正常使用串口中断了。

    硬件设计

    在开发板上,含有一个USB 转串口,一个RS232 串口,其硬件电路如图所示:

    在这里插入图片描述
    在这里插入图片描述

    PZ6806L 开发板串口3 电路:
    在这里插入图片描述
    从图中可以看出,通过CH340 芯片把STM32F1 的串口1 与 PC 机的USB 口进行连接,实现串口通信。根据前面介绍,串口通信需将数据收发管脚交叉连接,所以可以看到在CH340 芯片的2 和3 脚已做处理。电路中其他部分是自动下载电路部分,目的是控制BOOT 的启动模式与复位。
    STM32F1 使用的是串口3,即PB9 和PB10 管脚。此电路是按照RS232 接口标准搭建,使用了一个DB9 的母头,电平转换芯片使用的是SP3232,与MAX3232 一样。母头可作为下位机和上位机PC 进行串口通信,需使用交叉型串口线。电路中还有一个P232 插针,它是用来选择是USART3 功能还是IIC2 功能,如果我们需要使用这个DB9 做串口通信,需将P232 插针的3、5 短接,4、6 短接,如果做EEPROM 实验时需将P232 插针的1、3 短接,2、4 短接,开发板出厂时P232 插针默认选择的是IIC2 功能。

    本章实验所采用的是串口1 与PC 机USB 口进行通信,只需使用一根USB 线连接电脑USB 口即可实现串口通信。若大家需要使用DB9 接口,可以选择图2 电路,此时使用的是串口3,程序和串口1 通信是类似的,只需修改串口号即可。

    软件设计

    所要实现的功能是:STM32F1 通过USART1 实现与PC 机对话,STM32F1的USART1 收到PC 机发来的数据后原封不动的返回给PC 机显示。同时使用D1指示灯不断闪烁提示系统正常运行。程序框架如下:
    (1)初始化USART1,并使能串口接收中断等
    (2)编写USART1 中断函数
    (3)编写主函数
    在前面介绍串口配置步骤时,就已经讲解如何初始化串口。

    USART1 初始化函数
    要使用串口中断,我们必须先对它进行配置。USART1 初始化代码如下:

    /****************************************************************
    ***************
    * 函数名: USART1_Init
    * 函数功能: USART1 初始化函数
    * 输入: bound:波特率
    * 输出: 无
    *****************************************************************
    **************/
    void USART1_Init(u32 bound)
    {
    //GPIO 端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    
    /* 配置GPIO 的模式和IO 口*/
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX //串口输出PA9
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_Init(GPIOA,&GPIO_InitStructure); 
    /* 初始化串口输入IO */
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX //串口输入PA10
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //模拟输入
    GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */
    
    //USART1 初始化设置
    USART_InitStructure.USART_BaudRate = bound;//波特率设置
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8 位数据格式
    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); //初始化串口1
    USART_Cmd(USART1, ENABLE); //使能串口1
    USART_ClearFlag(USART1, USART_FLAG_TC);
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
    
    //Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1 中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;// 抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC 寄存器
    }
    

    在USART1_Init()函数中,首先使能USART1 串口及端口时钟,并初始化GPIO为复用功能。其次配置串口结构体USART_InitTypeDef,使能串口并开启接收中断,为了防止串口发送状态标志位的影响,我们清除下串口状态标志位(TC),最后配置相应的NVIC 并使能对应中断通道,我们将USART1 的抢占优先级设置为3,响应优先级设置为3。这一过程在前面步骤介绍中已经提了。USART1_Init()函数有一个参数bound,用来设置USART1 串口的波特率,方便大家修改。 USART1 中断函数初始化USART1 后,接收中断就已经开启了,当上位机发送数据过来,STM32F1的串口接收寄存器内即为非空,触发接收中断,具体代码如下:

    /****************************************************************
    ***************
    * 函数名: USART1_IRQHandler
    * 函数功能: USART1 中断函数
    * 输入: 无
    * 输出: 无
    *****************************************************************
    **************/
    
    void USART1_IRQHandler(void) //串口1 中断服务程序
    {
    u8 r;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
    {
    r =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
    USART_SendData(USART1,r);
    while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
    }
    USART_ClearFlag(USART1,USART_FLAG_TC);
    }
    

    为了确认USART1 是否发生接收中断,调用了读取串口中断状态标志位函数USART_GetITStatus,如果确实产生接收中断事件,那么就会执行if 内的语句,将串口接收到的数据保存在变量r 内,然后有通过串口发送出去,通过USART_GetFlagStatus 函数读取串口状态标志,如果数据发送完成,则退出while循环语句,且清除发送完成状态标志位USART_FLAG_TC。

    主函数
    编写好串口初始化和中断服务函数后,接下来就可以编写主函数了,代码如下:
    /****************************************************************
    ***************
    * 函数名: main
    * 函数功能: 主函数
    * 输入: 无
    * 输出: 无
    *****************************************************************
    **************/
    int main()
    {
    	u8 i=0;
    	SysTick_Init(72);
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组分2 组
    	LED_Init();
    	USART1_Init(9600);
    	while(1)
    	{
    		i++;
    		if(i%20==0)
    		{
    			led1=!led1;
    		}
    		delay_ms(10);
    		}
    }
    

    主函数实现的功能很简单,首先调用之前编写好的硬件初始化函数,包括SysTick 系统时钟,中断分组,LED 初始化等。然后调用我们前面编写的USART1初始化函数,这里我们设定串口通信波特率为9600。最后进入while 循环语句,不断让D1 指示间隔200ms 闪烁。如果发生接收中断事件,即会进入中断执行,执行完后回到主函数内继续运行。其实如果你学会了USART1 的使用,对于其他的串口都是类似的。

    展开全文
    weixin_41043617 2021-05-21 14:54:40
  • FuYYZ 2021-03-04 02:38:14
  • qq_45999753 2020-12-03 23:27:52
  • 807KB zhouml_msn 2020-05-07 12:06:19
  • txmnQAQ 2021-10-24 15:03:13
  • qq_27485531 2019-01-04 21:52:01
  • 14.81MB weixin_41988781 2018-04-17 17:42:33
  • 505KB weixin_38725119 2021-05-23 18:32:19
  • 2.17MB weixin_42685438 2021-10-01 18:54:48
  • qq_45264808 2020-12-01 14:33:20
  • Kudo_chitose 2021-05-19 10:42:48
  • weixin_56393108 2021-10-27 16:47:30
  • 11.78MB m0_46070147 2021-07-17 13:23:16
  • bsqetuo 2020-07-04 19:52:26
  • 5.56MB ren18281713749 2019-07-08 08:40:33
  • bsqetuo 2020-07-04 19:22:32
  • claylovetoo 2019-04-29 20:45:42
  • 538KB weixin_42681774 2021-09-30 09:55:39
  • m0_47159351 2020-11-30 19:43:54
  • TBMmagic 2020-12-05 18:29:19
  • 1.92MB weixin_42691065 2021-10-01 06:52:06
  • weixin_44202064 2021-09-16 15:14:49
  • uunubt 2019-07-26 15:21:26

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,489
精华内容 5,395
关键字:

usart串口通信设计