大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
公司需要做刷卡模块,因此选了RC522做demo程序。下面就RC522知识做简要的总结。
本人使用stm32的硬件spi接口搭建工程,相关的配置如下:
spi配置:
引脚配置
SDA ——-PA4
SCLK —-PB13
MOSI ——-PB15
MISO ——PB14
IRQ —没接
RST —- PB0
//PB12--NSS PB13--SCK PB14--MISO PB15--MOSI
void SPI2_Init(void)
{
RCC->APB2ENR |= 1 << 3; //开启PORT b端口时钟
RCC->APB1ENR |= 1 << 14; //开启SPI2时钟
// PB13,PB14 PB15复用输出
GPIOB->CRH &= 0X000FFFFF;
GPIOB->CRH |= 0XBBB00000;
GPIOB->ODR |= 7 << 13;
SPI2->CR1 |= 0<<10; //全双工模式
SPI2->CR1 |= 1<<9; //启用软件管理
SPI2->CR1 |= 1<<8; //ssi = 1
SPI2->CR1 |= 1<<2; // 主设备
SPI2->CR1 |= 0<<11; //8 bit
SPI2->CR1 |= 1<<1; //SCK空闲为高
SPI2->CR1 |= 1<<0; //上升沿采样
SPI2->CR1 |= 7<<3; //256分频
SPI2->CR1 |= 0<<7; //先发MSB
SPI2->CR1 |= 1<<6; //开启SPI
SPI2->CR2 |= 1 << 2;
//SPI2_ReadWriteByte(0xff);
}
void SPI2_SetSpeed(u8 SpeedSet)
{
SPI2->CR1 &= 0XFFC7;
if(SpeedSet==SPI_SPEED_2)
{
SPI2->CR1|=0<<3;
}
else if(SpeedSet==SPI_SPEED_8)
{
SPI2->CR1|=2<<3;
}
else if(SpeedSet==SPI_SPEED_16)
{
SPI2->CR1|=3<<3;
}
else
{
SPI2->CR1|=7<<3;
}
SPI2->CR1|=1<<6;
}
u8 SPI2_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while((SPI2->SR&1<<1)==0)
{
retry++;
if(retry>200)return 0;
}
SPI2->DR=TxData;
retry=0;
while((SPI2->SR&1<<0)==0)
{
retry++;
if(retry>200)return 0;
}
return SPI2->DR;
}
RC522相关接口初始化:
由于spi的cs由软件控制,所以,这里设置PA4为CS,PB0为rst
void RCC52_init(void)
{
RCC->APB2ENR |= 1 << 3;
RCC->APB2ENR |= 1 << 2;
GPIOB->CRL &= 0XFFFFFFF0;
GPIOB->CRL |= 0X00000003;
GPIOB->ODR |= 1 << 0;
GPIOA->CRL &= 0XFFF0FFFF;
GPIOA->CRL |= 0X00030000;
GPIOA->ODR |= 1 << 4;
}
rc522的识别过程:
寻卡———->防冲突———->寻卡———>验证密码———>存储操作
卡的操作包括:
读 (Read):读一个块;
写 (Write):写一个块;
加(Increment):对数值块进行加值;
减(Decrement):对数值块进行减值;
存储(Restore):将块中的内容存到数据寄存器中;
传输(Transfer):将数据寄存器中的内容写入块中;
中止(Halt):将卡置于暂停工作状态;
存储器组织
下面是识别卡过程的主函数
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "wdg.h"
#include "timer.h"
#include "lcd.h"
#include "rtc.h"
#include "wkup.h"
#include "adc.h"
#include "dma.h"
#include "24cxx.h"
#include "flash.h"
#include "RC522.h"
#include "spi2.h"
#include <string.h>
unsigned char DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
unsigned char data[16] = {0};
//4字节金额(低字节在前)+4字节金额取反+4字节金额+1字节块地址+1字节块地址取反+1字节块地址+1字节块地址取反
unsigned char bull[16] = {0x01,0x00,0x00,0x00,0xFE,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x02,0xFD,0x02,0xFD};
unsigned char value[4] = {0X00,0x00,0x00,0x0A};
int main(void)
{
unsigned char ucArray_ID [ 4 ]; /*先后存放IC卡的类型和UID(IC卡序列号)*/
unsigned char ucStatusReturn = MI_ERR; /*返回状态 */
char cStr [ 30 ];
int i = 0;
unsigned char addr = 2;
Stm32_Clock_Init(9);//系统时钟设置
delay_init(72); //延时初始化
uart_init(72,9600); //串口1初始化
LED_Init(); //LED初始化
RCC52_init ();
//PB12--NSS PB13--SCK PB14--MISO PB15--MOSI
SPI2_Init() ;
// SPIx_SetSpeed(256);
if( MI_OK == PcdReset())
{
printf("RESET OK\n");
}
else
{
printf("reset failed\n");
while(1);
}
PcdConfigISOType();
PcdAntennaOff();
delay_ms(10);
PcdAntennaOn();
while(1)
{
ucStatusReturn = PcdRequest(PICC_REQALL,ucArray_ID );
if(MI_OK != ucStatusReturn)
{ // printf("yanzheng fial\n");
PcdAntennaOff();
delay_ms(10);
PcdAntennaOn();
continue;
}
if(ucStatusReturn == MI_OK)
{
/*防冲撞(当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作)*/
if ( PcdAnticoll ( ucArray_ID ) == MI_OK )
{
sprintf ( cStr, "The Card ID is: %02X%02X%02X%02X",
ucArray_ID [ 0 ],
ucArray_ID [ 1 ],
ucArray_ID [ 2 ],
ucArray_ID [ 3 ] );
printf ( "%s\r\n",cStr );
}
}
ucStatusReturn = PcdSelect(ucArray_ID);
if(ucStatusReturn != MI_OK)
continue;
#if 0
ucStatusReturn = PcdAuthState(PICC_AUTHENT1A, 1, DefaultKey, ucArray_ID);//验证卡片密码
if(ucStatusReturn != MI_OK)
continue;
ucStatusReturn = PcdRead(1,data);
if(ucStatusReturn == MI_OK)
{
for(i = 0; i < 16; i++)
{
printf("0x%x ",data[i]);
}
}
printf("\n");
ucStatusReturn = PcdAuthState(PICC_AUTHENT1A, 1, DefaultKey, ucArray_ID);//验证卡片密码
if(ucStatusReturn != MI_OK)
continue;
data[14] = 0x11;
data[15] = 0x13;
ucStatusReturn = PcdWrite(1,data);
if(ucStatusReturn == MI_OK)
{
for(i = 0; i < 16; i++)
{
printf("0x%x ",data[i]);
}
}
printf("\n");
#else
//初始化钱包
ucStatusReturn = PcdAuthState(PICC_AUTHENT1A, 2, DefaultKey, ucArray_ID);//验证卡片密码
if(ucStatusReturn != MI_OK)
continue;
ucStatusReturn = PcdWrite(2,bull);
if(ucStatusReturn != MI_OK)
continue;
//查询钱包
ucStatusReturn = PcdAuthState(PICC_AUTHENT1A, 2, DefaultKey, ucArray_ID);//验证卡片密码
if(ucStatusReturn != MI_OK)
continue;
ucStatusReturn = PcdRead(2,bull);
if(ucStatusReturn == MI_OK)
{
for(i = 0; i < 16; i++)
{
printf("0x%x ",bull[i]);
}
}
printf("\n");
//扣值
ucStatusReturn = PcdAuthState(PICC_AUTHENT1A, addr, DefaultKey, ucArray_ID);//验证卡片密码
if(ucStatusReturn != MI_OK)
continue;
ucStatusReturn = PcdValue(PICC_INCREMENT,addr,value) ;
if(ucStatusReturn != MI_OK)
{printf("decre fial\n");
continue;
}
ucStatusReturn = PcdAuthState(PICC_AUTHENT1A, 2, DefaultKey, ucArray_ID);//验证卡片密码
if(ucStatusReturn != MI_OK)
continue;
//显示余额
ucStatusReturn = PcdRead(2,bull);
if(ucStatusReturn == MI_OK)
{
for(i = 0; i < 16; i++)
{
printf("0x%x ",bull[i]);
}
}
printf("\n");
#endif
delay_ms(1000);
}
}
大概过程就是这样。其中,充值,减值的电子钱包功能测试没有通过,没时间研究了,毕竟跟工作关系不大。相关代码已经上传了。
参考:
https://blog.csdn.net/liujianhua1989/article/details/72639307
https://blog.csdn.net/a827415225/article/details/51898897
https://blog.csdn.net/txf1984/article/details/46560261
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/191808.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...