对于上一个实验流水灯来说,这一次的实验是获取输入的一个小demo。
在课堂上,看老师调试的时候,只要有输入则输入寄存器IDR的值就会改变,所以想要获得输入只需要循环去获取IDR的值即可。在stm32的库中有一个读取输入信息的函数:
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 参数一是端口,参数二是针脚。返回值是十六进制的值(0x00或0x01),这个值可以直接与十进制的0或1比较。
有了这个之后就可以像上次的实验一样,先开启设备时钟,然后再设置引脚模式,最后调用这个函数读取信息即可。
1.按键电路原理图
由图中可以知道A端口的0号引脚为k1,C端口的13号引脚为k2。所以下一步要做的是读取A端口的0号引脚先试试能不能读取到信息。
2.源代码
#include "stm32f10x.h"
GPIO_InitTypeDef GPIO_InitStructure;
int K1=0,K2=0;
void Delay(__IO uint32_t nCount) //ÑÓ³Ù£¬²ÎÊýÊäÈë16½øÖÆÊý£¬È磺0x0FFFFF
{
for(; nCount != 0; nCount--);
}
void init(){
//¿ªÆôB¶Ë¿ÚµÄʱÖÓ£¬B¶Ë¿Ú¿ØÖÆ×ÅLED¡£
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//ÅäÖÃÒý½Åģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_5|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//³õʼ»¯B¶Ë¿Ú
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_5|GPIO_Pin_1);
//open keyboard port pa0(k1) and pc13(k2)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//red light
#define Led1(on) if(on){GPIO_SetBits(GPIOB,GPIO_Pin_5);}else{GPIO_ResetBits(GPIOB,GPIO_Pin_5);}
//green light
#define Led2(on) if(on){GPIO_SetBits(GPIOB,GPIO_Pin_0);}else{GPIO_ResetBits(GPIOB,GPIO_Pin_0);}
//blue light
#define Led3(on) if(on){GPIO_SetBits(GPIOB,GPIO_Pin_1);}else{GPIO_ResetBits(GPIOB,GPIO_Pin_1);}
//white light
#define Led(on) if(on){GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_5|GPIO_Pin_1);}else{GPIO_ResetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_5|GPIO_Pin_1);}
void readStatus(){
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)){
K1=1;
}
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13)){
K2=1;
}
}
int main(void)
{
init();
while(1){
readStatus();
if(K1==1){
Led1(0);
Led2(1);
}else{
Led2(0);
Led1(1);
}
}
}
上面的代码就是不停的检测k1键是否被按下,如果被按下就选择打开Led灯1(红灯)。通过观察上面的代码可以发现,我们只能检测一次k1键是否被按下,被按下之后就无法检测状态了,或者说上面的代码认为只要k1键被按过,就认为k1键一直被按着。所以我需要把代码改一改。
修改后的代码:
#include "stm32f10x.h"
GPIO_InitTypeDef GPIO_InitStructure;
int K1_Press=0,K2_Press=0;
int K1_Up=0,K2_Up=0;
int K1_Press_Up=0,K2_Press_Up=0;
void Delay(__IO uint32_t nCount) //ÑÓ³Ù£¬²ÎÊýÊäÈë16½øÖÆÊý£¬È磺0x0FFFFF
{
for(; nCount != 0; nCount--);
}
void init(){
//¿ªÆôB¶Ë¿ÚµÄʱÖÓ£¬B¶Ë¿Ú¿ØÖÆ×ÅLED¡£
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//ÅäÖÃÒý½Åģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_5|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//³õʼ»¯B¶Ë¿Ú
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_5|GPIO_Pin_1);
//open keyboard port pa0(k1) and pc13(k2)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//red light
#define Led1(on) if(on){GPIO_SetBits(GPIOB,GPIO_Pin_5);}else{GPIO_ResetBits(GPIOB,GPIO_Pin_5);}
//green light
#define Led2(on) if(on){GPIO_SetBits(GPIOB,GPIO_Pin_0);}else{GPIO_ResetBits(GPIOB,GPIO_Pin_0);}
//blue light
#define Led3(on) if(on){GPIO_SetBits(GPIOB,GPIO_Pin_1);}else{GPIO_ResetBits(GPIOB,GPIO_Pin_1);}
//white light
#define Led(on) if(on){GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_5|GPIO_Pin_1);}else{GPIO_ResetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_5|GPIO_Pin_1);}
void readStatus(){
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)){
K1_Press=1;
}else{
if(K1_Press==1){
K1_Press_Up++;
K1_Press=0;
//K1_Up=0;
}
}
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13)){
K2_Press=1;
}else{
if(K2_Press==1){
K2_Press_Up++;
K2_Press=0;
//K2_Up=0;
}
}
}
int main(void)
{
init();
while(1){
readStatus();
if(K1_Press_Up%4==0){
Led1(1);
Led2(1);
Led3(1);
}else if(K1_Press_Up%4==1){
Led1(0);
Led2(1);
Led3(1);
}else if(K1_Press_Up%4==2){
Led1(1);
Led2(0);
Led3(1);
}else{
Led1(1);
Led2(1);
Led3(0);
}
}
}
主要就是加多了一个K1_Press_Up变量用来记录按下按键并松开了多少次,因为我们把按下并且松开这一整个动作视为按下了k1,所以在引脚电平为低的时候判断是否之前有按下过就可以判断是否有过一次按压。
这一次实验主要得到k1的信息,并没有用到k2,而我根据按压了多少次来选择led是否该亮,或者该亮什么颜色。所以呢,如果再扩展一下,可以通过k2来控制灯亮的模式。
基本上输入就是这样的一个操作,下一次实验不知道可不可以开始涉及wifi模块了,关键是现在看不懂wifi模块的电路原理图,所以现在还不敢去弄wifi模块 。。。