当前位置:   article > 正文

STM32入门篇 9-自己写库-构建库函数雏形_stm32 库函数的编写

stm32 库函数的编写

语言只是工具
总线->外设->端口
GPIO端口->IO端口

1.寄存器结构体定义:

库函数

#define PERIPH_BASE 			  ((unsigned int )0x40000000)
#define APB1_PERIPH_BASE    PERIPH_BASE	 		
#define APB2_PERIPH_BASE    (PERIPH_BASE + 0x10000)
#define AHB_PERIPH_BASE 		(APB2_PERIPH_BASE + 0x10000)

#define RCC_BASE 						(AHB_PERIPH_BASE + 0x1000)
#define GPIOA_BASE					(APB2_PERIPH_BASE + 0x0800
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;

#define GPIOA ((GPIO_TypeDef*)GPIOA_BASE)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

封装成结构体 节约编码时间 简化逻辑

main.c

	//打开GPIOA端口的时钟
	RCC_APB2ENR |= ( (1) << 2); 
	//配置 IO口 为输出
	GPIOA->CRH	|= ( (1) << (4*0) ); 
	//控制 ODR 寄存器
	GPIOA->ODR &= ~(1<<7);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.编写端口复位置位函数

防止多次调用头文件时重复定义
区别用户定义的宏

#ifndef _STM32F10X_GPIO_H
#define _STM32F10X_GPIO_H

#endif /*_STM32F10X_GPIO_H*/
  • 1
  • 2
  • 3
  • 4

// stm32f10x_gpio.c
#include "stm32f10x_gpio.h"
#include "stm32f10x.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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

// stm32f10x_gpio.h
#ifndef _STM32F10X_GPIO_H
#define _STM32F10X_GPIO_H

#include "stm32f10x.h"

//GPIO 引脚定义
#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< 选择Pin0*/ //(00000000 00000001)a
#define GPIO_Pin_1 ((uint16_t)0x0002)/*!< 选择Pin1*/ //(00000000 00000010)a
#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< 选择Pin2*/ //(00000000 00000100)a
#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< 选择Pin3*/ //(00000000 00001000)a
#define GPIO_Pin_4 ((uint16_t)0x00010) /*!< 选择Pin4*/ //(00000000 00010000)a
#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< 选择Pin5*/ //(00000000 00100000)a
#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< 选择Pin6*/ //(00000000 01000000)a
#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< 选择Pin7*/ //(00000000 10000000)a

#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< 选择Pin8*/ //(00000000 00000001)a
#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< 选择Pin9*/ //(00000010 00000000)a
#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< 选择Pin10*/ //(00000100 00000000)a
#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< 选择Pin11*/ //(00001000 00000000)a
#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< 选择Pin12*/ //(00010000 00000000)a
#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< 选择Pin13*/ //(00100000 00000000)a
#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< 选择Pin14*/ //(01000000 00000000)a
#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< 选择Pin15*/ //(10000000 00000000)a
#define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< 选择全部引脚*/ //(11111111 11111111)a

void GPIO_SetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin);

#endif /*_STM32F10X_GPIO_H*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
// main.c
#elif 1
	GPIOA->ODR &= ~(1<<7);
		//打开GPIOA端口的时钟
	RCC->APB2ENR |= ( (1) << 2); 
	//配置 IO口 为输出
	GPIOA->CRH	|= ( (1) << (4*0) ); 

	GPIO_SetBits(GPIOA,GPIO_Pin_8);
	//GPIO_ResetBits(GPIOA,GPIO_Pin_8);
	
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

3.编写GPIO初始化结构体和初始化函数

在这里插入图片描述

寄存器中左移一位相当于乘以2

main.c

	GPIO_InitTypeDef GPIO_InitStructure;
	RCC->APB2ENR |= ( (1) << 2); 
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	//传入两个参数 GPIO端口 配置引脚
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	

	GPIO_SetBits(GPIOA,GPIO_Pin_8);
	//GPIO_ResetBits(GPIOA,GPIO_Pin_8);	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

stm32f10x_gpio.h
配置GPIO结构体

typedef struct
{
	uint16_t GPIO_Pin;
	uint16_t GPIO_Speed;
	uint16_t GPIO_Mode;
}GPIO_InitTypeDef;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

官方固件库 GPIO配置函数
stm32f10x_gpio.c

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
	//用于中间运算暂存数据
  uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
  uint32_t tmpreg = 0x00, pinmask = 0x00;
  /* Check the parameters */
//  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
//  assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
//  assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));  
  
/*---------------------------- GPIO Mode Configuration -----------------------*/
/*---------------------------- GPIO 模式配置 -----------------------*/
	//把输入参数GPIO_Mode的低四位暂存在currentmode
  currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
	
	//bit 是1代表输入
	//bit 是0代表输出
  //判断bit4是1还是0,即首选判断是输入还是输出模式
  if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
  { 
    /* Check the parameters */
    //assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
    /* Output mode */
		//输出模式则要设置输出速率
    currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
  }
/*---------------------------- GPIO CRL Configuration ------------------------*/
  /* Configure the eight low port pins */
	/*——————————GPIO CRL寄存器 控制着低8位I/O口——————————————*/
	//配置端口低8位 即Pin0-Pin7
  if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
  {
		//首先备份CRL寄存器的值
    tmpreg = GPIOx->CRL;
		
		//循环 从Pin0开始配对找出具体的Pin值
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
    {
			//pos的值为一 左移pinpos位
      pos = ((uint32_t)0x01) << pinpos;
      /* Get the port pins position */
			
      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
			//找到使用引脚
      if (currentpin == pos)
      {
				
				//pinpos左移两位(乘以4),寄存器中4个寄存器位控制一个引脚
        pos = pinpos << 2;
				
        /* Clear the corresponding low control register bits */
				//把控制这个引脚的寄存器清零,其他的寄存器位不变
        pinmask = ((uint32_t)0x0F) << pos;
        tmpreg &= ~pinmask;
				
        /* Write the mode configuration in the corresponding bits */
				//向寄存器写入将要配置的引脚的模式
        tmpreg |= (currentmode << pos);
				
        /* Reset the corresponding ODR bit */
				//判断是否为下拉输出
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
        {
					//下拉输出模式,默认为1,对BRR寄存器写1可对引脚置0
          GPIOx->BRR = (((uint32_t)0x01) << pinpos);
        }
        else
        {
          /* Set the corresponding ODR bit */
          if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
          {
            GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
          }
        }
      }
    }
    GPIOx->CRL = tmpreg;
  }
/*---------------------------- GPIO CRH Configuration ------------------------*/
  /* Configure the eight high port pins */
  if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
  {
    tmpreg = GPIOx->CRH;
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
    {
      pos = (((uint32_t)0x01) << (pinpos + 0x08));
      /* Get the port pins position */
      currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
      if (currentpin == pos)
      {
        pos = pinpos << 2;
        /* Clear the corresponding high control register bits */
        pinmask = ((uint32_t)0x0F) << pos;
        tmpreg &= ~pinmask;
        /* Write the mode configuration in the corresponding bits */
        tmpreg |= (currentmode << pos);
        /* Reset the corresponding ODR bit */
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
        {
          GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
        }
        /* Set the corresponding ODR bit */
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
        {
          GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
        }
      }
    }
    GPIOx->CRH = tmpreg;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111

4.如何提高程序的可移植性

#define LED_G_GPIO_PORT						GPIOA
#define LED_G_GPIO_CLK_ENABLE			(RCC->APB2ENR |= ( (1) << 2)); 
#define LED_G_GPIO_PIN						GPIO_Pin_8

  • 1
  • 2
  • 3
  • 4
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/309621
推荐阅读
相关标签
  

闽ICP备14008679号