day07:编写GPIO端口置位复位函数

为了方便程序的可读性,要把形如“GPIOC->ODR &= ~( 1<<2 );”的语句改成一个函数,增强可读性和可扩展性,比如换成下面的形式:

函数名(端口, 位)

========================================

工程结构:

stm32f10x.h:

/* 用于存放寄存器的映射代码,相当于51单片机的reg52.h */

#ifndef __STM32F10X_H__
#define __STM32F10X_H__

/* 所有的外设基地址 */
#define PERIPH_BASE 		(unsigned int)0X40000000
	
/* 三条总线基地址 */
#define APB1_PERIPH_BASE	PERIPH_BASE
#define APB2_PERIPH_BASE	PERIPH_BASE+0X00010000
#define AHB_PERIPH_BASE		PERIPH_BASE+0X00018000

/* GPIOA - GPIOG端口的地址,它们均在APB2这条总线上 */
#define GPIOA_BASE 			APB2_PERIPH_BASE+0X00000800
#define GPIOB_BASE			APB2_PERIPH_BASE+0X00000C00
#define GPIOC_BASE			APB2_PERIPH_BASE+0X00001000
#define GPIOD_BASE			APB2_PERIPH_BASE+0X00001400
#define GPIOE_BASE			APB2_PERIPH_BASE+0X00001800
#define GPIOF_BASE			APB2_PERIPH_BASE+0X00001C00
#define GPIOG_BASE			APB2_PERIPH_BASE+0X00002000

/* 使用结构体定义寄存器 */
typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef struct 
{
	uint32_t CRL;
	uint32_t CRH;
	uint32_t IDR;
	uint32_t ODR;
	uint32_t BSRR;
	uint32_t BRR;
	uint32_t LCKR;
} GPIO_TypeDef;

// 强制转换成自定义的结构体对象:GPIO_TypeDef
/* GPIOA_BASE是一块内存地址,(GPIO_TypeDef*)表示将内存地址转换成GPIO_TypeDef类型的结构体指针 */
#define GPIOA	((GPIO_TypeDef *)(GPIOA_BASE))	
#define GPIOB	((GPIO_TypeDef *)(GPIOB_BASE))
#define GPIOC	((GPIO_TypeDef *)(GPIOC_BASE))
#define GPIOD	((GPIO_TypeDef *)(GPIOD_BASE))
#define GPIOE	((GPIO_TypeDef *)(GPIOE_BASE))	
#define GPIOF	((GPIO_TypeDef *)(GPIOF_BASE))	
#define GPIOG	((GPIO_TypeDef *)(GPIOG_BASE))

/* APB2外设时钟使能寄存器 */
#define GPIO_RCC			*(unsigned int*)0X40021018

#endif		/* __STM32F10X_H__ */

 stm32f10x_gpio.h:

/* GPIO寄存器相关参数定义 */

#ifndef __STM32F10X_GPIO_H__
#define __STM32F10X_GPIO_H__

#include "stm32f10x.h"

// IO口定义
#define GPIO_Pin_0	(1<<0)
#define GPIO_Pin_1	(1<<1)
#define GPIO_Pin_2	(1<<2)
#define GPIO_Pin_3	(1<<3)
#define GPIO_Pin_4	(1<<4)
#define GPIO_Pin_5	(1<<5)
#define GPIO_Pin_6	(1<<6)
#define GPIO_Pin_7	(1<<7)
#define GPIO_Pin_8	(1<<8)
#define GPIO_Pin_9	(1<<9)
#define GPIO_Pin_10	(1<<10)
#define GPIO_Pin_11	(1<<11)
#define GPIO_Pin_12	(1<<12)
#define GPIO_Pin_13	(1<<13)
#define GPIO_Pin_14	(1<<14)
#define GPIO_Pin_15	(1<<15)

// 置位
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

// 清零
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

#endif		/* __STM32F10X_GPIO_H__ */

stm32f10x_gpio.c:

/* GPIO模块的实现 */

#include "stm32f10x_gpio.h"

// 置位
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
	GPIOx->BSRR = GPIO_Pin;
}

// 清位
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
	GPIOx->BRR = GPIO_Pin;
}

main.c:

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
	
// 延迟函数
void delay(unsigned int i)
{
	for(; i!=0; i--);
}

int main(void)
{
	/* 配置RCC寄存器,使能GPIO口的时钟 */
	GPIO_RCC |= ( 1<<4 );
	
	// 闪烁灯:D4和D5两个LED灯之间不断闪烁
	while(1)
	{
		/* 配置CRL寄存器,配置为推挽输出 */
		GPIOC->CRL |= ( 1<<(4*2) );			// 指针访问成员变量的方式
		/* 配置ODR寄存器 */
		//GPIOC->ODR &= ~( 1<<2 );			// 位2置0,LED亮
		GPIO_ResetBits(GPIOC, GPIO_Pin_2);		// 调用自定义库函数进行清零
		delay(0X99999);	
		//GPIOC->ODR |= ( 1<<2 );			// 位2置1,LED不亮	
		GPIO_SetBits(GPIOC, GPIO_Pin_2);		// 调用自定义库函数进行置1
		
		/* 配置CRL寄存器,配置为推挽输出 */
		GPIOC->CRL |= ( 1<<(4*3) );
		/* 配置ODR寄存器 */
		//GPIOC->ODR &= ~( 1<<3 );			// 位3置0,LED亮
		GPIO_ResetBits(GPIOC, GPIO_Pin_3);		// 调用自定义库函数进行清零
		delay(0X99999);		
		//GPIOC->ODR |= ( 1<<3 );			// 位3置1,LED不亮	
		GPIO_SetBits(GPIOC, GPIO_Pin_3);		// 调用自定义库函数进行置1	
	}
}

void SystemInit(void)
{
	/* 函数体为空,目的是为了骗过编译器不报错 */
}

现象:D4 和 D5 两个LED灯间断闪烁

 

posted @ 2018-04-19 00:12  半生戎马,共话桑麻、  阅读(2276)  评论(0)    收藏  举报
levels of contents