RC522读卡数据写入STM32内置FLASH的思路

这几天划水过多
这几天本着学习的态度去看RC522,NFC射频芯片

然后

在这里插入图片描述
无奈自己太菜了,只跑了大佬写的例程勉强可以完成读卡操作

不过也没有闲下来(不想划水),就想了想能不能用STM32内置FLASH存储NFC卡的UID信息,断电后也可以存在,这样验证NFC卡的信息也会方便很多。

基本单位换算

1 M B = 1024 K B 1MB=1024KB 1MB=1024KB
1 K B = 1024 b y t e s 1KB=1024bytes 1KB=1024bytes
1 b y t e s = 1024 K B 1bytes=1024KB 1bytes=1024KB

STM32中各种类型变量所占大小

这里我们随便定义几个不同类型的变量,通过debug就可以查看数据大小

数据类型字节大小
u c h a r uchar uchar 1 b y t e 1byte 1byte
c h a r char char 1 b y t e 1byte 1byte
u s h o r t ushort ushort 2 b y t e s 2bytes 2bytes
s h o r t short short 2 b y t e s 2bytes 2bytes
u i n t uint uint 4 b y t e s 4bytes 4bytes
i n t int int 4 b y t e s 4bytes 4bytes
f l o a t float float 4 b y t e s 4bytes 4bytes
d o u b l e double double 8 b y t e s 8bytes 8bytes

bit即为存储二进制的最小单位0和1

内置FLASH说明

野火的文档里讲解的已经很清晰了,不多说了,

芯片型号为STM32F407ZGT6

读写内部FLASH
在这里插入图片描述
这里需要注意的是:用户代码也存储在内置FLASH内,我们写入数据到FLASH的地址不能与程序代码存储的地址产生冲突。
野火的视频中有讲解

拿扇区 0 0 0来说

地 址 的 长 度 = 0 x 08003 F F F − 0 X 08000000 = 0 X 3 F F F 地址的长度=0x08003FFF-0X08000000=0X3FFF =0x08003FFF0X08000000=0X3FFF

0 x 3 F F F = ( 0011 ) ( 1111 ) ( 1111 ) ( 1111 ) 0x3FFF=(0011)(1111)(1111)(1111) 0x3FFF=(0011)(1111)(1111)(1111) (二进制)

逢二进一,且 1 b i t 1bit 1bit对应 1 b y t e 1byte 1byte

0 x 3 F F F 0x3FFF 0x3FFF的地址长度内存储了214 = 16384 b y t e s =16384bytes =16384bytes数据

16384 / 1024 = 16 K b y t e s 16384/1024=16Kbytes 16384/1024=16Kbytes

查看.map文件

我们双击 p r o j e c t project project下面的文件夹
在这里插入图片描述
就会弹出 . m a p .map .map文件
在这里插入图片描述
可以看出程序的加载地址为: 0 x 08000000 0x0800 0000 0x08000000
大小为: 0 x 3874 0x3874 0x3874
结尾地址: 0 x 08003874 0x0800 3874 0x08003874
可见程序并未超出扇区0的内存。

存储NFC UID数据

通过 d e b u g debug debug可以看出UID得数据类型和大小
在这里插入图片描述
一共为 8 b i t ∗ 4 = 32 b i t = 4 b y t e s 8bit*4=32bit=4bytes 8bit4=32bit=4bytes

我的思路是定义一个 u 8 u8 u8 P A S S [ u s e r ] [ 4 ] PASS[user][4] PASS[user][4]二维数组

一个用户存储 4 4 4 u 8 u8 u8类型的数据既UID数据

确认身份的时候可以根据已有的 u s e r user user来遍历数组,减少了运算量。

实际运行的时候,还要注意地址的递增,

每写入4个u8数据既 4 b y t e s 4bytes 4bytes, 地址增加 0 x 04 0x04 0x04

对应的 u s e r user user也相应+1,并写入 F L A S H FLASH FLASH

思路如下

请添加图片描述

读写UID函数

#define SIZE(data) data/4+((data%4)?1:0)//以u32为单位计算个数,例->5个u8型直接当做2个u32型因为数据写入最小大小为u32
char PASS[10][4],UID2[4];
/**
**********************************
* @brief  写入UID数据
* @param  
* @retval 只写入PASS中没有的UID
**********************************
*/
void Write_card(void)
{
    LCD_ShowString(0,0,"writing mode",DARKBLUE);
    LCD_ShowString(0,20,"set card",DARKBLUE); 
    if(PASS_ID()==0)//读取到卡片&&密码没有存入flash
    {
        if(user>=10)//容量->10
            user=0;
        STMFLASH_Write(FLASH_SAVE_ADDR+(0x04*user),(u32*)UID2,SIZE(sizeof(UID2)));//一个用户密码->u32 ->地址+0x04
        user++;
        FLASH_Write_Byte(USER_ADDR,user);                        //用户数量存入flash
        STMFLASH_Read(FLASH_SAVE_ADDR,(u32*)PASS,sizeof(PASS));    //刷新存储密码的数组
    }    
}
/**
**********************************
* @brief  读取UID并进行校验
* @param  
* @retval 
**********************************
*/
void Read_mode(void)
{
    LCD_ShowString(0,0,"reading mode",DARKBLUE);
    if(READ_CARD())//如果检测到卡片
        PASS_ID();
}

然后在初始化里读去数据就可以了

int main(void)
{ 
	delay_init(168);		  //初始化延时函数
    uart_init(9600);
    Lcd_Init();	
	LCD_Clear(WHITE);
	BACK_COLOR = WHITE;   
    LED_Init();
    SPI2_Init();
    KEY_Init();
    STMFLASH_Read(FLASH_SAVE_ADDR,(u32*)PASS,PASS_SIZE);//从flash内读取密码
    user=FLASH_Read_Byte(USER_ADDR);                    //从flash内读取用户数量
	while(1)
	{      
        i=KEY_Scan(1);
        if(i!=0)
            flag=i;
        else
            i=flag;
        //保持按键值
        switch(i)
        {
            case 1:Read_mode();break;//读卡模式
            case 2:Write_card();break;//写卡模式
            case 4:Erase();break;       //清除扇区2 3
        }
        LCD_ShowNum(0,80,i,1,RED);//显示按键值
	}
}

读写数据函数直接使用的正点的程序,由于正点的程序只能写入u32类型

我就自己写了读写u8类型函数

/**
**********************************
* @brief  写入flash内1个字节
* @param  addr->写入地址 data->写入数据
* @retval None
**********************************
*/
void FLASH_Write_Byte(u32 addr,u8 data)
{
    /*解锁->擦除->写入->上锁*/
    FLASH_Unlock();   
    FLASH_EraseSector(STMFLASH_GetFlashSector(addr),VoltageRange_3);
    FLASH_ProgramByte(addr,data);
    FLASH_Lock();
}

/**
**********************************
* @brief  从flash读取一个字节
* @param  addr->开始读取地址
* @retval None
**********************************
*/
u8 FLASH_Read_Byte(u32 addr)
{
    char *p=(char*)addr;
    u8 data;
    data=*p;
    return data;
}

程序比较简单,都是简单的读写

下面是遍历数组校验UID是否为已有用户的程序

u8 PASS_ID(void)
{
    u8 i=0,j=0;
    for(j=0;j<user;j++)
    {
         for(i=0;i<=3;i++)
        {
            if(PASS[j][i]!=UID[i])
                break;           
        }
        if(i==4)
            break;
    }
        if(i==4)  
        {
            LCD_ShowString(0,40,"PASS->CARD:",DARKBLUE);
            LCD_ShowNum(80,40,j,1,DARKBLUE);
            return 1;
        }
        else 
        {
            LCD_ShowString(0,40,"ERROR",RED); 
            return 0;
        }            
        
}
//==============================================================================
//读取卡的类型
//读取卡的ID号
// 卡片:12AAD52D
// 卡环:EC838322
//==============================================================================
void ReaderCard(void)
{
    char temp_value;
	if(PcdRequest(PICC_REQALL,Temp)==MI_OK)	//选卡
	{
		if(Temp[0]==0x04&&Temp[1]==0x00)  
				printf("MFOne-S50");
		else if(Temp[0]==0x02&&Temp[1]==0x00)
			printf("MFOne-S70");
		else if(Temp[0]==0x44&&Temp[1]==0x00)
			printf("MF-UltraLight");
		else if(Temp[0]==0x08&&Temp[1]==0x00)
			printf("MF-Pro");
		else if(Temp[0]==0x44&&Temp[1]==0x03)
			printf("MF Desire");
		else
			printf("Unknown");
		if(PcdAnticoll(UID)==MI_OK)			//防冲撞
		{ 
			printf("Card Id is:");
			/* 获取卡值  */
			Uart1_SendHexDisplay(UID[0]); 
			Uart1_SendHexDisplay(UID[1]);
			Uart1_SendHexDisplay(UID[2]);
			Uart1_SendHexDisplay(UID[3]);
			printf("\r\n");                //发送换行指令
			temp_value = ((UID[0]>>4)*10+(UID[0]&0x0f));
			printf("管理员:%d\r\n",temp_value);
            
//			switch(temp_value)
//			{
//				case 12 : printf("管理员:%d\r\n",temp_value);    break;
//				case 152: printf("学生  :%d\r\n",temp_value);    break;
//				default : printf("无效卡:%d\r\n",temp_value);    break;
//			}	                             
		}
  } 
}

u8 READ_CARD(void)
{
    u8 i;
    ReaderCard();
    for(i=0;i<4;i++)
    {
        if(UID2[i]!=UID[i])
            break;
    }
    if(i==4)
    {
        return 0;
    }
    else
    {
        data_re();
        return 1;
    }
}

debug效果

在这里插入图片描述

UID数据及用户数量被依次存入FLASH,断电或者复位后数据仍然存在。

上面写的知识一种思路,具体的加密什么也没有搞,更多的是对 F L A S H FLASH FLASH的操作和认知,关于 R C 522 RC522 RC522还需要更多的去学习。
工程文件
提取码:eqbr

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值