(寄存器操作)STM32F10X系列单片机GPIO口操作

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

一、led函数

需求:输出低电平 点亮

输出高电平 熄灭

(一) 查led引脚

查原理图可得,LED1~4对应的引脚是PE2~PE5,即GPIOE的port2~port5

(二) led初始化

开时钟

我们查一下数据手册,发现GPIOE对应的时钟总线是RCC的APB2ENR寄存器

于是再去翻参考手册,发现该寄存器GPIOE对应的位数是第六位

翻参考手册,发现该寄存器GPIOE对应的位数是第六位

于是我们把相应的位置1,即可开启GPIOE的时钟

RCC->APB2ENR |= (0X1<<6); //开启GPIOE的时钟

设置引脚模式

开启时钟后,我们要设置一下led1对应的GPIOE的PE2引脚

查阅参考手册,寄存器的0~7端口由CRL*地位寄存器管理

记忆技巧:低位引脚CRL(low),高位引脚CRH(high)

CRL每四位管理一个引脚,PE2对应的位为8-11位,需要给引脚输出低电平,所以我们要设置模式为通用推挽输出,速度50MHZ,即8-11位设置为0011

操作手法:

首先将8-11清零

(0XF<<8)其中 管led灯的 有4位 0xF == 1111 <<8 是要把8-11位清0

然后再将8,9位 置1 即可

(0x3<<8) 其中 0x3 是为了设置模式 为0x3== 0011 <<8 作用相同为了把8-11位 设置成0011

****清零操作***

***置1操作***

输出电平

输出,需要操作输出寄存器ODR

记忆技巧:输出寄存器ODR(output) 输入寄存器IDR(intut)

查阅参考手册

由图可知,若想给PE2引脚输出一个低电平,把第二位清零即可

GPIOE ->ODR &=~ (0X01<<2);//第二位清零,输出低电平,灯亮

*技巧:操作ODR寄存器时,操作哪一位就移几位

这是时候对于PE2引脚的操作流程就写完了,完整代码如下

//开时钟
RCC->APB2ENR |= (0X1<<6);
//设置引脚模式
GPIOE->CRL &=~(0XF<<8);//CRL 8-11位清零
GPIOE->CRL |=(0X03<<8);//8-11位0011 通用推免输出
//点灯
GPIOE ->ODR &=~ (0X01<<2);//第二位清零,输出低电平,灯亮

至于PE3,PE4,PE5,操作基本相同,只需要修改操作的位即可

完整代码如下


//PE3
GPIOE->CRL &=~(0XF<<12);//CRL 12-15位清零
GPIOE->CRL |=(0X03<<12);//通用推免输出
GPIOE ->ODR &=~ (0X01<<3);//点灯
//PE4
GPIOE->CRL &=~(0XF<<16);//CRL 16-20位清零
GPIOE->CRL |=(0X03<<16);//通用推免输出
GPIOE ->ODR &=~ (0X01<<4);//点灯
//PE5
GPIOE->CRL &=~(0XF<<20);//CRL 20-24位清零
GPIOE->CRL |=(0X03<<20);//通用推免输出
GPIOE ->ODR &=~ (0X01<<5);//点灯

关灯,只需要把输出寄存器ODR的第2,3,4,5位全部设置为高电平即可

GPIOE->ODR |= (0xF << 2);

*置高 PE2~PE5(1为高电平,高电平关灯) 关闭这四个灯 F正好表示四位 然后移两位就是PE2-PE5

(三) 封装led函数

寄存器操作难免有些累

把他封装成一个个函数会省很多事情

首先,初始化led函数,需要完成开时钟和设置引脚模式,开关灯操作单独封装

代码如下

void led_config(void)
{
	//开时钟
	RCC->APB2ENR |= (0X1<<6);

	//设置引脚模式
	//PE2
	GPIOE->CRL &=~(0XF<<8);//CRL 8-11位清零
	GPIOE->CRL |=(0X03<<8);//8-11位0011 通用推免输出

	//PE3
	GPIOE->CRL &=~(0XF<<12);//CRL 12-15位清零
	GPIOE->CRL |=(0X03<<12);//通用推免输出

	//PE4
	GPIOE->CRL &=~(0XF<<16);//CRL 16-20位清零
	GPIOE->CRL |=(0X03<<16);//通用推免输出

	//PE5
	GPIOE->CRL &=~(0XF<<20);//CRL 20-24位清零
	GPIOE->CRL |=(0X03<<20);//通用推免输出
}

用PE2开灯举例子,

GPIOE ->ODR &=~ (0X01<<2);

该代码存在两个变量更换端口时,这两个值会变。所以封装时,把他俩当参数传进去就可以实现开灯操作

GPIOE是一个结构体,在标准库中已有定义

所以我们设置一下参数即可

#define led1port GPIOE //PE2
#define led2port GPIOE //PE3
#define led3port GPIOE //PE4
#define led4port GPIOE //PE5
#define led1pin  1<<2
#define led2pin  1<<3
#define led3pin  1<<4
#define led4pin  1<<5

封装后的开关灯代码如下

//开灯函数
void led_on(GPIO_TypeDef * port,uint16_t pin)
{
	port->ODR &=~ (pin);   
	
}

//关灯函数
void led_off(GPIO_TypeDef * port,uint16_t pin)
{
	port->ODR |= (pin);   
	
}

封装后

led_on(led1port,led1pin); 如此可实现对led1的开灯操作,见名知意,关灯函数同理

led头文件如下

#ifndef __LED_H
#define __LED_H

#include "stm32f10x.h"
#include "delay.h"
void led_config(void);
void led_on(GPIO_TypeDef * port,uint16_t pin);
void led_off(GPIO_TypeDef * port,uint16_t pin);


#define led1port GPIOE //PE2
#define led2port GPIOE //PE3
#define led3port GPIOE //PE4
#define led4port GPIOE //PE5
#define led1pin  1<<2
#define led2pin  1<<3
#define led3pin  1<<4
#define led4pin  1<<5


#endif

二、延时函数

讲解略,直接上代码

#include "delay.h"

void delay_1us(void)
{
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
}

//us延时函数
void delay_us(uint32_t t)
{
	for(uint32_t i =0;i<t;i++)
	{
		delay_1us();
	}
}

//ms函数
void delay_ms(uint32_t t)
{
	t=1000*t;
	for(uint32_t i =0;i<t;i++)
	{
		delay_1us();
	}
}

三、beep函数

beep函数用于操作蜂鸣器

高电平响

低电平停

(一) 查beep引脚

由图可知beep对应单片机的PC0引脚,即GPIOC的第0位引脚

(二) beep初始化

开时钟

可参考led开时钟分析

RCC->APB2ENR |= (0X1<<4); //开启控制GPIOC的时钟

设置引脚模式

设置PC0引脚模式

参考GPIOE->CRL可知PC0被前四位管理

	GPIOC->CRL &=~(0XF<<0);//CRL 0-4位清零
	GPIOC->CRL |=(0X03<<0);//设置模式为通用推挽

输出电平
GPIOC ->ODR |= (0X01<<0);	//设置输出位为1高电平,高电平beep响

GPIOC ->ODR |= (0X01<<0);	//设置输出位为0低电平,高电平beep停

*蜂鸣器操作和led操作相反,设置时要注意

(三) 封装beep函数

封装原理和led相同

代码如下

void beep_config(void)//初始化蜂鸣器 
{
	
	
	//开时钟
	RCC->APB2ENR |= (0X1<<4); //开启控制GPIOC的时钟
	//设置模式
	GPIOC->CRL &=~(0XF<<0);//CRL 0-4位清零
	GPIOC->CRL |=(0X03<<0);//设置模式为通用推挽

}


void beep_on(GPIO_TypeDef * port,uint16_t pin)	//开蜂鸣器函数
{
	port->ODR |= (pin);   
	
}

void beep_off(GPIO_TypeDef * port,uint16_t pin)		//关蜂鸣器函数
{
	port->ODR &=~ (pin);   
	
}

beep函数头文件如下

#ifndef __BEEP_H
#define __BEEP_H


#include "stm32f10x.h"

void beep_config(void);
void beep_off(GPIO_TypeDef * port,uint16_t pin);
void beep_on(GPIO_TypeDef * port,uint16_t pin);
#define   beepport  GPIOC


#define beeppin  0X01<<0

#endif

标准库函数应用

1.初始化

该段参考STM32固件库使用手册

GPIO_InitTypeDef GPIO_InitStructure; 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_XX;  //设置引脚XX
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 		//10MHZ为速度 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		//IN_FLOATING为模式
GPIO_Init(GPIOX, &GPIO_InitStructure); 			//初始化GPIOX

2.设置I/O电平

GPIO_SetBits / GPIO_ResetBits

 GPIO_SetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15);  //设置GPIOA的10,15引脚为高电平
 GPIO_ResetBits(GPIOB, GPIO_Pin_9 | GPIO_Pin_12);  //设置GPIOA的9,12引脚为低电平

SetBits---设为高电平

ResetBits---设为低电平

GPIO_WriteBit

GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET);  //前两个参数 同SetBits,最后一个参数是把电平设置为0或1

四、 relay函数

(一) 查引脚

需求:输出高电平,吸合

输出低电平,断开

从原理图上看relay对应GPIOA的第11个引脚

(二) relay初始化

开时钟

翻参考手册,发现该寄存器GPIOA对应的位数是第2位

于是我们把相应的位置1,即可开启GPIOA的时钟

RCC->APB2ENR |= (0X1<<2); //开启GPIOA的时钟

设置引脚模式

设置PA11引脚模式 为通用推挽

CRH高位寄存器管理8~15号引脚

GPIOA->CRH &=~(0XF<<12);//CRL 0-4位清零
GPIOA->CRH |=(0X03<<12);//设置模式为通用推挽
输出电平

继电器高电平吸合,低电平松开

继电器不好观察效果,可以在主函数一关一开,能听见声音

//封装函数
//开继电器函数
void relay_on(GPIO_TypeDef * port,uint16_t pin)
{
	port->ODR &=~ (pin);   
	
}

//关继电器
void relay_off(GPIO_TypeDef * port,uint16_t pin)
{
	port->ODR |= (pin);   
	
}

头文件代码如下

#ifndef __RELAY_H
#define __RELAY_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"

void relay_config(void);
void relay_off(GPIO_TypeDef * port,uint16_t pin);
void relay_on(GPIO_TypeDef * port,uint16_t pin);

#define   relayport  GPIOA


#define relaypin  0X1<<11

#endif

五、RGB函数

(一) 查引脚

从原理图可知控制RGB彩灯的引脚是GPIOA的PA6,PA7,PA8三个引脚

设置引脚模式

PA6,PA7属于CRL地位寄存器

PA8属于CRH高位寄存器

原理都相同

//PA6,PA7
GPIOA->CRL &=~(0XFF<<24);//CRL 0-4位清零
GPIOA->CRL |=(0X033<<24);//设置模式为通用推挽

//PA8
GPIOA->CRH &=~(0XF<<0);//CRL 0-4位清零
GPIOA->CRH |=(0X03<<0);//设置模式为通用推挽

输出电平
void rgb_on(GPIO_TypeDef * port,uint16_t pin)
{
	port->ODR &=~ (pin);   //低电平点亮
	
}

void rgb_off(GPIO_TypeDef * port,uint16_t pin)
{
	port->ODR |= (pin);   //高电平熄灭
	
}

头文件如下

#ifndef __RGB_H
#define __RGB_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"

void rgb_config(void);
void rgb_off(GPIO_TypeDef * port,uint16_t pin);
void rgb_on(GPIO_TypeDef * port,uint16_t pin);
#define   rgbport  GPIOA


#define rgbpin  0X07<<6

#endif

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值