当前位置:网站首页>STM32串口通信

STM32串口通信

2020-12-08 12:33:55 osc_52r4y6wv

一、学习任务

  1. 学习相关资料,说名基于寄存器与基于固件库的stm32 LED流水灯例子的编程方式有什么差异。
  2. 学习和阅读“零死角玩转STM32F103–指南者”文档中的第20、21章内容,完成STM32的USART窗口通讯程序,要求:1)设置波特率为115200,1位停止位,无校验位。2)STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。3)当上位机给stm32发送“Stop,stm32”后,stm32停止发送。

二、学习内容

1.基于寄存器与基于固件库的stm32 LED流水灯编程方式差异

1.1基于寄存器的stm32 LED流水灯程序

1.1.1寄存器简介

寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成。
按照功能的不同,可将寄存器分为基本寄存器和移位寄存器两大类。基本寄存器只能并行送入数据,也只能并行输出。移位寄存器中的数据可以在移位脉冲作用下依次逐位右移或左移,数据既可以并行输入、并行输出,也可以串行输入、串行输出,还可以并行输入、串行输出,或串行输入、并行输出,十分灵活,用途也很广。

1.1.2.代码

led.h

#ifndef __LED_H
#define __LED_H	 
#include "sys.h"


//LED端口定义
#define LED0 PBout(5)	// DS0
#define LED1 PEout(5)	// DS1	

void LED_Init(void);	//初始化		 				    
#endif

led.c

#include "led.h"


//初始化PB5和PE5为输出口.并使能这两个口的时钟		    
//LED IO初始化
void LED_Init(void)
{
   
   
	RCC->APB2ENR|=1<<3;    //使能PORTB时钟	   	 
	RCC->APB2ENR|=1<<6;    //使能PORTE时钟	
	   	 
	GPIOB->CRL&=0XFF0FFFFF; 
	GPIOB->CRL|=0X00300000;//PB.5 推挽输出   	 
  GPIOB->ODR|=1<<5;      //PB.5 输出高
											  
	GPIOE->CRL&=0XFF0FFFFF;
	GPIOE->CRL|=0X00300000;//PE.5推挽输出
	GPIOE->ODR|=1<<5;      //PE.5输出高 
}

main.c

#include "sys.h"
#include "usart.h"		
#include "delay.h"	
#include "led.h"

int main(void)
{
   
   				  
	Stm32_Clock_Init(9);//系统时钟设置
	delay_init(72);	  	//延时初始化
	LED_Init();		  	//初始化与LED连接的硬件接口
	while(1)
	{
   
   
		LED0=0;		//低电平有效
		LED1=1;
		delay_ms(1000);
		LED0=1;
		LED1=0;
		delay_ms(1000);
	}	 
}

1.2基于固件库的stm32 LED流水灯程序

1.2.1固件库概述

固件是介于软件和硬件之间的产品,给开发者访问底层硬件提供一个中间的API,大大提高应用程序开发效率。CMSIS: ARM Cortex 微控制器软件接口标准(CMSIS:Cortex Microcontroller Software Interface Standard) 是 Cortex-M 处理器系列的与供应商无关的硬件抽象层,使用CMSIS,可以为处理器和外设实现一致且简单的软件接口,从而简化软件的重用、缩短微控制器新开发人员的学习过程,并缩短新设备的上市时间。

1.2.2代码

led.h

#ifndef __LED_H
#define __LED_H	 
#include "sys.h"

#define LED0 PBout(5)// PB5
#define LED1 PEout(5)// PE5	
void LED_Init(void);//初始化				    
#endif

led.c

#include "led.h"
//初始化PB5和PE5为输出口.并使能这两个口的时钟		    
//LED IO初始化
void LED_Init(void)
{
   
   
 GPIO_InitTypeDef  GPIO_InitStructure;	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PB,PE端口时钟	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				 //LED0-->PB.5 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB.5
 GPIO_SetBits(GPIOB,GPIO_Pin_5);						 //PB.5 输出高
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	    		 //LED1-->PE.5 端口配置, 推挽输出
 GPIO_Init(GPIOE, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
 GPIO_SetBits(GPIOE,GPIO_Pin_5); 						 //PE.5 输出高 
}

main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"

 int main(void)
 {
   
   	
	delay_init();	    //延时函数初始化	  
	LED_Init();		  	//初始化与LED连接的硬件接口
     
    
	while(1)
	{
   
   
		LED0=0;
		LED1=1;
		delay_ms(300);	 //延时300ms
		LED0=1;
		LED1=0;
		delay_ms(300);	//延时300ms
	}    
 }


 /**
 *****************下面注视的代码是通过调用库函数来实现IO控制的方法*****************************************
int main(void)
{ 
 
	delay_init();		  //初始化延时函数
	LED_Init();		        //初始化LED端口
	while(1)
	{
			GPIO_ResetBits(GPIOB,GPIO_Pin_5);  //LED0对应引脚GPIOB.5拉低,亮  等同LED0=0;
			GPIO_SetBits(GPIOE,GPIO_Pin_5);   //LED1对应引脚GPIOE.5拉高,灭 等同LED1=1;
			delay_ms(300);  		   //延时300ms
			GPIO_SetBits(GPIOB,GPIO_Pin_5);	   //LED0对应引脚GPIOB.5拉高,灭  等同LED0=1;
			GPIO_ResetBits(GPIOE,GPIO_Pin_5); //LED1对应引脚GPIOE.5拉低,亮 等同LED1=0;
			delay_ms(300);                     //延时300ms
	}
} 

1.3 差异

仔细观察源代码发现主要是led.c中的LED_Init()函数有很大的差别。基于寄存器的主要是使用指针指向地址进行使能和赋值;基于固件库主要使用的函数包进行使能和赋值。在小工程中可以看出使用寄存器和固件库是没有多大差别的,但从实现多功能和多端口的工程设计来看,使用固件库可以大大减少开发时间,提高工作效率。
使用固件库,目前比较多的例程是使用固件库编写的。官方的例子也都采用固件库方式。特点就是简单,易于理解,资料多。如果你没有CortexM系列内核的开发基础,建议从固件库开始玩起。等有一定基础,或是特别需要时再用寄存器。
使用寄存器,想要深入理解CortexM3内核或是需要为了获得更好的可移植性,学习寄存器编程会比较有帮助。但是从专业的角度上看,寄存器更贴近底层,对外设的工作原理和运行机理会有更深的理解。

2.STM32的USART窗口通讯程序

2.1 实验环境

开发板:野火指南者(STM32F103)
STM32库版本:STM32F10x_StdPeriph_Lib_V3.5.0
IDE:KEIL5
使用到的串口:USART1
硬件原理图:
在这里插入图片描述




2.2 实验文件

链接:书籍配套例程-F103VE指南者
提取码:k5rw
下载完成后如箭头所示打开keil文件。
在这里插入图片描述


2.3.相关代码及修改

2.3.1 找到stm32f10x_it.c,及main.c;
在这里插入图片描述
2.3.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++;
}

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);
	}	
}

2.3.3.修改如下
stm32f10x_it.c:
在这里插入图片描述
main.c:
.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Jhd2VpOTM5,size_16,color_FFFFFF,t_70)
2.3.4编译及生成hex文件
在这里插入图片描述





2.4.烧录程序

2.4.1 连接开发板
在这里插入图片描述
2.4.2打开串口下载器选择刚编译生成的.hex文件,然后进行烧写
在这里插入图片描述


3.实验结果

在这里插入图片描述

三、参考网址

STM32串口通信USART学习笔记

版权声明
本文为[osc_52r4y6wv]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/4274700/blog/4780882