12讲 自己写库–构建库函数
内容纲要

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 的区别

file

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

file

stm32f4xx_gpio.h

file

led_register.h

  • 看笔记上方的代码,并无变动。

main.c

file

//野火源码
#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 中写的结构体主要作用是保存寄存器需要输出的值。结构体中变量的类型使用枚举类型,可以限定其配置的参数。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇