上上周实验室学长学姐出题考察我们对STM32的掌握程度,题目是实现用矩阵键盘控制数码管输出。因为关系到自己在嵌入式小组的去留问题(学姐就那么一说,我们也就那么一听?,不管怎么样我们都很认真,因为学到就是自己的?),所以分外认真(最后考核阶段很水,虽然自己在考核之前就做完了?)。数码管显示原理
矩阵键盘是好久以前小组的另一项考核项目,当时学长要求的是:第一,会焊矩阵键盘;第二,写出矩阵键盘的代码,实现通过按下不同按键单片机都会串口发送相应信息的功能。
因为有了上次矩阵键盘的经验、现成的硬件(上次焊好的矩阵键盘)和代码。这次我们显得从容了许多,说好的周日考核,不到周五我们绝对不提关于考核的东西?,到了周六我们才会慌的一批。。。。。。
下面聊聊自己设计程序的思路:
本次的数码管输出实验考核主要是通过按下矩阵键盘上不同的按键通过数码管反馈给用户不同的结果(不同的数字图案),因为是与矩阵键盘结合所以我就在上次的矩阵键盘输出实验代码的基础上编写了矩阵键盘控制数码管输出的代码。实测还是可以达到自己预期效果的。
第一步,将数码管的各个引脚与单片机上的相应引脚连接。在这里我使用的是共阴极方案,将数码管的A、B、C、D、E、F、G引脚分别接到PA1、2、3、4、5、6、7引脚上,因为没用到数码管上的小数点位,所以将其搁置。
第二步,将0~9的图案在数码管上的显示编写出来:(此处“K”为数码管要显示的图案)
switch(k)
{
case 0:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF3F;
break;
}
case 1:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF06;
break;
}
case 2:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF5B;
break;
}
case 3:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF4F;
break;
}
case 4:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF66;
break;
}
case 5:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF6D;
break;
}
case 6:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF7D;
break;
}
case 7:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF07;
break;
}
case 8:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFFFF;
break;
}
case 9:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF6F;
break;
}
}
第三步,改变按下矩阵键盘后键盘扫描函数返回的特定值。并在main函数中接受返回值根据返回值判断下一步要进行的运算操作。并将运算后的值赋给“k”根据不同的k值,输出不同的图案。
key.c
#include "key.h"
#include "delay.h"
#include "usart.h"
void KEY_Init1(void)
{
RCC->APB2ENR|=1<<3;
JTAG_Set(SWD_ENABLE);
GPIOB->CRL&=0XFF0FFFFF;
GPIOB->CRL|=0X00800000;
GPIOB->CRL&=0XF0FFFFFF;
GPIOB->CRL|=0X08000000;
GPIOB->CRL&=0X0FFFFFFF;
GPIOB->CRL|=0X80000000;
GPIOB->CRH&=0XFFFFFFF0;
GPIOB->CRH|=0X00000003;
GPIOB->ODR|=1<<8;
GPIOB->CRH&=0XFFFFFF0F;
GPIOB->CRH|=0X00000030;
GPIOB->ODR|=1<<9;
GPIOB->CRH&=0XFFFFF0FF;
GPIOB->CRH|=0X00000300;
GPIOB->ODR|=1<<10;
key9_Out=1;
key8_Out=1;
}
void KEY_Init2(void)
{
GPIOB->CRL&=0XFF0FFFFF;
GPIOB->CRL|=0X00300000;
GPIOB->ODR|=1<<5;
GPIOB->CRL&=0XF0FFFFFF;
GPIOB->CRL|=0X03000000;
GPIOB->ODR|=1<<6;
GPIOB->CRL&=0X0FFFFFFF;
GPIOB->CRL|=0X30000000;
GPIOB->ODR|=1<<7;
GPIOB->CRH&=0XFFFFFFF0;
GPIOB->CRH|=0X00000008;
GPIOB->CRH&=0XFFFFFF0F;
GPIOB->CRH|=0X00000080;
GPIOB->CRH&=0XFFFFF0FF;
GPIOB->CRH|=0X00000800;
key6_Out=1;
key5_Out=1;
}
u8 KEY_Scan1()
{
u8 H=0;
GPIOB->ODR&=~(1<<5);
GPIOB->ODR&=~(1<<6);
KEY_Init1();
if(key5_In==1||key6_In==1)
{
delay_ms(10);
if(key5_In==1)
H=1;
if(key6_In==1)
H=2;
return H*10;
}
else
return 0;
}
u8 KEY_Scan2()
{
u8 L=0;
GPIOB->ODR&=~(1<<8);
GPIOB->ODR&=~(1<<9);
KEY_Init2();
if(key8_In==1||key9_In==1)
{
delay_ms(10);//È¥¶¶¶¯
if(key8_In==1)
L=1;
else if(key9_In==1)
L=2;
return L;
}
else return 0;
}
u8 KEY_Out(void)
{
u8 t=0,p=1;
while((KEY_Scan1()==0||KEY_Scan2()==0))
{
t=KEY_Scan1()+KEY_Scan2();
if(t!=0)
{
if(t==11)
return KEY1H_PRES;
else if(t==12)
return KEY2H_PRES;
else if(t==21||t==22)
return 3;
}
}
}
main.c
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "smg.h"
int main(void)
{
static u8 k=0;
u8 r;
Stm32_Clock_Init(9);
delay_init(72);
LED_Init();
while(1)
{
r=KEY_Out();
printf("%d\r\n",r);
if(r==KEY2H_PRES)
{
if(k==0)
k=9;
else
k--;
}
else if(r==KEY1H_PRES)
{
if(k==9)
k=0;
else
k++;
}
else if(r==KEY3H_PRES)
k=0;
switch(k)
{
case 0:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF3F;
break;
}
case 1:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF06;
break;
}
case 2:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF5B;
break;
}
case 3:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF4F;
break;
}
case 4:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF66;
break;
}
case 5:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF6D;
break;
}
case 6:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF7D;
break;
}
case 7:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF07;
break;
}
case 8:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFFFF;
break;
}
case 9:
{
GPIOA->ODR&=0x0000;
GPIOA->ODR|=0xFF6F;
break;
}
}
}
}
简单说一下自己在编程过程中遇到的问题:
在第一次改动key.c中的函数之后KEY_Out()函数后,发现不管是否按下按键数码管上的数都会依次递增,不受外部环境(按键状态)的影响。
最后我在KEY_Out()函数中加上了判断条件“while((KEY_Scan1()==0||KEY_Scan2()==0))”如果没有按下按键则程序会不断在这个while循环中不断循环,不会返回数值给主函数。这就巧妙地解决了该项问题。
最后给出测试视频: