STM32与RC522简单公交卡系统的设计
系统的结构框图目前所用到的硬件有RC522,STM32和矩阵键盘,实物图如下:
引脚连接以及相关接口设计
RC522相关的引脚在我上一篇博客已经说过,请大家点开本博客开头的链接查看,4x4的矩阵键盘相关行我们用到的引脚是PF8,9,10,11,相关列用到的引脚是PF12,13,14,15。
按键相关代码如下:
按键初始化函数void Matrix_ssKey_Pin_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;//行按键
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOF,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;//列按键
GPIO_Init(GPIOF,&GPIO_InitStructure);
} 按键扫描函数
int Matrix_Key_Scan(void)
{
u8 temp = 0;
int key_val = -1;
GPIO_ResetBits(GPIOF,GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11);
delay_us(10);
temp=(GPIO_ReadInputData(GPIOF) >> 8)&0xff;
if (temp == 0xf0)
{
delay_ms(50);
GPIO_ResetBits(GPIOF,GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11);
delay_us(10);
temp=(GPIO_ReadInputData(GPIOF) >> 8)&0xff;
if (temp != 0xf0)
{
GPIO_Write(GPIOF,0);
delay_ms(5);
GPIO_Write(GPIOF,(uint16_t)(0xFE << 8));
if(((GPIO_ReadInputData(GPIOF) >> 8) & 0XF0) != 0XF0)
{
delay_ms(20);
if(((GPIO_ReadInputData(GPIOF) >> 8) & 0XF0) != 0XF0)
{
temp=((GPIO_ReadInputData(GPIOF) >> 8) & 0XFE);
switch(temp)
{
case 0xEE:key_val = 1; break;
case 0xDE:key_val = 2; break;
case 0xBE:key_val = 3; break;
case 0x7E:key_val = 4; break;
default: key_val = -1; break;
}
}
}
GPIO_Write(GPIOF,0);
delay_ms(5);
GPIO_Write(GPIOF,(uint16_t)(0xFD << 8));
if(((GPIO_ReadInputData(GPIOF) >> 8) & 0XF0)!= 0XF0)
{
delay_ms(20);
if(((GPIO_ReadInputData(GPIOF) >> 8) & 0XF0) != 0XF0)
{
temp=((GPIO_ReadInputData(GPIOF) >> 8) & 0XFD);
switch(temp)
{
case 0xED:key_val = 5; break;
case 0xDD:key_val = 6; break;
case 0xBD:key_val = 7; break;
case 0x7D:key_val = 8; break;
default: key_val = -1; break;
}
}
}
GPIO_Write(GPIOF,0);
delay_ms(5);
GPIO_Write(GPIOF,(uint16_t)(0xFB << 8));
if(((GPIO_ReadInputData(GPIOF) >> 8) & 0XF0) != 0XF0)
{
delay_ms(20);
if(((GPIO_ReadInputData(GPIOF) >> 8) & 0XF0) != 0XF0)
{
temp=((GPIO_ReadInputData(GPIOF) >> 8) & 0XFB);
switch(temp)
{
case 0xEB:key_val = 9; break;
case 0xDB:key_val = 10; break;
case 0xBB:key_val = 11; break;
case 0x7B:key_val = 12; break;
default: key_val = -1; break;
}
}
}
GPIO_Write(GPIOF,0);
delay_ms(5);
GPIO_Write(GPIOF,(uint16_t)(0xF7 << 8));
if(((GPIO_ReadInputData(GPIOF) >> 8) & 0XF0) !=0XF0)
{
delay_ms(20);
if(((GPIO_ReadInputData(GPIOF) >> 8) & 0XF0) != 0XF0)
{
temp=((GPIO_ReadInputData(GPIOF) >> 8) & 0XF7);
switch(temp)
{
case 0xE7:key_val = 13; break;
case 0xD7:key_val = 14; break;
case 0xB7:key_val = 15; break;
case 0x77:key_val = 16; break;
default: key_val = -1; break;
}
}
}
}
}
return key_val;
} 软件流程图
调试过程
我最开始设计的功能是将卡号先写好定义在数组里面,可是这样的话就没有了发卡的功能,于是我就想到设置一个空数组,读卡的时候把卡号存进这个数组里面去。随后,我在设置个人信息的功能时遇到了麻烦,我按下一个按键之后,不需要按后面三个按键他就自动跟第一个按键一样了,于是我在代码里找原因,发现原来每一次输入按键的时候都需要重新扫描,否则按键会停留在上一次的值。 在发卡和个人信息绑定设置完成后,我又要设置挂失和解除挂失功能。这个时候我又用到了一个临时数组,用来临时存放卡号。 当输入的个人信息和相应的卡匹配时,就将卡号存放在临时数组里面。 起初我只考虑了输入正确的情况,没有考虑到输入的信息错误的情况,于是我又小改了一下函数,把if改成了else if 最后如果输入的个人信息都不匹配,则打印出密码错误。
在设计卡的扣款的功能的时候,由于要扣款小数位,最开始我没有想到很好的方法怎么去设置小数位。然后我突然想到一个办法,就是用数据的第十位作为小数位,比如数据100,则实际金额为10.0。根据这个想法,我修改了代码。 将数值块的数据除以10再强制转换为double类型,这样就实现了小数的功能了。不过这样做的坏处就是整体可用金额少了十倍。 在我本来以为功能都设计的差不多的时候,我又发现了另一个问题,那就是挂失和解除挂失功能的模块,我原先把这块函数写在了读卡成功之后。实际功能为不刷卡时无法进入挂失和解除挂失模式的函数,这与实际情况不符合,我就是因为卡掉了才要进入挂失,你现在要我刷卡,我拿什么刷?于是我就把这块函数写在了读卡之前,这样,即使不刷卡,也能进入卡的挂失和解除挂失功能,更加符合实际情况。 相关代码
挂失代码
if(WK_UP==1)//进入挂失和解除挂失模式
{
printf("\r\n进入挂失和解除挂失模式\r\n");
printf("\r\n按下S1进入挂失模式,按下S2进入解除挂失模式\r\n");
while(1)
{
key_val = Matrix_Key_Scan();
if(key_val > 0 && key_val < 17)
{
if(key_val==1)//进入挂失模式
{
printf("\r\n 进入挂失模式\r\n");
printf("\r\n 请输入4位个人信息\r\n");
while(1)
{
key_val = Matrix_Key_Scan();
if(key_val > 0 && key_val < 17)//¸个人信息第一位
{
if(key_val==1)card_3=1;
if(key_val==2)card_3=2;
if(key_val==3)card_3=3;
if(key_val==4)card_3=4;
if(key_val==5)card_3=5;
if(key_val==6)card_3=6;
if(key_val==7)card_3=7;
if(key_val==8)card_3=8;
if(key_val==9)card_3=9;
if(key_val==10)card_3=0;
printf("\r\n %d \r\n",card_3);
if(card_3==0|card_3==1|card_3==2|card_3==3|card_3==4|card_3==5|card_3==6|card_3==7|card_3==8|card_3==9)break;
}
}
delay_ms(10000);
while(1)
{
key_val = Matrix_Key_Scan();
if(key_val > 0 && key_val < 17)//个人信息第二位
{
if(key_val==1)card_3=1;
if(key_val==2)card_3=2;
if(key_val==3)card_3=3;
if(key_val==4)card_3=4;
if(key_val==5)card_3=5;
if(key_val==6)card_3=6;
if(key_val==7)card_3=7;
if(key_val==8)card_3=8;
if(key_val==9)card_3=9;
if(key_val==10)card_3=0;
printf("\r\n %d \r\n",card_3);
if(card_3==0|card_3==1|card_3==2|card_3==3|card_3==4|card_3==5|card_3==6|card_3==7|card_3==8|card_3==9)break;
}
}
delay_ms(10000);
while(1)
{
key_val = Matrix_Key_Scan();
if(key_val > 0 && key_val < 17)//个人信息第三位
{
if(key_val==1)card_3=1;
if(key_val==2)card_3=2;
if(key_val==3)card_3=3;
if(key_val==4)card_3=4;
if(key_val==5)card_3=5;
if(key_val==6)card_3=6;
if(key_val==7)card_3=7;
if(key_val==8)card_3=8;
if(key_val==9)card_3=9;
if(key_val==10)card_3=0;
printf("\r\n %d \r\n",card_3);
if(card_3==0|card_3==1|card_3==2|card_3==3|card_3==4|card_3==5|card_3==6|card_3==7|card_3==8|card_3==9)break;
}
}
delay_ms(10000);
while(1)
{
key_val = Matrix_Key_Scan();
if(key_val > 0 && key_val < 17)//个人信息第四位
{
if(key_val==1)card_3=1;
if(key_val==2)card_3=2;
if(key_val==3)card_3=3;
if(key_val==4)card_3=4;
if(key_val==5)card_3=5;
if(key_val==6)card_3=6;
if(key_val==7)card_3=7;
if(key_val==8)card_3=8;
if(key_val==9)card_3=9;
if(key_val==10)card_3=0;
printf("\r\n %d \r\n",card_3);
if(card_3==0|card_3==1|card_3==2|card_3==3|card_3==4|card_3==5|card_3==6|card_3==7|card_3==8|card_3==9)break;
}
}
delay_ms(10000);
if(((card_3==card)&&(card_3==card)&&(card_3==card)&&(card_3==card)))//如果为普通卡的信息
{//创建一个临时数组来临时保存普通卡的卡号,然后将该卡卡号初始化为0
card_4=card;card=0;
card_4=card;card=0;
card_4=card;card=0;
card_4=card;card=0;
printf("\r\n 普通卡挂失成功\r\n");
printf("\r\n 按下S16退出\r\n");
}
else if(((card_3==card)&&(card_3==card)&&(card_3==card)&&(card_3==card)))//如果为学生卡的信息
{//创建一个临时数组来临时保存学生卡的卡号,然后将该卡卡号初始化为0
card_5=card;card=0;
card_5=card;card=0;
card_5=card;card=0;
card_5=card;card=0;
printf("\r\n 学生卡挂失成功\r\n");
printf("\r\n 按下S16退出\r\n");
}
else if(((card_3==card)&&(card_3==card)&&(card_3==card)&&(card_3==card)))//如果为老年卡的信息
{//创建一个临时数组来临时保存老年卡的卡号,然后将该卡卡号初始化为0
card_6=card;card=0;
card_6=card;card=0;
card_6=card;card=0;
card_6=card;card=0;
printf("\r\n 老年卡挂失成功\r\n");
printf("\r\n 按下S16退出\r\n");
}
else
{
printf("\r\n 该信息未绑定公交卡\r\n ");
}
}
}
key_val = Matrix_Key_Scan();
if(key_val > 0 && key_val < 17)
{
if(key_val==2)//进入解除挂失模式
{
printf("\r\n 进入解除挂失模式\r\n");
printf("\r\n 请输入4为个人信息\r\n");
while(1)
{
key_val = Matrix_Key_Scan();
if(key_val > 0 && key_val < 17)//个人信息第一位
{
if(key_val==1)card_3=1;
if(key_val==2)card_3=2;
if(key_val==3)card_3=3;
if(key_val==4)card_3=4;
if(key_val==5)card_3=5;
if(key_val==6)card_3=6;
if(key_val==7)card_3=7;
if(key_val==8)card_3=8;
if(key_val==9)card_3=9;
if(key_val==10)card_3=0;
printf("\r\n %d \r\n",card_3);
if(card_3==0|card_3==1|card_3==2|card_3==3|card_3==4|card_3==5|card_3==6|card_3==7|card_3==8|card_3==9)break;
}
}
delay_ms(10000);
while(1)
{
key_val = Matrix_Key_Scan();
if(key_val > 0 && key_val < 17)//个人信息第二位
{
if(key_val==1)card_3=1;
if(key_val==2)card_3=2;
if(key_val==3)card_3=3;
if(key_val==4)card_3=4;
if(key_val==5)card_3=5;
if(key_val==6)card_3=6;
if(key_val==7)card_3=7;
if(key_val==8)card_3=8;
if(key_val==9)card_3=9;
if(key_val==10)card_3=0;
printf("\r\n %d \r\n",card_3);
if(card_3==0|card_3==1|card_3==2|card_3==3|card_3==4|card_3==5|card_3==6|card_3==7|card_3==8|card_3==9)break;
}
}
delay_ms(10000);
while(1)
{
key_val = Matrix_Key_Scan();
if(key_val > 0 && key_val < 17)//个人信息第三位
{
if(key_val==1)card_3=1;
if(key_val==2)card_3=2;
if(key_val==3)card_3=3;
if(key_val==4)card_3=4;
if(key_val==5)card_3=5;
if(key_val==6)card_3=6;
if(key_val==7)card_3=7;
if(key_val==8)card_3=8;
if(key_val==9)card_3=9;
if(key_val==10)card_3=0;
printf("\r\n %d \r\n",card_3);
if(card_3==0|card_3==1|card_3==2|card_3==3|card_3==4|card_3==5|card_3==6|card_3==7|card_3==8|card_3==9)break;
}
}
delay_ms(10000);
while(1)
{
key_val = Matrix_Key_Scan();
if(key_val > 0 && key_val < 17)//个人信息第四位
{
if(key_val==1)card_3=1;
if(key_val==2)card_3=2;
if(key_val==3)card_3=3;
if(key_val==4)card_3=4;
if(key_val==5)card_3=5;
if(key_val==6)card_3=6;
if(key_val==7)card_3=7;
if(key_val==8)card_3=8;
if(key_val==9)card_3=9;
if(key_val==10)card_3=0;
printf("\r\n %d \r\n",card_3);
if(card_3==0|card_3==1|card_3==2|card_3==3|card_3==4|card_3==5|card_3==6|card_3==7|card_3==8|card_3==9)break;
}
}
delay_ms(10000);
if(((card_3==card)&&(card_3==card)&&(card_3==card)&&(card_3==card)))//如果为普通卡的个人信息
{//将挂失时临时保存的普通卡重新定义
card=card_4;
card=card_4;
card=card_4;
card=card_4;
printf("\r\n 普通卡解除挂失成功\r\n");
printf("\r\n 按下S16退出\r\n");
}
else if(((card_3==card)&&(card_3==card)&&(card_3==card)&&(card_3==card)))//如果为学生卡的个人信息
{//将挂失时临时保存的学生卡重新定义
card=card_5;
card=card_5;
card=card_5;
card=card_5;
printf("\r\n 学生卡解除挂失成功\r\n");
printf("\r\n 按下S16退出\r\n");
}
else if(((card_3==card)&&(card_3==card)&&(card_3==card)&&(card_3==card)))//如果为老年卡的个人信息
{//将挂失时临时保存的老年卡重新定义
card=card_6;
card=card_6;
card=card_6;
card=card_6;
printf("\r\n 老年卡解除挂失成功\r\n");
printf("\r\n 按下S16退出\r\n");
}
else
{
printf("\r\n 该个人信息未绑定公交卡\r\n ");
}
}
}
key_val = Matrix_Key_Scan();
if(key_val > 0 && key_val < 17)
{
if(key_val==16)//按下S16退出挂失和解除挂失功能
{
printf("\r\n 退出挂失和解除挂失功能\r\n");
break;
}
}
}
}
页:
[1]
2