内容纲要
12讲 自己写库--构建库函数
12讲自己写库,外设寄存器结构体定义。
- 使用结构体来实现对寄存器地址的偏移。
#define GPIOF ((GPIO_TypeDefine *)GPIOF_BASE)
宏定义:通过将GPIOF_BASE的地址强制类型转换为GPIO_TypeDefine 的指针,来实现寄存器地址偏移。
typedef unsigned short int uint_16_t;
typedef 定义:unsigned short int
就是short类型,只是编译器不同,这里需要这么写。。我C++了解得稍微比C语言多一点。。。
typedef 和 #define 的区别
led_register.h
#ifndef _STM32F4XX_H
#define _STM32F4XX_H
#define RCC_BASE (unsigned int)0x40023800
#define GPIOF_BASE (unsigned int)0x40021400
#define RCC_AHB1ENR *(unsigned int *)(RCC_BASE + 0x30)
//#define GPIOF_MODER *(unsigned int *)(GPIOF_BASE + 0X00)
//#define GPIOF_OTYPE *(unsigned int *)(GPIOF_BASE + 0x04)
//#define GPIOF_ODR *(unsigned int *)(GPIOF_BASE + 0X14)
//#define GPIOF_BSRR *(unsigned int *)(GPIOF_BASE + 0x18)
//#define RCC_BASE 0x40023800
//#define RCC_AHB1ENR *(unsigned int *)(RCC_BASE + 0x30)
//#define GPIOF_BASE 0x40021400
typedef unsigned int uint_32_t;
typedef unsigned short int uint_16_t;
//定义结构体,结构体中划的一块连续的内存,可以通过指针访问结构体对象来实现寄存器的偏移
typedef struct
{
uint_32_t MODER;
uint_32_t OTYPER;
uint_32_t OSPEEDR;
uint_32_t PUPDR;
uint_32_t IDR;
uint_32_t ODR;
uint_16_t BSRRL;
uint_16_t BSRRH;
uint_32_t LCKR;
uint_32_t AFRL;
uint_32_t AFRH;
}GPIO_TypeDefine;
//通过将GPIOF_BASE的地址强制类型转换为GPIO_TypeDefine 的指针,来实现寄存器地址偏移。
#define GPIOF ((GPIO_TypeDefine *)GPIOF_BASE) //这里的宏定义出来的结果,就把`GPIOF` 当成指针用
struct GPIO
{
int name;
};
#endif
main.c
#include "led_register.h"
void delay(unsigned int count)
{
while(count != 0)
{
count--;
}
}
int main()
{
while(1){
//点亮PF8
//1.开启RCC时钟。
RCC_AHB1ENR |= (1<<5);
//2.配置GPIO端口模式。
GPIOF->MODER &= ~(0X11<<2*6);
GPIOF->MODER |= (0X01<<2*6);
GPIOF->MODER &= ~(0X11<<2*7);
GPIOF->MODER |= (0X01<<2*7);
GPIOF->MODER &= ~(0X11<<2*8);
GPIOF->MODER |= (0X01<<2*8);
while(1){
//3.配置ODR 将GPIOF8 端口配置为低电平
GPIOF->ODR &= ~(1<<6);
delay(0x0fffff);
GPIOF->ODR |= (1<<6);
delay(0x0fffff);
GPIOF->ODR &= ~(1<<7);
delay(0x0fffff);
GPIOF->ODR |= (1<<7);
delay(0x0fffff);
GPIOF->ODR &= ~(1<<8);
delay(0x0fffff);
GPIOF->ODR |= (1<<8);
delay(0x0fffff);
}
}
return 0;
}
void SystemInit()
{
}
13讲 编写复位置位函数 BSRR
stm32f4xx_gpio.c
stm32f4xx_gpio.h
led_register.h
- 看笔记上方的代码,并无变动。
main.c
//野火源码
#include "stm32f4xx_gpio.h"
/**
*函数功能:设置引脚为高电平
*参数说明:GPIOx,该参数为GPIO_TypeDef类型的指针,指向GPIO端口的地址
* GPIO_Pin:选择要设置的GPIO端口引脚,可输入宏GPIO_Pin_0-15,
* 表示GPIOx端口的0-15号引脚。
*/
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/*设置GPIOx端口BSRRL寄存器的第GPIO_Pin位,使其输出高电平*/
/*因为BSRR寄存器写0不影响,
GPIO_Pin只是对应位为1,其它位均为0,所以可以直接赋值*/
GPIOx->BSRRL = GPIO_Pin;
}
/**
*函数功能:设置引脚为低电平
*参数说明:GPIOx,该参数为GPIO_TypeDef类型的指针,指向GPIO端口的地址
* GPIO_Pin:选择要设置的GPIO端口引脚,可输入宏GPIO_Pin_0-15,
* 表示GPIOx端口的0-15号引脚。
*/
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/*设置GPIOx端口BSRRH寄存器的第GPIO_Pin位,使其输出低电平*/
/*因为BSRR寄存器写0不影响,
GPIO_Pin只是对应位为1,其它位均为0,所以可以直接赋值*/
GPIOx->BSRRH = GPIO_Pin;
}
/**
*函数功能:初始化引脚模式
*参数说明:GPIOx,该参数为GPIO_TypeDef类型的指针,指向GPIO端口的地址
* GPIO_InitTypeDef:GPIO_InitTypeDef结构体指针,指向初始化变量
*/
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
/*-- GPIO Mode Configuration --*/
for (pinpos = 0x00; pinpos < 16; pinpos++)
{
/*以下运算是为了通过 GPIO_InitStruct->GPIO_Pin 算出引脚号0-15*/
/*经过运算后pos的pinpos位为1,其余为0,与GPIO_Pin_x宏对应。pinpos变量每次循环加1,*/
pos = ((uint32_t)0x01) << pinpos;
/* pos与GPIO_InitStruct->GPIO_Pin做 & 运算,若运算结果currentpin == pos,
则表示GPIO_InitStruct->GPIO_Pin的pinpos位也为1,
从而可知pinpos就是GPIO_InitStruct->GPIO_Pin对应的引脚号:0-15*/
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
/*currentpin == pos时执行初始化*/
if (currentpin == pos)
{
/*GPIOx端口,MODER寄存器的GPIO_InitStruct->GPIO_Pin对应的引脚,MODER位清空*/
GPIOx->MODER &= ~(3 << (2 *pinpos));
/*GPIOx端口,MODER寄存器的GPIO_Pin引脚,MODER位设置"输入/输出/复用输出/模拟"模式*/
GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (2 *pinpos));
/*GPIOx端口,PUPDR寄存器的GPIO_Pin引脚,PUPDR位清空*/
GPIOx->PUPDR &= ~(3 << ((2 *pinpos)));
/*GPIOx端口,PUPDR寄存器的GPIO_Pin引脚,PUPDR位设置"上/下拉"模式*/
GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (2 *pinpos));
/*若模式为"输出/复用输出"模式,则设置速度与输出类型*/
if ((GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT) || (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF))
{
/*GPIOx端口,OSPEEDR寄存器的GPIO_Pin引脚,OSPEEDR位清空*/
GPIOx->OSPEEDR &= ~(3 << (2 *pinpos));
/*GPIOx端口,OSPEEDR寄存器的GPIO_Pin引脚,OSPEEDR位设置输出速度*/
GPIOx->OSPEEDR |= ((uint32_t)(GPIO_InitStruct->GPIO_Speed) << (2 *pinpos));
/*GPIOx端口,OTYPER寄存器的GPIO_Pin引脚,OTYPER位清空*/
GPIOx->OTYPER &= ~(1 << (pinpos)) ;
/*GPIOx端口,OTYPER位寄存器的GPIO_Pin引脚,OTYPER位设置"推挽/开漏"输出类型*/
GPIOx->OTYPER |= (uint16_t)(((uint16_t)GPIO_InitStruct->GPIO_OType) << (pinpos));
}
}
}
}
/*********************************************END OF FILE**********************/
个人总结,
stmref4xx_gpio.h 中写的结构体主要作用是保存寄存器需要输出的值。结构体中变量的类型使用枚举类型,可以限定其配置的参数。