使用固件库点亮LED灯
1. 项目:使用固件库点亮LED灯。
2. 代码:
main.c
#include "stm32f10x.h" #include "stm32f10x_gpio.h" /*宏定义实现快速移植*/ #define LED_GPIO_PORT GPIOB #define LED_GPIO_CLK_ENABLE RCC->APB2ENR |= ((1)<<3); #define LED_G_GPIO_PIN GPIO_Pin_0 void Delay(uint32_t count) { for(;count!=0;count--); } int main(void) { //点亮绿灯 GPIO_InitTypeDef GPIO_InitStructure; LED_GPIO_CLK_ENABLE; //打开GPIOB端口时钟 GPIO_InitStructure.GPIO_Pin = LED_G_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LED_GPIO_PORT,&GPIO_InitStructure); while(1) { GPIO_SetBits(LED_GPIO_PORT, LED_G_GPIO_PIN); Delay(0xfffff); /*延时*/ GPIO_ResetBits(LED_GPIO_PORT, LED_G_GPIO_PIN); Delay(0xfffff); } } void SystemInit(void) { //函数体为空,目的是为了骗过编译器报错 }
stm32f10x.h
#ifndef __stm32f10x_h #define __stm32f10x_h //外设 peripheral #define PERIPH_BASE ((unsigned int)0x40000000) #define APB1PERIPH_BASE PERIPH_BASE #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) #define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) #define RCC_BASE (AHBPERIPH_BASE + 0x1000) #define GPIOB_BASE (APB2PERIPH_BASE + 0x0c00) #define RCC_APB2ENR *(unsigned int *)(RCC_BASE + 0x18) 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; typedef struct { uint32_t CR; uint32_t CFGR; uint32_t CIR; uint32_t APB2RSTR; uint32_t APB1RSTR; uint32_t AHBENR; uint32_t APB2ENR; uint32_t APB1ENR; uint32_t BDCR; uint32_t CSR; }RCC_TypeDef; #define GPIOB ((GPIO_TypeDef*)GPIOB_BASE) #define RCC ((RCC_TypeDef*)RCC_BASE) #endif /*__stm32f10x_h*/
stm32f10x_gpio.c
#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; /*设置引脚为低电平*/ } void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef * GPIO_InitStruct) /*GPIO外设指针,GPIO初始化结构体指针*/ { uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00; uint32_t tmpreg = 0x00, pinmask = 0x00; /*--------------------------------GPIO Mode Configuration---------------------------------------*/ currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode)&((uint32_t)0x0f); if (( ((uint32_t)GPIO_InitStruct->GPIO_Mode)&((uint32_t)0x10) )!= 0x00) /*判断GPIO_Mode的bit4是等于1,则为输出*/ { currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; /*如果为输出,则设定速率*/ } /*--------------------------------GPIO CRL Configuration---------------------------------------*/ if (((uint32_t)GPIO_InitStruct->GPIO_Pin &((uint32_t)0x00ff)) != 0x00) /*通过pin的值判断初始化低8位哪个引脚*/ { tmpreg = GPIOx->CRL; /*先备份CRL寄存器的值*/ for (pinpos = 0x00; pinpos < 0x08; pinpos++) /*0x08: 0000 1000; 循环,从pin0开始配对,找出具体的pin*/ { pos = ((uint32_t)0x01) << pinpos; /*pos的值为1,左移pinpos位*/ currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; /*令pos与输入参数GPIO_PIN作位与运算*/ if (currentpin == pos) /*若currentpin = pos,则找到使用的引脚*/ { pos = pinpos << 2; pinmask = ((uint32_t)0x0f) << pos; /*清除相同的低控制位*/ tmpreg &= ~pinmask; tmpreg |= (currentmode << pos); /*在相同位写模式配置*/ if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) /*Reset the corresponding ODR bit*/ { GPIOx->BRR = (((uint32_t)0x01) << pinpos); } else { if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) /*Set the corresponding ODR bit*/ { GPIOx->BSRR = (((uint32_t)0x01) << pinpos); } } } } GPIOx->CRL = tmpreg; } /*----------------------------------GPIO CRH Configuration---------------------------------------*/ if (GPIO_InitStruct-> GPIO_Pin > 0x00ff) { tmpreg = GPIOx-> CRH; for (pinpos = 0x00; pinpos < 0x08; pinpos++) { pos = (((uint32_t)0x01) << (pinpos + 0x08)); currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos); if (currentpin == pos) { pos = pinpos <<2; pinmask = ((uint32_t)0x0f) << pos; tmpreg &= ~pinmask; tmpreg |= (currentmode << pos); if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) { GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08)); } if(GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) { GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08)); } } } GPIOx->CRH = tmpreg; } }
stm32f10x_gpio.h
#ifndef __stm32f10x_gpio_h #define __stm32f10x_gpio_h #include "stm32f10x.h" /*GPIO引脚号定义*/ #define GPIO_Pin_0 ((uint16_t)0x0001) /*选择Pin0 (1<<0)*/ #define GPIO_Pin_1 ((uint16_t)0x0002) /*选择Pin1 (1<<1)*/ #define GPIO_Pin_2 ((uint16_t)0x0004) /*选择Pin2 (1<<2)*/ #define GPIO_Pin_3 ((uint16_t)0x0008) /*选择Pin3 (1<<3)*/ #define GPIO_Pin_4 ((uint16_t)0x0010) /*Pin4*/ #define GPIO_Pin_5 ((uint16_t)0x0020) #define GPIO_Pin_6 ((uint16_t)0x0040) #define GPIO_Pin_7 ((uint16_t)0x0080) #define GPIO_Pin_8 ((uint16_t)0x0100) #define GPIO_Pin_9 ((uint16_t)0x0200) #define GPIO_Pin_10 ((uint16_t)0x0400) #define GPIO_Pin_11 ((uint16_t)0x0800) #define GPIO_Pin_12 ((uint16_t)0x1000) #define GPIO_Pin_13 ((uint16_t)0x2000) #define GPIO_Pin_14 ((uint16_t)0x4000) #define GPIO_Pin_15 ((uint16_t)0x8000) #define GPIO_Pin_A11 ((uint16_t)0xFFFF) /*所有数据位都为1*/ /*GPIO初始化结构体*/ typedef struct { uint16_t GPIO_Pin; /*选择要配置的GPIO引脚*/ uint16_t GPIO_Speed; /*选择GPIO引脚的速率*/ uint16_t GPIO_Mode; /*选择GPIO引脚的工作模式*/ }GPIO_InitTypeDef; typedef enum { GPIO_Mode_AIN = 0x00, //模拟输入 (0000 0000)b GPIO_Mode_IN_FLOATING = 0x04, //浮空输入 (0000 0100)b GPIO_Mode_IPD = 0x28, //下拉输入 (0010 1000)b GPIO_Mode_IPU = 0x48, //上拉输入 (0100 1000)b GPIO_Mode_Out_OD = 0x14, //开漏输出 (0001 0100)b GPIO_Mode_Out_PP = 0x10, //推挽输出 (0001 0000)b GPIO_Mode_AF_OD = 0x1c, //复用开漏输出 (0001 1100)b GPIO_Mode_AF_PP = 0x18 //复用推挽输出 (0001 1000)b }GPIOMode_TypeDef; typedef enum { GPIO_Speed_10MHz = 1, //10MHz (01)b GPIO_Speed_2MHz, //2MHz (10)b GPIO_Speed_50MHz, //50MHz (11)b }GPIOSpeed_TypeDef; void GPIO_SetBits(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin); void GPIO_ResetBits(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin); void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef * GPIO_InitStruct); /*GPIO外设指针,GPIO初始化结构体指针*/ #endif /*__stm32f10x_gpio_h*/
3. 执行结果:
野火开发板指南者绿色LED灯闪亮。
参考资料:野火开发板(指南者)视频,B站搜野火即可。