[STM32F103RC]正点原子mini板,嵌入式学习日记----点灯(寄存器)

前言

相比于库函数,有过单片机基础的对于寄存器写法肯定更熟悉,写起来也会更简单,正点原子的课程过于坑爹,那么在正点原子课程中没有细说的地方我会做出补充,当然也要配合资料来看,正点原子的资料还是很棒的,有过单片机学习经验的看懂不是很难

思路

依旧是老规矩,先分析思路,无论写什么代码都要知道自己要做什么

对于点亮LED来说

第一步:使能外部时钟         APB2总线下的外部时钟

第二部:初始化引脚        PA8,PD2,50HZ推挽输出

第三步:点灯        置1,延时,置0

具体的细节在上一篇库函数已经交代过,这里不过多赘述

创建文件

首先创建一个led.h文件,用来防止复用,上一篇库函数已经讲过,直接看代码

#ifndef __LED_H
#define __LED_H


void LED_Init(void);

#endif

创建C文件

也就是初始化函数的文件

根据上文说过的寄存器第一步就是使能外部时钟

我手中的板子led是PA8和PD2

这是配置的代码

RCC->APB2ENR|=1<<2;
RCC->APB2ENR|=1<<5;

按照对应的寄存器设置,A位在第二位,所以将1向左移动两位,D位同理

至于为何用左移右移的方式,因为对于复杂的单片机而言,像常规的设置整个寄存器的状态可能会对其他寄存器造成影响,使用这种方法就可以避免影响到寄存器的其他位

|=符号则是C语言中的或运算,学过数电的都知道,1与任何数或都为1 所以在操纵寄存器单个数据的时候我们一般置1使用XXX|=1<<2;置0一般使用XXX&=~(1<<2);的方法

如果确定其他位的状态,假如只有第三位为1,其他为0,就可以写XXX=0x04;这样的十六进制写法

RCC是关与寄存器的一个结构体变量缩写名称,APB2ENR是成员变量,所以用指向的方式写,意思是外设时钟使能寄存器

初始化引脚

如图所示,引脚有十六个,分为高八位和低八位,0-7属于低八位,8-15为高八位,每位引脚由四位数据控制状态,而控制引脚的四位数据中,前两位控制输入输出,一旦选定,后两位控制输入输出的状态,所以后两位看起来同样的数据配置有两种状态,其实是由输入输出决定的

我们的引脚为PD2和PA8,所以选低八位的第3组的四位数据和高八位的第一组的数据

写法是

GPIOA->CRH&=0xfffffff0;
GPIOA->CRH|=0x00000003;
GPIOD->CRL&=0xfffff0ff;
GPIOD->CRL|=0x00000300;

第一行和第三行是为了清除目标为的状态并置零

寄存器名称如图所示不再多说

看图上的清除置零方法,上面提到,置零要用与非的方式,可这里是与运算,因为十六进制的F转换为二进制就是1111,对应四位控制位,而1与任何数与都等于任何数,0与任何数与都等于0,所以用这种方式既可以置零,又不会影响其他位的状态

2,4行置1上文已经解释过,之说一下3是什么意思,十六进制的3转换为2进制就是0011对应图中的50HZ推挽输出模式

最后设置初始状态

如图可见16位数据置1,0就可以控制所以直接写就好,没得讲

GPIOD->ODR|=1<<2;
GPIOA->ODR|=1<<8;

完整代码为

#include "led.h"
#include "stm32f10x.h"

void LED_Init()
{
	RCC->APB2ENR|=1<<2; //启用GPIOA的时钟   APB2ENR使能/禁用APB2时钟寄存器   ENG就是使能/禁用
	RCC->APB2ENR|=1<<5;//启用GPIOD的时钟   ||至于-》的写法,是因为APB2ENG是RCC结构体的成员变量
//CR就是配置寄存器的意思
	
	GPIOA->CRH&=0xfffffff0;//清除A8位置0
	GPIOA->CRH|=0x00000003;//设为推挽输出
	//mini板有0-15个pin口,分别对应,CRH和CRL各32位,每四位控制一个引脚,各控制八个引脚
	//即外设IO口A的高配置寄存器的0-3位也就是8号引脚
	
	GPIOA->ODR|=1<<8;//PA8输出高电平
	
	GPIOD->CRL&=0xfffff0ff;//清除置0
	GPIOD->CRL|=0x00000300;
	
	GPIOD->ODR|=1<<2;
	//即外设IO口D的低配置寄存器的8-11位也就是2号引脚
	
	
	
}



main函数

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"	 

int main(void)
{				 
	delay_init(72);
	LED_Init();
	
  	while(1)
	{
		GPIOA->ODR|=1<<8;
		GPIOD->ODR|=1<<2;
		
		delay_ms(50);
		
		GPIOA->ODR&=~(1<<8);
		GPIOD->ODR&=~(1<<2);
		
		delay_ms(50);

	}	 
} 



其中的代码在上篇库函数和这一篇都已经解释过

唯一不同就是delay初始化不知道为什么突然要初始值了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值