基于寄存器和固件库的STM32LED灯实验

目录

一、基于寄存器点亮LED灯

1、寄存器的定义

2、创建一个基于寄存器的keil工程

3、基于寄存器的LED流水灯

二、基于固件库点亮LED灯

1、固件库的定义

2、创建一个基于寄固件库的keil工程

3、基于固件库的LED流水灯

三、两种方式的对比


一、基于寄存器点亮LED灯

1、寄存器的定义

寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成。

2、创建一个基于寄存器的keil工程

1)、新建一个文件夹,命名为stm32基于寄存器点亮led,打开keil,点击Project,选择New uVision Project,选择文件夹(stm32基于寄存器点亮led),新建项目(寄存器LED),选择开发板STM32F103C8。

2)、在线添加库文件
用寄存器控制 STM32 时,不需要在线添加库文件,可以直接关掉。
3)、添加文件
①添加已经存在文件
在新建的工程中添加启动文件(startup_stm32f10x_hd.s),该文件可以先到固件库中复制到此处startup_stm32f10x_hd.s。
②创建新文件
stm32f10x.h
手动新建,用于存放寄存器映射的代码,暂时为空。
main.c
手动新建,用于存放 main 函数,暂时为空。

4)、配置魔术棒选项卡
①Target设置,目的是能够使用printf

②Output设置,以便在编译时生成hex文件

③Listing设置,让输出文件定位到Listing文件夹

④Debug设置

⑤Utilities设置

3、基于寄存器的LED流水灯

1)、编写代码

#define GPIOC_BASE 0x40011000
#define GPIOA_BASE 0x40010800

#define RCC_APB2ENR (*(unsigned int *)0x40021018)

#define GPIOB_CRH (*(unsigned int *)0x40010C04)
#define GPIOC_CRH (*(unsigned int *)0x40011004)
#define GPIOA_CRL (*(unsigned int *)0x40010800)

#define GPIOB_ODR (*(unsigned int *)0x40010C0C)
#define GPIOC_ODR (*(unsigned int *)0x4001100C)
#define GPIOA_ODR (*(unsigned int *)0x4001080C)
	


void Delay_ms(volatile  unsigned  int);
void A_LED_LIGHT(void);
void B_LED_LIGHT(void);
void C_LED_LIGHT(void);
void Delay_ms( volatile  unsigned  int  t)
{
     unsigned  int  i;
     while(t--)
         for (i=0;i<800;i++);
}

void A_LED_LIGHT(){
	GPIOA_ODR=0x0<<4;		//PA4低电平
	GPIOB_ODR=0x1<<9;		//PB9高电平
	GPIOC_ODR=0x1<<13;		//PC13高电平
}
void B_LED_LIGHT(){
	GPIOA_ODR=0x1<<4;		//PA4高电平
	GPIOB_ODR=0x0<<9;		//PB9低电平
	GPIOC_ODR=0x1<<13;		//PC13高电平
}
void C_LED_LIGHT(){
	GPIOA_ODR=0x1<<4;		//PA4高电平
	GPIOB_ODR=0x1<<9;		//PB9高电平
	GPIOC_ODR=0x0<<13;		//PC13低电平	
}

int main(){
	int j=100;
	// 开启时钟
	RCC_APB2ENR |= (1<<3); // 开启 GPIOB 时钟
	RCC_APB2ENR |= (1<<4); // 开启 GPIOC 时钟
	RCC_APB2ENR |= (1<<2); // 开启 GPIOA 时钟
	
	

	// 设置 GPIO 为推挽输出
	GPIOB_CRH&= 0xffffff0f;	//设置位 清零		
	GPIOB_CRH|=0x00000020;  //PB9推挽输出
	 
	GPIOC_CRH &= ~(1111<<(4*5)); //设置位 清零		
	GPIOC_CRH|=(1<<(4*5)); //PC13推挽输出

 

	GPIOA_CRL &= 0xfff0ffff; //设置位 清零		
	GPIOA_CRL|=0x00010000; //PA4推挽输出
	 
	// 3个LED初始化为不亮(即高点位)
	GPIOB_ODR |= (1<<9); 
	GPIOC_ODR |= (1<<13); 
	GPIOA_ODR |= (1<<4);  
	
	while(j){
		
		B_LED_LIGHT();
		Delay_ms(10000);
	 
		C_LED_LIGHT();
		Delay_ms(10000);
	 
		A_LED_LIGHT();
		Delay_ms(10000);
	}

}

 2)、实验结果

二、基于固件库点亮LED灯

1、固件库的定义

固件库又称固件函数库,是⼀个固件函数包,它由程序、数据结构和宏组成,包括了微控制器所有外设的性能特征。该函数库还包括每⼀个外设的驱动描述和应⽤实例,为开发者访问底层硬件提供了⼀个中间API,通过使⽤固件函数库,⽆需深⼊掌握底层硬件细节,开发者就可以轻松应⽤每⼀个外设。因此,使⽤固态函数库可以⼤⼤减少⽤户的程序编写时间,进⽽降低开发成本。每个外设驱动都由⼀组函数组成,这组函数覆盖了该外设所有功能。每个器件的开发都由⼀个通⽤API (application programming interface 应⽤编程界⾯)驱动,API对该驱动程序的结构,函数和参数名称都进⾏了标准化

2、创建一个基于寄固件库的keil工程

方法类似于寄存器的创建。
不同点:

需要添加libraries文件

3、基于固件库的LED流水灯

1)编写代码

``
#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	

	GPIO_InitTypeDef GPIO_InitStructure;//创建结构体
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置为推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;//初始化GPIOA的全部引脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	//将串口设置为高电平,因为接线方式导致LED灯默认为低电平点亮,故先熄灭LED灯
	GPIO_SetBits(GPIOA,GPIO_Pin_0);
	GPIO_SetBits(GPIOA,GPIO_Pin_1);
	GPIO_SetBits(GPIOA,GPIO_Pin_2);
	GPIO_SetBits(GPIOA,GPIO_Pin_3);
	GPIO_SetBits(GPIOA,GPIO_Pin_4);
	GPIO_SetBits(GPIOA,GPIO_Pin_5);
	GPIO_SetBits(GPIOA,GPIO_Pin_6);
	GPIO_SetBits(GPIOA,GPIO_Pin_7);
	
	while (1)
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_0);//低电平点亮
		Delay_ms(1000);                  //延时1s
		GPIO_SetBits(GPIOA,GPIO_Pin_0);  //高电平熄灭
		GPIO_ResetBits(GPIOA,GPIO_Pin_1);
		Delay_ms(1000);
		GPIO_SetBits(GPIOA,GPIO_Pin_1);
		GPIO_ResetBits(GPIOA,GPIO_Pin_2);
		Delay_ms(1000);
		GPIO_SetBits(GPIOA,GPIO_Pin_2);
		
		GPIO_ResetBits(GPIOA,GPIO_Pin_3);
		Delay_ms(1000);
		GPIO_SetBits(GPIOA,GPIO_Pin_3);
		GPIO_ResetBits(GPIOA,GPIO_Pin_4);
		Delay_ms(1000);
		GPIO_SetBits(GPIOA,GPIO_Pin_4);
		GPIO_ResetBits(GPIOA,GPIO_Pin_5);
		Delay_ms(1000);
		GPIO_SetBits(GPIOA,GPIO_Pin_5);
		GPIO_ResetBits(GPIOA,GPIO_Pin_6);
		Delay_ms(1000);
		GPIO_SetBits(GPIOA,GPIO_Pin_6);
		GPIO_ResetBits(GPIOA,GPIO_Pin_7);
		Delay_ms(1000);
		GPIO_SetBits(GPIOA,GPIO_Pin_7);;
	}

}

2)实验结果

三、两种方式的对比

寄存器方法
缺点:
①开发速度慢
②程序可读性差
③维护复杂
优点:
①具体参数更直观
②程序运行占用资源少
开库开发方式则正好弥补了寄存器开发的缺点。
通过两个方式的实现,你会发现采用寄存器开发的方式,需要不断地查看对应的手册,了解对应寄存器的地址。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值