STM32f103精英版之用寄存器实现按键控制led流水灯的流向
1.前言
2020.11.29,用正点原子的STM32f103精英版做寄存器
实现按键控制led流水灯的流向的实验,遇到很多坑,还是写一下缓解我这想哭的心情。
2.环境+stm32f103ZET6精英版用到的引脚介绍
MDK
正点原子stm32f103zet6,
led灯---PE5 和PB5 是两个led灯 -->低电平有效
key0 -- PE4 -->低电平有效
3.遇到的问题
1.key0的模式设置不对到底用那个模式
2.led就两个,怎么看到底是那个流向是什么
3.u8 变量 导致一些低级问题。
4.按键到底是不是生效了,什么时机按下。
4.全部代码(测试调通代码,还没优化)
例如:按键消抖我都还没+。
/*
按键控制灯的循环闪烁
ke0 --pe4--低电平有效
key1 --pe3
BSRR - RESET set
BRR - 保留 RESET
ODR - 保留 对应输出。
//模式设置寄存器。
CRL 低位0-7
CRH
*/
#include "stm32f10x.h"
//#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n)
void Key_Init(void);
int key_Scan(void);
void delay_nms(u16 time); //毫秒延时。
int main(void){
u8 inputDataBit=1;
int flag=-1;
//开启GPIO时钟
RCC->APB2ENR |=1<<3;//开启 GPIOB
RCC->APB2ENR |=1<<6;//开启 GPIOE
//先清零PIN5
GPIOB->CRL &=0xff0fffff;
GPIOE->CRL &=0xff0fffff;
//设置pin5的输出模式--复用推挽输出 50MHz
GPIOB->CRL |=0x00300000;
GPIOE->CRL |=0X00300000;
//按键设置成输入模式---1000 --8;
Key_Init();
//这是置 PE5,PB5 为高电平。
GPIOE->ODR|=1<<5;
GPIOB->ODR|=1<<5;
//GPIOE->ODR|=0xffdf; --这样不对呀。 或上一个0 就相当于没有操作呀。
//GPIOE->BRR|=0x0020;
//GPIOB->ODR=~(1<<5);
while(1){
if(key_Scan()){
flag=!flag;
}
/*
delay_nms(10);
if(inputDataBit==1){
while(inputDataBit);
//这里表示按下一次,
flag=!flag;
}
*/
//也就说,这里的逻辑对了,
if(flag==1){
//快速
GPIOE->ODR|=1<<5;
GPIOB->ODR=~(1<<5);
delay_nms(100);
GPIOB->ODR|=1<<5;
GPIOE->BRR|=0x0020;
delay_nms(100);
}else if(flag==-1){
//这是从绿到蓝。 慢速。
GPIOB->ODR|=1<<5;
GPIOE->BRR|=0x0020;
delay_nms(500);
GPIOE->ODR|=1<<5;
GPIOB->ODR=~(1<<5);
delay_nms(500);
}
}
}
int key_Scan(void){
//按下了,我们就返回一个1.
if(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)){
return 1;
} else{
return 0;
}
}
void delay_nms(u16 time) //延时子程序
{
u16 i=0;
while(time--){
i=12000;
while(i--);
}
}
void Key_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
//开启GPIOE 的时钟
RCC->APB2ENR |=1<<6;
//设置PE4/3 为输出,默认下拉
GPIOE->CRL&=0xfff0ffff;//PE4; -->
GPIOE->CRL|=0x00040000; //--> 设置为浮空输入。
}
5.问题分析
1.key0的模式设置不对到底用那个模式
看最后:开始我是使用GPIOE->CRL|=0x00080000; 设置为上拉/下拉输入,**具体是上拉下拉,还得看PxODR寄存器的状态。**所以还是又改成浮空输入:
对这两个进行区分:
自己理解。
网上: https://www.21ic.com/app/mcu/201808/780648.htm
所以这里做按键的时候,应该选择浮空输入。
//
void Key_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
//开启GPIOE 的时钟
RCC->APB2ENR |=1<<6;
//设置PE4/3 为输出,默认下拉
GPIOE->CRL&=0xfff0ffff;//PE4; -->
//看这里1。
GPIOE->CRL|=0x00040000; //--> 设置为浮空输入。
}
2.led就两个,怎么看到底是那个流向是什么
本来就两个led 很容易看不明白。所以
选择两种状态切换频率。(用时间来控制,)
if(flag==1){
//快速
GPIOE->ODR|=1<<5;
GPIOB->ODR=~(1<<5);
delay_nms(100);
GPIOB->ODR|=1<<5;
GPIOE->BRR|=0x0020;
delay_nms(100);
}else if(flag==-1){
//这是从绿到蓝。 慢速。
GPIOB->ODR|=1<<5;
GPIOE->BRR|=0x0020;
delay_nms(500);
GPIOE->ODR|=1<<5;
GPIOB->ODR=~(1<<5);
delay_nms(500);
}
3.u8 变量 导致一些低级问题。
unsigned 是无符号的,记得不要有 -1,之类的 例如 led = !led 这是错的 。
4.按键到底是不是生效了,什么时机按下。
这个问题也是大问题,因为采用查询的方法,所以一定要在key_Scan()指令执行之前进行按下。
6.存在问题:
1.还是不能从高频率变回来。