STM32学习笔记3:正点原子miniSTM32串口通信实验详解

初学者学习总结,如有错误,请大神指正


目的:用 STM32 的串口来发送和接收数据。

一、STM32串口

1.1 简介

ALIENTEK MiniSTM32 V3 版开发板选择的是 STM32F103RCT6 作为 MCU,拥有5 个串口分别为

USART1、USART2、USART3、UART4、UART5,

其中只有USART1挂载在APB2总线上,其余均挂载在APB1总线上

APB1操作速度限于36MHz,APB2操 作于全速(最高72MHz)。

注:

UART     通用异步收发器

USART   通用同步异步收发器

1.2 端口复用

在STM32F103RCT6中串口 1 的引脚对应的 IO 为 PA9,PA10而PA9,PA10 默认功能是 GPIO,所以当 PA9,PA10 引脚作为串口 1 的 TX,RX 引脚使用的时候,那就是端口复用。

复用端口初始化有几个步骤:

1) GPIO 端口时钟使能。要使用到端口复用,当然要使能端口的时钟了。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

2) 复用的外设时钟使能。比如你要将端口 PA9,PA10 复用为串口,所以要使能串口时钟。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

3) 端口模式配置。在 IO 复用位内置外设功能引脚的时候,必须设置 GPIO 端口的模式。下表为对应模式

 例如要配置全双工的串口 1  

代码如下

//USART1_TX PA.9 复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
//USART1_RX PA.10 浮空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA,GPIO_InitStructure);

1.3 USART库函数

1.4 串口设置 

串口设置的一般步骤可以总结为如下几个步骤:

1) 串口时钟使能,GPIO 时钟使能

2) 串口复位 3) GPIO 端口模式设置

4) 串口参数初始化

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

6) 使能串口

7) 编写中断处理函数

1.5 主要函数介绍

1)串口时钟使能

串口是挂载在 APB2 下面的外设,所以使能函数为:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);

2)串口复位

 

USART_DeInit(USART1); //复位串口 1 

3)串口参数初始化

 一般的实现格式为:

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); //初始化串口

4)数据发送与接收

STM32 的发送与接收是通过数据双寄存器 USART_DR 来实现的,包含了 TDR 和 RDR。

当向该寄存器写数据的时候,串口就会自动发送,当收到收据的时候,存在该寄存器内。

  • 发送数据
  • 例如

    USART_SendData(USART3, 0x26);

  • 接收数据
  • 例如

    USART_ReceiveData(USART3, 0x26); 

     5)串口状态

    6)串口使能

     例如

    USART_Cmd(USART1, ENABLE);

    7)开启串口响应中断

     

    例如

     USART_ITConfig(USART1, USART_IT_Transmit ENABLE);

    8)获取相应中断状态

    例如

     ITStatus ErrorITStatus;

    ErrorITStatus = USART_GetITStatus(USART1, USART_IT_OverrunError);

    二、硬件连接

    在ALIENTEK MiniSTM32 V3 版开发板上串口 1 与 USB 串口并没有在 PCB 上连接在一起,需要用跳线帽连接。

    如图

     三、程序设计

    3.1 串口初始化程序

    void uart_init(u32 bound){
        //GPIO端口设置
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
        //使能USART1,GPIOA时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
      
    	//USART1_TX即GPIOA9
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
        GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.9
       
        //USART1_RX即GPIOA10初始化
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
        GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  
    
        //Usart1 NVIC 配置
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
      
        //USART 初始化设置
    
    	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_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
        USART_Cmd(USART1, ENABLE);                    //使能串口1 
    
    }

    代码编写对应步骤:

    1) 串口时钟使能,GPIO 时钟使能

    2) 串口复位

    3) GPIO 端口模式设置

    4) 串口参数初始化

    5) 开启中断并且初始化 NVIC

    6) 使能串口

    3.2 中断接收程序

    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)  
        //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    		{
    		Res =USART_ReceiveData(USART1);	//读取接收到的数据
    		
    		if((USART_RX_STA&0x8000)==0)//接收未完成
    			{
    			if(USART_RX_STA&0x4000)//接收到了0x0d
    				{
    				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
    				else USART_RX_STA|=0x8000;	//接收完成了 
    				}
    			else //还没收到0X0D
    				{	
    				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;
                        //接收数据错误,重新开始接收	  
    					}		 
    				}
    			}   		 
         } 

    即第七步

    7) 编写中断处理函数

    3.3 main

    #include "sys.h"
    #include "usart.h"
    #include "delay.h"
    #include "led.h" 
    int main(void)
    {
    	u8 t;
    	u8 len;
    	u16 times=0; 
    	
    	delay_init(); //延时函数初始化
    	uart_init(9600); //串口初始化为 9600
    	LED_Init(); //初始化与 LED 连接的硬件接口
    	
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断分组 
    	
    	while(1)
    	{
    		if(USART_RX_STA&0x8000)
    		{ 
    			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
    			
    			printf("\r\n 您发送的消息为:\r\n");
    			
    			for(t=0;t<len;t++)
    			{
    				USART1->DR=USART_RX_BUF[t];
    				while((USART1->SR&0X40)==0);//等待发送结束
    			}
    			
    			printf("\r\n\r\n");//插入换行
    			
    			USART_RX_STA=0;
    		}else
    		{
    			times++;
    			
    			if(times%5000==0)
    			{
    				printf("\r\nALIENTEK MiniSTM32 开发板 串口实验\r\n");
    				printf("正点原子@ALIENTEK\r\n\r\n\r\n");
    			}
    			
    			if(times%200==0)printf("请输入数据,以回车键结束\r\n"); 
    			if(times%30==0)LED0=!LED0;//闪烁 LED,提示系统正在运行.
    			
    			delay_ms(10); 
    		}
    	}
    }

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32学习笔记3:正点原子miniSTM32串口通信实验详解

    发表评论