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.还是不能从高频率变回来。

7.还是好好学学中断,用中断来进行控制

猜你喜欢

转载自blog.csdn.net/qq_44218805/article/details/110351601