STM32寄存器函数与库函数的区别以及串口通信实验

一、概述:

本文先通过最开始的LED灯程序完成寄存器与库函数的一个对比,然后通过串口完成stm32与上位机(PC机)的串口通信

二、库函数与寄存器的区别

1、库函数与寄存器的区别:

STM32对寄存器操作和对库函数操作的区别主要在于两个点
1、寄存器是直接对芯片的寄存器操作,相对库函数来说,整个程序更加高效,在需要大量处理数据的时候,寄存器能比库函数相对快的处理速度完成

2、库函数相比寄存器来说,我们更容易理解,工程师、编程人员更容易学会如何去应用函数来完成功能。也能够更加高效的完成主程序的撰写。


2、代码对比:

1、寄存器:

#include "led.h"
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输出高 
}

2、库函数:

#include "led.h"
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 输出高 
}

总结

通过代码的直观的对比,对寄存器的操作我们没有一个最直观的感受,我们还需要去查找相应的IO口的寄存器地址,但是通过库函数操作IO口,我们就能很直接的看到不同设置的功能。

3、两种方式所需要的库的区别

1、寄存器:
在这里插入图片描述

2、库函数:
在这里插入图片描述

总结

通过两种方式的所需要的库能够看出,库函数所需要的库比寄存器操作要多得多,所需要的底层开发程序就更多,而且库函数根本也还是对寄存器的操作,所以库函数相比寄存器运行要慢一点。


三、STM32的串口通信USART

1、构建添加需要的库

在这里插入图片描述

  • 注释:这些库函数商家资料都有,我主要演示如何使用。

2、usart_init函数:

void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
  
	//USART1_TX   GPIOA.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);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  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 

}

主要步骤包括:

  • 串口和GPIO引脚时钟使能
  • 串口复位
  • GPIO端口初始化模式设置
  • 串口参数初始化
  • 初始化中断方式和中断等级NVIC并且开启中断
  • 使能串口

3、主函数main:

1:函数体
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
 int main(void)
 {		
 	u16 t0,t1,t;  
	u16 len;	
	u16 times=0;
	char *pt=" Hello windows";
	u8 *on="goon stm32";
	u8 *off="stop stm32";
	u8 flag=0;						//标志如果是1的话,停止发送数据
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 //串口初始化为115200
 	LED_Init();			     //LED端口初始化
	KEY_Init();          //初始化与按键连接的硬件接口
	while(1)
	{
			//给上位机连续发送Hello world
		if(!flag)
		{
			times++;
			if(times%100==0)
			{
				len=14;
				for(t=0;t<len;t++)
			{
			USART_SendData(USART1,pt[t]);//向串口1发送数据
			while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
			}
			printf("\r\n\r\n");//插入换行
			USART_RX_STA=0;
			}
			if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
			delay_ms(10);   
		}
		//接收上位机的发送,并判断是否停止
		if(USART_RX_STA&0x8000)
		{
				len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
				for(t0=0;t0<10;t0++)
					if(off[t0]!=USART_RX_BUF[t0])//如果出现不等,那么就继续发送
					{
						flag=flag;
						break;
					}
				for(t1=0;t1<10;t1++)
					if(on[t1]!=USART_RX_BUF[t1])//如果出现不等,那么就继续发送
					{
						flag=flag;
						break;
					}
				if(t0==10)//如果都相等,那么停止发送
				{
					flag=1;
					printf("已收到停止命令,输出停止\r\n");
					USART_RX_STA=0;
					continue;
				}
				if(t1==10)//如果都相等,那么停止发送
				{
					flag=0;
					printf("已收到继续命令,输出继续\r\n");
					USART_RX_STA=0;
					continue;
				}
				printf("\r\n\r\n");//插入换行
				USART_RX_STA=0;
		}
	}
}

  • 功能介绍:当灯在闪烁时,系统正常工作,打开串口时,调试助手会一直输出Hello windows,当我们给32发送stop stm32时,串口停止向上位机发送,当我们给32发送 goon stm32时,他们会继续输出Hello windows。
2:功能演示:

在这里插入图片描述

灯闪烁情况
在这里插入图片描述

4、总结:

通过串口与上位机联系起来,这样我们就不用每次都调试代码来设置参数,我们能够直接通过上位机发指令来设置参数,这样有利于我们后面学习PID的参数设置的时候,通过上位机的控制来快速修改参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值