欢迎大家关注博主的公众号 大海电子,在大海电子公众号里会和大家分享我的一些看法和知识。
不定期的会发布一些有趣的硬件作品及电路分析、软件源码分享。
需要以下源码工程请扫码关注大海电子,回复“基于STM32F103C8T6的RC522 RFID模块调试”,建议直接复制双引号里面的内容。(免费)
一、所需材料
整个工程文件(淘宝购买):https://item.taobao.com/item.htm?spm=a2126o.11854294.0.0.2aa64831R4YacQ&id=583069400742
1、面包板:
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.12.942e3961LSzalG&id=566952992749
2、STM32F103C8T6核心板
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.12.69693961YaTulR&id=567200541464
3、串口工具
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.21.7dd33961iRVAkv&id=567201073239
5、STlink 下载程序,或用串口下载亦可
https://item.taobao.com/item.htm?spm=a1z10.3-c.w4002-17409464480.9.fff43961mPmMrt&id=573084876537
二、RFID工作原理(待补充)
三、MFRC522与STM32接线图
硬件连接
STM32F103C8T6 RC522模块
PA4(SPI1_NSS) SDA
PA5(SPI1_SCK) SCK
PA6(SPI1_MISO) MISO
PA7(SPI1_MOSI) MOSI
PB0(RST) RST
PB1(IRQ) IRQ
供电:3.3V
四、MFRC522源码
main文件
#include "usart.h"
#include "stm32f10x_spi.h"
#include "RC522.h"
#include "delay.h"
#include "string.h"
#include "spi_driver.h"
#include "stdio.h"
/******************************************************************************
大海电子专营各种电子模块,欢迎光临
功能:只返回卡号
硬件连接
STM32F103C8T6 RC522模块
PA4(SPI1_NSS) SDA
PA5(SPI1_SCK) SCK
PA6(SPI1_MISO) MISO
PA7(SPI1_MOSI) MOSI
PB0(RST) RST
PB1(IRQ) IRQ
备注:以下代码非原创,只是经过修改适配成STM32F103C8T6
若侵权,请告知。
此代码是融合了战舰开发板程序+网上RFID RC522(Author: wdluo)模块进行适配的。
******************************************************************************/
uint8_t Card_Type1[2];
uint8_t Card_ID[4];
uint8_t Card_KEY[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; //{0x11,0x11,0x11,0x11,0x11,0x11}; //密码
uint8_t Card_Data[16];
uint8_t status;
int main(void)
{
uint8_t i;
Card_Type1[0]=0x04;
Card_Type1[1]=0x00;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
printf("\r\n***************************** 大海电子串口测试 *****************************\r\n");
delay_init();
RC522_IO_Init();
PcdReset(); //复位RC522
PcdAntennaOff(); //关闭天线
delay_ms(100);
PcdAntennaOn(); //开启天线
printf("\r\n***************************** 大海电子串口测试 *****************************\r\n");
while(1)
{
delay_ms(10);
if(MI_OK==PcdRequest(0x52, Card_Type1)) //寻卡函数,如果成功返回MI_OK 打印多次卡号
// if(MI_OK==PcdRequest(0x26, Card_Type1)) //寻卡函数,如果成功返回MI_OK 打印1次卡号
{
uint16_t cardType = (Card_Type1[0]<<8)|Card_Type1[1];//读不同卡的类型
printf("卡类型:(0x%04X)\r\n",cardType); //"Card Type(0x%04X):"
switch(cardType){
case 0x4400:
printf("Mifare UltraLight\r\n");
break;
case 0x0400:
printf("Mifare One(S50)\r\n");
break;
case 0x0200:
printf("Mifare One(S70)\r\n");
break;
case 0x0800:
printf("Mifare Pro(X)\r\n");
break;
case 0x4403:
printf("Mifare DESFire\r\n");
break;
default:
printf("Unknown Card\r\n");
break;
}
status = PcdAnticoll(Card_ID);//防冲撞 如果成功返回MI_OK
if(status != MI_OK){
printf("Anticoll Error\r\n");
}else{
printf("Serial Number:%02X%02X%02X%02X\r\n",Card_ID[0],Card_ID[1],Card_ID[2],Card_ID[3]);
}
status = PcdSelect(Card_ID); //选卡 如果成功返回MI_OK
if(status != MI_OK){
printf("Select Card Error\r\n");
}
else
printf("Select Card OK\r\n");
// status = PcdAuthState(PICC_AUTHENT1A,5,Card_KEY,Card_ID);//验证卡密码 如果成功返回MI_OK
// if(status != MI_OK){
// printf("Auth State Error\r\n");
// continue;
// }
//
// memset(Card_ID,1,4); //函数用于为变量开辟空间,或将变量都赋值为一个值
// memset(Card_Data,1,16);
// Card_Data[0]=0xaa;
// status = PcdWrite(5,Card_Data); //写入0XAA,0X01,0X01……选择块地址写入数据,成功则返回MI_OK
// if(status != MI_OK){
// printf("Card Write Error\r\n");
// continue;
// }
// memset(Card_Data,0,16); //清零
// delay_us(8);
//
//
// status = PcdRead(5,Card_Data); //再一次把它读取出来16字节的卡片数据,选择块地址读出数据,成功则返回MI_OK
// if(status != MI_OK){
// printf("Card Read Error\r\n");
// continue;
// }else{
// for(i=0;i<16;i++){
// printf("%02X ",Card_Data[i]);
// }
// printf("\r\n");
// }
//
// memset(Card_Data,2,16);
// Card_Data[0]=0xbb;
// delay_us(8);
// status = PcdWrite(5,Card_Data); //写入0Xbb,0X02,0X02……
// if(status != MI_OK){
// printf("Card Write Error\r\n");
// continue;
// }
// delay_us(8);
//
// status = PcdRead(5,Card_Data); //再一次把它读取出来16字节的卡片数据
// if(status != MI_OK){
// printf("Card Read Error\r\n");
// continue;
// }else{
// for(i=0;i<16;i++){
// printf("%02X ",Card_Data[i]);
// }
// printf("\r\n");
// }
//memset(Card_Data,0,16);
// PcdHalt(); //卡片进入休眠状态
status = PcdHalt(); //卡片进入休眠状态
if(status != MI_OK){
printf("PcdHalt Error\r\n");
}
else
{
printf("PcdHalt OK\r\n");
}
}
}
}
RC522.c
#include "stm32f10x.h"
#include "rc522.h"
#include "delay.h"
#include "spi_driver.h"
#include "stm32f10x_spi.h"
void RC522_IO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //开启AFIO时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //关闭JTAG因为要使用PB3和4
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_4;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
SPI_Configuration(SPI1);
}
/*
/////////////////////////////////////////////////////////////////////
//功 能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
// value[IN]:写入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{
unsigned char i, ucAddr;
RC522_SCK_RESET(); //MF522_SCK = 0;
RC522_NSEL_RESET(); //MF522_NSS = 0;
ucAddr = ((Address<<1)&0x7E);
RC522_Delay(10);
for(i=8;i>0;i--)
{
//MF522_SI = ((ucAddr&0x80)==0x80);
if((ucAddr&0x80)==0x80)
{
RC522_MOSI_SET();
}
else
{
RC522_MOSI_RESET();
}
RC522_SCK_SET(); //MF522_SCK = 1;
ucAddr <<= 1;
RC522_Delay(10);
RC522_SCK_RESET(); //MF522_SCK = 0;
RC522_Delay(10);
}
for(i=8;i>0;i--)
{
//MF522_SI = ((value&0x80)==0x80);
if((value&0x80)==0x80)
{
RC522_MOSI_SET();
}
else
{
RC522_MOSI_RESET();
}
RC522_SCK_SET(); //MF522_SCK = 1;
value <<= 1;
RC522_Delay(10);
RC522_SCK_RESET(); //MF522_SCK = 0;
RC522_Delay(10);
// MF522_SCK = 1;
// value <<= 1;
// MF522_SCK = 0;
}
RC522_NSEL_SET(); //MF522_NSS = 1;
RC522_SCK_SET(); //MF522_SCK = 1;
}
/////////////////////////////////////////////////////////////////////
//功 能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返 回:读出的值
/////////////////////////////////////////////////////////////////////
unsigned char ReadRawRC(unsigned char Address)
{
unsigned char i, ucAddr;
unsigned char ucResult=0;
RC522_SCK_RESET(); //MF522_SCK = 0;
RC522_NSEL_RESET(); //MF522_NSS = 0;
ucAddr = ((Address<<1)&0x7E)|0x80;
RC522_Delay(10);
for(i=8;i>0;i--)
{
// MF522_SI = ((ucAddr&0x80)==0x80);
// MF522_SCK = 1;
// ucAddr <<= 1;
// MF522_SCK = 0;
if((ucAddr&0x80)==0x80)
{
RC522_MOSI_SET();
}
else
{
RC522_MOSI_RESET();
}
RC522_SCK_SET(); //MF522_SCK = 1;
ucAddr <<= 1;
RC522_Delay(10);
RC522_SCK_RESET(); //MF522_SCK = 0;
RC522_Delay(10);
}
for(i=8;i>0;i--)
{
RC522_SCK_SET(); //MF522_SCK = 1;
ucResult <<= 1;
RC522_Delay(10);
//ucResult|=(bit)MF522_SO;
// if(RC522_MISO_STATUS==1)
// {
// ucResult|=0x01;
// }
// else
// {
// ucResult&=~0x01;
// }
ucResult |=RC522_MISO_STATUS;
RC522_SCK_RESET(); //MF522_SCK = 0;
RC522_Delay(10);
}
RC522_NSEL_SET(); //MF522_NSS = 1;
RC522_SCK_SET(); //MF522_SCK = 1;
return ucResult;
}
*/
//#define MAXRLEN 18
/////////////////////////////////////////////////////////////////////
//功 能:寻卡
//参数说明: req_code[IN]:寻卡方式
// 0x52 = 寻感应区内所有符合14443A标准的卡
// 0x26 = 寻未进入休眠状态的卡
// pTagType[OUT]:卡片类型代码
// 0x4400 = Mifare_UltraLight
// 0x0400 = Mifare_One(S50)
// 0x0200 = Mifare_One(S70)
// 0x0800 = Mifare_Pro(X)
// 0x4403 = Mifare_DESFire
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
char status;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08); //清RC522寄存位
WriteRawRC(BitFramingReg,0x07); //写RC623寄存器
SetBitMask(TxControlReg,0x03); //置RC522寄存位
//
ucComMF522Buf[0] = req_code;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
// UART_send_byte(status);
if ((status == MI_OK) && (unLen == 0x10))
{
*pTagType = ucComMF522Buf[0];
*(pTagType+1) = ucComMF522Buf[1];
}
else
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdAnticoll(unsigned char *pSnr)
{
char status;
unsigned char i,snr_check=0;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x00);
ClearBitMask(CollReg,0x80);
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x20;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
if (status == MI_OK)
{
for (i=0; i<4; i++)
{
*(pSnr+i) = ucComMF522Buf[i];
snr_check ^= ucComMF522Buf[i];
}
if (snr_check != ucComMF522Buf[i])
{ status = MI_ERR; }
}
SetBitMask(CollReg,0x80);
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:选定卡片
//参数说明: pSnr[IN]:卡片序列号,4字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdSelect(unsigned char *pSnr)
{
char status;
unsigned char i;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x70;
ucComMF522Buf[6] = 0;
for (i=0; i<4; i++)
{
ucComMF522Buf[i+2] = *(pSnr+i);
ucComMF522Buf[6] ^= *(pSnr+i);
}
CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
ClearBitMask(Status2Reg,0x08);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x18))
{ status = MI_OK; }
else
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
// 0x60 = 验证A密钥
// 0x61 = 验证B密钥
// addr[IN]:块地址
// pKey[IN]:密码
// pSnr[IN]:卡片序列号,4字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = auth_mode;
ucComMF522Buf[1] = addr;
for (i=0; i<6; i++)
{ ucComMF522Buf[i+2] = *(pKey+i); }
for (i=0; i<6; i++)
{ ucComMF522Buf[i+8] = *(pSnr+i); }
status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:读取M1卡一块数据
//参数说明: addr[IN]:块地址
// p [OUT]:读出的数据,16字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRead(unsigned char addr,unsigned char *pData)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_READ;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x90))
{
for (i=0; i<16; i++)
{ *(pData+i) = ucComMF522Buf[i]; }
}
else
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:写数据到M1卡一块
//参数说明: addr[IN]:块地址
// p [IN]:写入的数据,16字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdWrite(unsigned char addr,unsigned char *pData)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_WRITE;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
{ status = MI_ERR; }
if (status == MI_OK)
{
for (i=0; i<16; i++)
{ ucComMF522Buf[i] = *(pData+i); }
CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
{ status = MI_ERR; }
}
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:扣款和充值
//参数说明: dd_mode[IN]:命令字
// 0xC0 = 扣款
// 0xC1 = 充值
// addr[IN]:钱包地址
// pValue[IN]:4字节增(减)值,低位在前
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = dd_mode;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
{ status = MI_ERR; }
if (status == MI_OK)
{
for (i=0; i<16; i++)
{ ucComMF522Buf[i] = *(pValue+i); }
CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
unLen = 0;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
if (status != MI_ERR)
{ status = MI_OK; }
}
if (status == MI_OK)
{
ucComMF522Buf[0] = PICC_TRANSFER;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
{ status = MI_ERR; }
}
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:备份钱包
//参数说明: sourceaddr[IN]:源地址
// goaladdr[IN]:目标地址
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr)
{
char status;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_RESTORE;
ucComMF522Buf[1] = sourceaddr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
{ status = MI_ERR; }
if (status == MI_OK)
{
ucComMF522Buf[0] = 0;
ucComMF522Buf[1] = 0;
ucComMF522Buf[2] = 0;
ucComMF522Buf[3] = 0;
CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
if (status != MI_ERR)
{ status = MI_OK; }
}
if (status != MI_OK)
{ return MI_ERR; }
ucComMF522Buf[0] = PICC_TRANSFER;
ucComMF522Buf[1] = goaladdr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:命令卡片进入休眠状态
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdHalt(void)
{
//char status;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_HALT;
ucComMF522Buf[1] = 0;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
//status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
return MI_OK;
}
/////////////////////////////////////////////////////////////////////
//用MF522计算CRC16函数
/////////////////////////////////////////////////////////////////////
void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData)
{
unsigned char i,n;
ClearBitMask(DivIrqReg,0x04);
WriteRawRC(CommandReg,PCD_IDLE);
SetBitMask(FIFOLevelReg,0x80);
for (i=0; i
WriteRawRC(CommandReg, PCD_CALCCRC);
i = 0xFF;
do
{
n = ReadRawRC(DivIrqReg);
i--;
}
while ((i!=0) && !(n&0x04));
pOutData[0] = ReadRawRC(CRCResultRegL);
pOutData[1] = ReadRawRC(CRCResultRegM);
}
/////////////////////////////////////////////////////////////////////
//功 能:复位RC522
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdReset(void)
{
RC522_RESET_SET(); //RST522_1;
delay_us(10); //_NOP();
RC522_RESET_RESET(); //RST522_0;
delay_ms(60); //_NOP();_NOP();
RC522_RESET_SET(); //RST522_1;RST522_1;
delay_us(500); //_NOP();_NOP();
WriteRawRC(CommandReg,PCD_RESETPHASE);
delay_ms(2); //_NOP();_NOP();
WriteRawRC(ModeReg,0x3D); //?Mifare???,CRC???0x6363
WriteRawRC(TReloadRegL,30); //?30?????
WriteRawRC(TReloadRegH,0);
WriteRawRC(TModeReg,0x8D);
WriteRawRC(TPrescalerReg,0x3E);
WriteRawRC(TxAutoReg,0x40);
ClearBitMask(TestPinEnReg, 0x80);//off MX and DTRQ out
WriteRawRC(TxAutoReg,0x40);
return MI_OK;
}
/////////////////////////////////////////////////////////////////////
//功 能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返 回:读出的值
/////////////////////////////////////////////////////////////////////
unsigned char ReadRawRC(unsigned char Address)
{
unsigned char ucAddr;
unsigned char ucResult=0;
ucAddr = ((Address<<1)&0x7E)|0x80;
delay_ms(1);
RC522_ENABLE;
SPI_WriteNBytes(SPI1,&ucAddr,1); //向总线写多个数据
SPI_ReadNBytes(SPI1,&ucResult,1); //向总线读多个数据
RC522_DISABLE;
return ucResult;
}
/////////////////////////////////////////////////////////////////////
//功 能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
// value[IN]:写入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{
unsigned char ucAddr;
uint8_t write_buffer[2]={0};
ucAddr = ((Address<<1)&0x7E);
write_buffer[0] = ucAddr;
write_buffer[1] = value;
delay_ms(1);
RC522_ENABLE;
SPI_WriteNBytes(SPI1,write_buffer,2);
RC522_DISABLE;
}
/////////////////////////////////////////////////////////////////////
//功 能:置RC522寄存器位
//参数说明:reg[IN]:寄存器地址
// mask[IN]:置位值
/////////////////////////////////////////////////////////////////////
void SetBitMask(unsigned char reg,unsigned char mask)
{
char tmp = 0x0;
tmp = ReadRawRC(reg); //读RC632寄存器
WriteRawRC(reg,tmp | mask); // set bit mask
}
/////////////////////////////////////////////////////////////////////
//功 能:清RC522寄存器位
//参数说明:reg[IN]:寄存器地址
// mask[IN]:清位值
/////////////////////////////////////////////////////////////////////
void ClearBitMask(unsigned char reg,unsigned char mask)
{
char tmp = 0x0;
tmp = ReadRawRC(reg);
WriteRawRC(reg, tmp & ~mask); // clear bit mask
}
/////////////////////////////////////////////////////////////////////
//功 能:通过RC522和ISO14443卡通讯
//参数说明:Command[IN]:RC522命令字
// pIn [IN]:通过RC522发送到卡片的数据
// InLenByte[IN]:发送数据的字节长度
// pOut [OUT]:接收到的卡片返回数据
// *pOutLenBit[OUT]:返回数据的位长度
/////////////////////////////////////////////////////////////////////
char PcdComMF522(unsigned char Command,
unsigned char *pInData,
unsigned char InLenByte,
unsigned char *pOutData,
unsigned int *pOutLenBit)
{
char status = MI_ERR;
unsigned char irqEn = 0x00;
unsigned char waitFor = 0x00;
unsigned char lastBits;
unsigned char n;
unsigned int i;
switch (Command)
{
case PCD_AUTHENT:
irqEn = 0x12;
waitFor = 0x10;
break;
case PCD_TRANSCEIVE:
irqEn = 0x77;
waitFor = 0x30;
break;
default:
break;
}
WriteRawRC(ComIEnReg,irqEn|0x80);
ClearBitMask(ComIrqReg,0x80);
WriteRawRC(CommandReg,PCD_IDLE);
SetBitMask(FIFOLevelReg,0x80);
for (i=0; i
WriteRawRC(CommandReg, Command);
if (Command == PCD_TRANSCEIVE)
{ SetBitMask(BitFramingReg,0x80); }
i = 800 ; //600;//????????,??M1???????25ms
do
{
n = ReadRawRC(ComIrqReg);
i--;
}
while ((i!=0) && !(n&0x01) && !(n&waitFor));
ClearBitMask(BitFramingReg,0x80);
if (i!=0)
{
if(!(ReadRawRC(ErrorReg)&0x1B))
{
status = MI_OK;
if (n & irqEn & 0x01)
{ status = MI_NOTAGERR; }
if (Command == PCD_TRANSCEIVE)
{
n = ReadRawRC(FIFOLevelReg);
lastBits = ReadRawRC(ControlReg) & 0x07;
if (lastBits)
{ *pOutLenBit = (n-1)*8 + lastBits; }
else
{ *pOutLenBit = n*8; }
if (n == 0)
{ n = 1; }
if (n > MAXRLEN)
{ n = MAXRLEN; }
for (i=0; i
}
}
else
{ status = MI_ERR; }
}
SetBitMask(ControlReg,0x80); // stop timer now
WriteRawRC(CommandReg,PCD_IDLE);
return status;
}
/////////////////////////////////////////////////////////////////////
//开启天线
//每次启动或关闭天险发射之间应至少有1ms的间隔
/////////////////////////////////////////////////////////////////////
void PcdAntennaOn(void)
{
unsigned char i;
i = ReadRawRC(TxControlReg);
if (!(i & 0x03))
{
SetBitMask(TxControlReg, 0x03);
}
}
/////////////////////////////////////////////////////////////////////
//关闭天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOff(void)
{
ClearBitMask(TxControlReg, 0x03);
}
void RC522_Config(unsigned char Card_Type)
{
ClearBitMask(Status2Reg,0x08);
WriteRawRC(ModeReg,0x3D);//3F
WriteRawRC(RxSelReg,0x86);//84
WriteRawRC(RFCfgReg,0x7F); //4F
WriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec)
WriteRawRC(TReloadRegH,0);
WriteRawRC(TModeReg,0x8D);
WriteRawRC(TPrescalerReg,0x3E);
// WriteRawRC(TxAutoReg,0x40);//???
delay_ms(5);//delay_10ms(1);
PcdAntennaOn();
}
SPI.c
#include "stm32f10x.h"
#include "spi_driver.h"
static void SPI_RCC_Configuration(SPI_TypeDef* SPIx)
{
if(SPIx==SPI1){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1,ENABLE);
}else{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
}
}
/**
* @brief 配置指定SPI的引脚
* @param SPIx 需要使用的SPI
* @retval None
*/
static void SPI_GPIO_Configuration(SPI_TypeDef* SPIx) //D哥的板子用PB13,PB14,PB15
{
GPIO_InitTypeDef GPIO_InitStruct;
if(SPIx==SPI1){
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
//初始化片选输出引脚
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_SetBits(GPIOA,GPIO_Pin_4);
}else{
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStruct);
//初始化片选输出引脚
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}
}
/**
* @brief 根据外部SPI设备配置SPI相关参数
* @param SPIx 需要使用的SPI
* @retval None
*/
void SPI_Configuration(SPI_TypeDef* SPIx)
{
SPI_InitTypeDef SPI_InitStruct;
SPI_RCC_Configuration(SPIx);
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_InitStruct.SPI_Direction= SPI_Direction_2Lines_FullDuplex;
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStruct.SPI_NSS = SPI_NSS_Hard;
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStruct.SPI_CRCPolynomial = 7;
SPI_Init(SPIx, &SPI_InitStruct);
SPI_GPIO_Configuration(SPIx);
SPI_SSOutputCmd(SPIx, ENABLE);
SPI_Cmd(SPIx, ENABLE);
}
/**
* @brief 写1字节数据到SPI总线
* @param SPIx 需要使用的SPI
* @param TxData 写到总线的数据
* @retval 数据发送状态
* @arg 0 数据发送成功
* @arg -1 数据发送失败
*/
int32_t SPI_WriteByte(SPI_TypeDef* SPIx, uint16_t TxData)
{
uint8_t retry=0;
while((SPIx->SR&SPI_I2S_FLAG_TXE)==0); //等待发送区空
{
retry++;
if(retry>200)return -1;
}
SPIx->DR=TxData; //发送一个byte
retry=0;
while((SPIx->SR&SPI_I2S_FLAG_RXNE)==0); //等待接收完一个byte
{
retry++;
if(retry>200)return -1;
}
SPIx->DR;
return 0; //返回收到的数据
}
/**
* @brief 从SPI总线读取1字节数据
* @param SPIx 需要使用的SPI
* @param p_RxData 数据储存地址
* @retval 数据读取状态
* @arg 0 数据读取成功
* @arg -1 数据读取失败
*/
int32_t SPI_ReadByte(SPI_TypeDef* SPIx, uint16_t *p_RxData)
{
uint8_t retry=0;
while((SPIx->SR&SPI_I2S_FLAG_TXE)==0); //等待发送区空
{
retry++;
if(retry>200)return -1;
}
SPIx->DR=0xFF; //发送一个byte
retry=0;
while((SPIx->SR&SPI_I2S_FLAG_RXNE)==0); //等待接收完一个byte
{
retry++;
if(retry>200)return -1;
}
*p_RxData = SPIx->DR;
return 0; //返回收到的数据
}
/**
* @brief 向SPI总线写多字节数据
* @param SPIx 需要使用的SPI
* @param p_TxData 发送数据缓冲区首地址
* @param sendDataNum 发送数据字节数
* @retval 数据发送状态
* @arg 0 数据发送成功
* @arg -1 数据发送失败
*/
int32_t SPI_WriteNBytes(SPI_TypeDef* SPIx, uint8_t *p_TxData,uint32_t sendDataNum)
{
uint8_t retry=0;
while(sendDataNum--){
while((SPIx->SR&SPI_I2S_FLAG_TXE)==0); //等待发送区空
{
retry++;
if(retry>20000)return -1;
}
SPIx->DR=*p_TxData++; //发送一个byte
retry=0;
while((SPIx->SR&SPI_I2S_FLAG_RXNE)==0); //等待接收完一个byte
{
SPIx->SR = SPIx->SR;
retry++;
if(retry>20000)return -1;
}
SPIx->DR;
}
return 0;
}
/**
* @brief 从SPI总线读取多字节数据
* @param SPIx 需要使用的SPI
* @param p_RxData 数据储存地址
* @param readDataNum 读取数据字节数
* @retval 数据读取状态
* @arg 0 数据读取成功
* @arg -1 数据读取失败
*/
int32_t SPI_ReadNBytes(SPI_TypeDef* SPIx, uint8_t *p_RxData,uint32_t readDataNum)
{
uint8_t retry=0;
while(readDataNum--){
SPIx->DR = 0xFF;
while(!(SPIx->SR&SPI_I2S_FLAG_TXE)){
retry++;
if(retry>20000)return -1;
}
retry = 0;
while(!(SPIx->SR&SPI_I2S_FLAG_RXNE)){
retry++;
if(retry>20000)return -1;
}
*p_RxData++ = SPIx->DR;
}
return 0;
}
/*********************************END OF FILE**********************************/