其实这个小实验就是学会运用GPIO这个外设。
GPIO是一个片上高速外设,它是由几个寄存器来控制的,每个寄存器占据0x04:
GPIOx_BSSR:
端口位设置/清除寄存器,这个寄存器的BSy位是0-15位(BS0-BS15),BRy位是16-31位(BR0-BR15);通过这两个位可以控制16个引脚;BSy只写,写0对ODRy无作用,写1置ODRy位1;BRy只写,写0对ODRy无作用,写1清除ODRy为0;如若两个位同时设置,BSy位起作用。
GPIOx_CRL/CRH:
端口配置低/高寄存器,用到了两个寄存器来配置16个引脚,每个引脚由低位开始按顺序每四个位控制一个引脚;MODEy[1:0],这两位00表示输入模式;01为输出模式,最大速度10MHz;10为输出模式,最大速度为2MHz;11为输出模式,最大速度位50MHz;CNFy[1:0],在输入/输出模式,这两位就可以配置四种不同的输入/输出模式。
GPIOx_IDR:
端口输入数据寄存器,IDRy[0:15](16-31位保留),这些位只能以字(16位)的形式的只读,读出的值就是对应引脚的状态。
GPIOx_ODR:
端口输出数据寄存器, IDRy[0:15](16-31位保留),这些位能以字(16位)的形式的读写,读出的值就是对应引脚的状态。
GPIOx_BRR:
端口位清除寄存器,BRy[0:15](16-31位保留),这些位只能以字(16位)的形式的只写,写0对相应的ODRy无作用,写1对对应的ODRy为0。
GPIOx_LCKR:
端口配置锁定寄存器,LCKK[16],改位可随时读出,但只可以通过锁键写入序列来修改,写0锁键位激活;写1,锁键位激活,下次复位前该寄存器被锁住;
LCKy[0:15],每个锁定位锁定CRL/CRH对应的四个位,这些锁定位可读,在锁键位为0时写入;写0不锁定端口的配置;写1锁定端口的配置。
用单片机点亮一个LED灯,可以通过寄存器,也可以通过库函数;
下面是寄存器版本:
#include"stm32f10x.h" #define PERIPH_BASE1 ((unsigned int)0x40000000) /*APB2 总线基地址 */ #define APB2PERIPH_BASE1 (PERIPH_BASE1 + 0x10000) /* AHB总线基地址 */ #define AHBPERIPH_BASE1 (PERIPH_BASE1 + 0x20000) /*GPIOB外设基地址*/ #define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) /* GPIOB寄存器地址,强制转换成指针 */ #define GPIOB_CRL *(unsigned int*)(GPIOB_BASE+0x00) #define GPIOB_CRH *(unsigned int*)(GPIOB_BASE+0x04) #define GPIOB_IDR *(unsigned int*)(GPIOB_BASE+0x08) #define GPIOB_ODR *(unsigned int*)(GPIOB_BASE+0x0C) #define GPIOB_BSRR *(unsigned int*)(GPIOB_BASE+0x10) #define GPIOB_BRR *(unsigned int*)(GPIOB_BASE+0x14) #define GPIOB_LCKR *(unsigned int*)(GPIOB_BASE+0x18) /*RCC外设基地址*/ #define RCC_BASE (AHBPERIPH_BASE + 0x1000) /*RCC的AHB1时钟使能寄存器地址,强制转换成指针*/ #define RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18) int main() { RCC_APB2ENR |=(1<<3);//开启GPIOB的时钟 GPIOB_CRL&=~(0x0F<<(4*0));//清零PB0的控制位 GPIOB_CRL|=(1<<(4*0));//配置PB0的控制位 GPIOB_ODR&=~(1<0);//PB0输出低电平 while(1); }
下面是库函数版本的bsp_led.h文件:
#ifndef __LED_H #define __LED_H #include"stm32f10x.h" //定义端口,时钟,引脚 #define red_PORT GPIOB #define red_PIN GPIO_Pin_5 #define red_LCK RCC_APB2Periph_GPIOB #define green_PORT GPIOB #define green_PIN GPIO_Pin_0 #define green_LCK RCC_APB2Periph_GPIOB #define blue_PORT GPIOB #define blue_PIN GPIO_Pin_1 #define blue_LCK RCC_APB2Periph_GPIOB #define ON 0//低电平点亮led #define OFF 1 //定义7种颜色的显示 #define red(a) if(a) GPIO_SetBits(red_PORT,red_PIN);\ else GPIO_ResetBits(red_PORT,red_PIN) #define green(a) if(a) GPIO_SetBits(green_PORT,green_PIN);\ else GPIO_ResetBits(green_PORT,green_PIN) #define blue(a) if(a) GPIO_SetBits(blue_PORT,blue_PIN);\ else GPIO_ResetBits(blue_PORT,blue_PIN) #define yellow red(ON);green(ON);blue(OFF) #define purple red(ON);green(OFF);blue(ON) #define cyan red(OFF);green(ON);blue(ON) #define white red(ON);green(ON);blue(ON) void LED_GPIO_Config(void); #endif
下面是bsp_led.c文件:
#include "bsp_led.h" void LED_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO结构体 RCC_APB2PeriphClockCmd(red_LCK|green_LCK|blue_LCK,ENABLE);//使能外设时钟 GPIO_InitStructure.GPIO_Pin=red_PIN;//配置引脚,模式,速度 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(red_PORT,&GPIO_InitStructure);//初始化配置 GPIO_InitStructure.GPIO_Pin=green_PIN; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(green_PORT,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=blue_PIN; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(blue_PORT,&GPIO_InitStructure); red(OFF); green(OFF); blue(OFF); }
下面是main.c:
#include"stm32f10x.h" #include"bsp_led.h" int main(void) { LED_GPIO_Config(); while(1) { red(ON); } }
以上代码能正常运行的前提是已经搭建好你自己的程序基础框架。