赞
踩
STM32 的每个 IO 端口都有 7 个寄存器来控制,分别是:CRH、CHL、ODR、IDR、BSRR、BRR、LCLK,加上APB2 外设时钟使能寄存器ACC->APB2ENR就可以实现对IO口的所有操作了。不管是库函数还是HAL库究其根源都是通过控制这几个寄存器实现的。
各个寄存器功能如下:
RCC->APB2ENR|=1<<5; //使能PORTD时钟
GPIOD->CRL=GPIOD->CRL & 0XFFFFF0FF | (3<<8); //PD.2 配置为推挽输出
GPIOD->ODR=GPIOD->ODR & ~0X00000004 | (1<<2); //PD.2 输出高电平
所以对IO口的控制并不难,记住这几个寄存器就OK了。
点灯即为对IO口输出电平进行操作,正常点灯按位操作可以直接对ODR寄存器进行操作。
如:将A3置为高电平 GPIOA->ODR=GPIOA->ODR&~0X00000008 | (1<<3);
但是由于蓝桥杯开发板PC口连接了LCD和LED两种外设,所以使用了74HC573芯片对8为数据进行锁存处理。因此,单独对一个引脚直接进行操作是不方便的。所以我设置了一个LED控制函数如下所示:
void Disp_Led(uint8_t LED)
{
GPIOC->ODR=(GPIOC->ODR&0X00FF) | 0XFF00;
GPIOD->ODR=(GPIOD->ODR&~0X0004) | 0X0004;
GPIOD->ODR=(GPIOD->ODR&~0X0004) | 0X0000;
GPIOC->ODR=(GPIOC->ODR&0X00FF) | LED<<8;
GPIOD->ODR=(GPIOD->ODR&~0X0004) | 0X0004;
GPIOD->ODR=(GPIOD->ODR&~0X0004) | 0X0000;
}
对此函数10ms执行一次,需要改变哪一位就对LED进行按位操作,如:点亮第0位,熄灭第一位。
LED=LED&~0X01 | 0X01; LED=LED& ~0X02 | 0X00;
什么时候需要改就什么时候对LED进行赋值,这样就实现了LED的按位操作。
首先定义一个按键结构体如下:
struct
{
uint8_t judge_sta; //按键判断当前步骤
uint16_t key_time1; //按键按下时间
uint8_t key_time2; //双击价格时间
uint16_t key_sta; //按键状态
bool key_single; //单击标志
bool key_double; //双击标志
bool key_long; //长按标志
}Key_N[4];
打开一个10ms的定时器中断,利用中断时间进行消抖和按下时间的判断,从而避免按键影响整体代码的扫描速度。以下代码在10ms的定时器中断中
/*************按键**********************/ Key_N[0].key_sta=GPIOB->IDR &(1); //读取按键状态判断是否按下 Key_N[1].key_sta=(GPIOB->IDR &(1<<1)) >>1; //读取按键状态判断是否按下 Key_N[2].key_sta=(GPIOB->IDR &(1<<2)) >>2; //读取按键状态判断是否按下 Key_N[3].key_sta=GPIOA->IDR &(1); //读取按键状态判断是否按下 for (uint8_t i=0;i<4;i++) //循环4个按键 { switch (Key_N[i].judge_sta) //判断此时按键所处的状态 { case 0 :{if(Key_N[i].key_sta==0) Key_N[i].judge_sta=1;}break; //确认按下 case 1 :{if(Key_N[i].key_sta==0) Key_N[i].judge_sta=2;}break; //进行消抖 case 2 : //判断是否抬起 { if(Key_N[i].key_sta==1) Key_N[i].judge_sta=3; //抬起则进入下个状态 else Key_N[i].key_time1++; //没抬起则进行时间累加 }break; case 3 : //按键抬起状态 { if(Key_N[i].key_sta==0) //判断是否再次按下双击 { Key_N[i].judge_sta=4; // 进入下一个状态 } else //没有再次按下进行时间累加 { Key_N[i].key_time2++; //双击间隔时间自加 if(Key_N[i].key_time2>30) //设置双击时间间隔最大为300ms,过300ms还是没有再次按下,表明是单击或长按 {//判断按下时间是否大于1s,大于1s为长按 if(Key_N[i].key_time1>100) Key_N[i].key_long=1; else Key_N[i].key_single=1; //否则为短按 Key_N[i].key_time1=0; //按键按下时间标志清0 Key_N[i].key_time2=0; //是否双击按键时间清0 Key_N[i].judge_sta=0; //按键判断状态清0 } } }break; case 4 :{if(Key_N[i].key_sta==0) Key_N[i].judge_sta=5;}break; //双击的第二次按下消抖 case 5 : //判断第二次是否抬起 { if(Key_N[i].key_sta==1) //抬起了 { Key_N[i].key_double=1; //双击标志之一 Key_N[i].key_time1=0;//按键按下时间标志清0 Key_N[i].key_time2=0; //是否双击按键时间清0 Key_N[i].judge_sta=0; //按键判断状态清0 } }break; }
(链接:https://pan.baidu.com/s/1DbZ6YarBLwqGaJnvFC1RPg
提取码:al08)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。