#define LED0 PBout(5)// PB5 #define LED1 PEout(5)// PE5 void LED_Init(void);//初始化 //蜂鸣器端口定义 #define BEEP PBout(8) // BEEP,蜂鸣器接口 void BEEP_Init(void); //初始化 #define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//阅读按钮0 #define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//阅读按钮1 #define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//阅读按钮3(WK_UP) #define KEY0_PRES 1 //KEY0按下 #define KEY1_PRES 2 //KEY1按下 #define WKUP_PRES 3 //KEY_UP按下(即WK_UP/KEY_UP) void KEY_Init(void);//IO初始化 u8 KEY_Scan(u8); //按键扫描函数 //LED灯 void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB.5 GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出 GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高 } //蜂鸣器 void BEEP_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //BEEP-->PB.8 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度为50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //根据参数初始化GPIOB.8 GPIO_ResetBits(GPIOB,GPIO_Pin_8);//输出0,关闭蜂鸣器输出 } //按钮初始化函数 void KEY_Init(void) //IO初始化 { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_3;//KEY0-KEY1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置上拉输入 GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE4,3 //初始化 WK_UP-->GPIOA.0 下拉输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0 } //按键处理函数 //返回按键值 //mode:0.不支持连续按压;1.支持连续按压; //0,没有按钮 //1,KEY0按下 //2,KEY1按下 //3,KEY3按下 WK_UP //注意这个函数有响应优先级,KEY0>KEY1>KEY_UP!! u8 KEY_Scan(u8 mode) { static u8 key_up=1.//按键松开标志 if(mode)key_up=1; //支持连按 if(key_up&&(KEY0==0||KEY1==0||WK_UP==1)) { delay_ms(10) key_up=0; if(KEY0==0)return KEY0_PRES; else if(KEY1==0)return KEY1_PRES; else if(WK_UP==1)return WKUP_PRES; }else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1; return 0;// 无按键按下 }
写在前面:IO口寄存器只能用32位字访问
以上代码需要说明的几个地方(以上)LED以灯为例):
GPIO_InitTypeDef GPIO_InitStructure; 应该是每一个功能都有一个类似于这样的结构体,后面要讲到的串口、AD设置中使用类似的结构。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); 时钟的使能,你的硬件挂在哪条总线上,你可以使用哪个总线时钟。APB1(低速)和APB2(高速)
APB1:DAC CAN2 CAN1 I2C2 I2C1 UART2~5 SP1 3
APB2:USART1 SPI 1 TIM1 ADC2 ADC1 IOA~E IO复位
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
重难点:IO八种输入输出模式
输入模式
输入浮空(GPIO_Mode_IN_FLOATING):浮空是指逻辑器件和引脚不接高电平或低电平。相当于引脚接高电平。一般实际使用时,不建议引脚悬挂,容易干扰。一般来说,浮空就是浮在空中,相当于这个端口在默认情况下什么都不接,呈高阻态,在数据传输中使用较多。浮空最大的特点是电压的不确定性,可能是0V,可能是VCC,也可能是两者之间的一个值(最有可能) 浮空通常用于制造这样可以减少上下拉电阻对结果的影响
输入上拉(GPIO_Mode_IPU):上拉就是把点拉高,比如拉到Vcc。上拉就是电阻同时起到限流作用。弱强度只是上拉电阻的电阻值不同,没有严格区分
输入下拉(GPIO_Mode_IPD):拉下电压,拉到GND。
模拟输入(GPIO_Mode_AIN):模拟输入是指传统的输入方式,数字输入是输入PCM数字信号,即0、1的二进制数字信号,通过数模转换转换为模拟信号,通过前级放大进入功率放大器,或模拟功率放大器。
输出模式
-开漏输出(GPIO_Mode_Out_OD):
-开漏复用功能(GPIO_Mode_AF_OD):可以理解为GPIO当口被用作第二个功能时(即不是通用)的配置IO使用口)。端口必须配置为复用功能输出模式(推拉或泄漏)。
-推挽式输出(GPIO_Mode_Out_PP):它可以输出高、低电平和连接数字设备;推拉结构一般是指两个三级管分别受到互补信号的控制,总是在一个三极管导通时的另一个截止日期。高低电平由IC低电源。
-推挽式复用功能(GPIO_Mode_AF_PP):可以理解为GPIO当口被用作第二个功能时(不是通用)的配置IO使用)、
定时器的引脚配置、串口的引脚配置、SPI、I2S、I2C、CAN、USB、ADC/DAC的引脚配置,在中文参考手册的第八小节都有写
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
typedef enum { GPIO_Speed_10MHz = 1, GPIO_Speed_2MHz, GPIO_Speed_50MHz }GPIOSpeed_TypeDef;