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灯间断闪烁

浙公网安备 33010602011771号