一、应用简介
最近很忙,老早就想写STM32的RFID了,对于读卡来说MS522和RC522是驱动通用的,这里做个简单的RFID刷卡计时分享出来吧!
话不多说,先上个效果图看看,效果如下:
1.1 环境
1.主控芯片:STM32F103RC
2.RFID模块:SPI3接口(其他SPI接口类似,这里我用的3比较特殊需要禁用JTAG)
3.编译环境:Keil MDK(基于标准库)
1.2 原理图
二、设计实例
board_spi.h
#ifndef __BOARD_SPI_H
#define __BOARD_SPI_H
#include "stm32f10x.h"
#include <stdio.h>
void SPI_INIT(void);
void GPIO_Configuration(void);
#endif
board_spi.c
#include "stm32f10x.h"
#include "string.h"
void SPI_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
//APB1 SPI3
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);
//SPI3
SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex; //SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode=SPI_Mode_Master; //设置为主SPI
SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b; //SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low; //时钟悬空低
SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge; //数据捕获于第1个时钟沿
SPI_InitStructure.SPI_NSS=SPI_NSS_Soft; //NSS由外部管脚管理
SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_16; //波特率预分频值为4
//此处的SPI频率 要控制在30MHZ以下 2分频的话是36MHZ W5500的手册标注极限是33MHZ
SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB; //数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial=7; //CRC多项式为7
SPI_Init(SPI3,&SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPI2寄存器
SPI_Cmd(SPI3, ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|\
GPIO_Pin_3|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度
GPIO_Init(GPIOB, &GPIO_InitStructure);
//禁用JTAG 开启SWD
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//关闭jtag,保留swd。
}
接下来是重头戏,驱动不是我写的,但是管用就行,有的注释没改过来。文件名是rc522.h和rc522.c但是实际芯片用的是MS522。
rc522.h
#ifndef _RC522_H_
#define _RC522_H_
#include "stm32f10x.h"
#include "stm32f10x_it.h"
//--------------#define --------------
#define MAXRLEN 18
#define MIN_STRENGTH 228
#define DEF_FIFO_LENGTH 64 //FIFO size=64byte;
/
// RC522命令字 /
/
#define PCD_IDLE 0x00 //取消当前命令
#define PCD_AUTHENT 0x0E //验证密钥
#define PCD_RECEIVE 0x08 //接收数据
#define PCD_TRANSMIT 0x04 //发送数据
#define PCD_TRANSCEIVE 0x0C //发送并接收数据
#define PCD_RESETPHASE 0x0F //复位
#define PCD_CALCCRC 0x03 //CRC计算
/
// Mifare_One卡片命令字 */
/
#define PICC_REQIDL 0x26 //寻天线区内未进入休眠状态
#define PICC_REQALL 0x52 //寻天线区内全部卡
#define PICC_ANTICOLL1 0x93 //防冲撞
#define PICC_ANTICOLL2 0x95 //防冲撞
#define PICC_AUTHENT1A 0x60 //验证A密钥
#define PICC_AUTHENT1B 0x61 //验证B密钥
#define PICC_READ 0x30 //读块
#define PICC_WRITE 0xA0 //写块
#define PICC_DECREMENT 0xC0 //扣款
#define PICC_INCREMENT 0xC1 //充值
#define PICC_RESTORE 0xC2 //调块数据到缓冲区
#define PICC_TRANSFER 0xB0 //保存缓冲区中数据
#define PICC_HALT 0x50 //休眠
/
// MF522寄存器定义 /
/
// PAGE 0
#define RFU00 0x00
#define CommandReg 0x01
#define ComIEnReg 0x02
#define DivlEnReg 0x03
#define ComIrqReg 0x04
#define DivIrqReg 0x05
#define ErrorReg 0x06
#define Status1Reg 0x07
#define Status2Reg 0x08
#define FIFODataReg 0x09
#define FIFOLevelReg 0x0A
#define WaterLevelReg 0x0B
#define ControlReg 0x0C
#define BitFramingReg 0x0D
#define CollReg 0x0E
#define RFU0F 0x0F
// PAGE 1
#define RFU10 0x10
#define ModeReg 0x11
#define TxModeReg 0x12
#define RxModeReg 0x13
#define TxControlReg 0x14
#define TxASKReg 0x15
#define TxSelReg 0x16
#define RxSelReg 0x17
#define RxThresholdReg 0x18
#define DemodReg 0x19
#define RFU1A 0x1A
#define RFU1B 0x1B
#define MifareReg 0x1C
#define RFU1D 0x1D
#define RFU1E 0x1E
#define SerialSpeedReg 0x1F
// PAGE 2
#define RFU20 0x20
#define CRCResultRegM 0x21
#define CRCResultRegL 0x22
#define RFU23 0x23
#define ModWidthReg 0x24
#define RFU25 0x25
#define RFCfgReg 0x26
#define GsNReg 0x27
#define CWGsCfgReg 0x28
#define ModGsCfgReg 0x29
#define TModeReg 0x2A
#define TPrescalerReg 0x2B
#define TReloadRegH 0x2C
#define TReloadRegL 0x2D
#define TCounterValueRegH 0x2E
#define TCounterValueRegL 0x2F
// PAGE 3
#define RFU30 0x30
#define TestSel1Reg 0x31
#define TestSel2Reg 0x32
#define TestPinEnReg 0x33
#define TestPinValueReg 0x34
#define TestBusReg 0x35
#define AutoTestReg 0x36
#define VersionReg 0x37
#define AnalogTestReg 0x38
#define TestDAC1Reg 0x39
#define TestDAC2Reg 0x3A
#define TestADCReg 0x3B
#define RFU3C 0x3C
#define RFU3D 0x3D
#define RFU3E 0x3E
#define RFU3F 0x3F
/
// RC522通讯返回错误代码 /
/
#define MI_ERR 0xFE
//#define MI_ERR //(-2)
// Mifare Error Codes
// Each function returns a status value, which corresponds to the
// mifare error codes.
#define MI_OK 0
#define MI_CHK_OK 0
#define MI_CRC_ZERO 0
#define MI_CRC_NOTZERO 1
#define MI_NOTAGERR 0xFF
#define MI_CHK_FAILED 0xFF
#define MI_CRCERR 0xFE
#define MI_CHK_COMPERR 0xFE
#define MI_EMPTY 0xFD
#define MI_AUTHERR 0xFC
#define MI_PARITYERR 0xFB
#define MI_CODEERR 0xFA
#define MI_SERNRERR 0xF8
#define MI_KEYERR 0xF7
#define MI_NOTAUTHERR 0xF6
#define MI_BITCOUNTERR 0xF5
#define MI_BYTECOUNTERR 0xF4
#define MI_IDLE 0xF3
#define MI_TRANSERR 0xF2
#define MI_WRITEERR 0xF1
#define MI_INCRERR 0xF0
#define MI_DECRERR 0xEF
#define MI_READERR 0xEE
#define MI_OVFLERR 0xED
#define MI_POLLING 0xEC
#define MI_FRAMINGERR 0xEB
#define MI_ACCESSERR 0xEA
#define MI_UNKNOWN_COMMAND 0xE9
#define MI_COLLERR 0xE8
#define MI_RESETERR 0xE7
#define MI_INITERR 0xE7
#define MI_INTERFACEERR 0xE7
#define MI_ACCESSTIMEOUT 0xE5
#define MI_NOBITWISEANTICOLL 0xE4
#define MI_QUIT 0xE2
#define MI_RECBUF_OVERFLOW 0xCF
#define MI_SENDBYTENR 0xCE
#define MI_SENDBUF_OVERFLOW 0xCC
#define MI_BAUDRATE_NOT_SUPPORTED 0xCB
#define MI_SAME_BAUDRATE_REQUIRED 0xCA
#define MI_WRONG_PARAMETER_VALUE 0xC5
#define MI_BREAK 0x9E
#define MI_NY_IMPLEMENTED 0x9D
#define MI_NO_MFRC 0x9C
#define MI_MFRC_NOTAUTH 0x9B
#define MI_WRONG_DES_MODE 0x9A
#define MI_HOST_AUTH_FAILED 0x99
#define MI_WRONG_LOAD_MODE 0x97
#define MI_WRONG_DESKEY 0x96
#define MI_MKLOAD_FAILED 0x95
#define MI_FIFOERR 0x94
#define MI_WRONG_ADDR 0x93
#define MI_DESKEYLOAD_FAILED 0x92
#define MI_WRONG_SEL_CNT 0x8F
#define MI_RC531_WRONG_READVALUE 0x8E //LI ADDED 09-4-24
#define MI_WRONG_TEST_MODE 0x8C
#define MI_TEST_FAILED 0x8B
#define MI_TOC_ERROR 0x8A
#define MI_COMM_ABORT 0x89
#define MI_INVALID_BASE 0x88
#define MI_MFRC_RESET 0x87
#define MI_WRONG_VALUE 0x86
#define MI_VALERR 0x85
void rc522_init(void);
//u8 RC522_Handel(void);
//char PcdAuthState ( u8 ucAuth_mode, u8 ucAddr, u8 * pKey, u8 * pSnr );
char PcdSelect ( u8 * pSnr );
//char PcdWrite ( u8 ucAddr, u8 * pData );
//char PcdRead ( u8 ucAddr, u8 * pData );
void CalulateCRC ( u8 * pIndata, u8 ucLen, u8 * pOutData );
void rc522_write_setbit_mask(unsigned char reg,unsigned char mask);
void rc522_write_clrbit_mask(unsigned char reg,unsigned char mask);
char PcdRequest(unsigned char req_code,unsigned char *pTagType);
char PcdComMF522(unsigned char Command ,unsigned char *pInData ,
unsigned char InLenByte,unsigned char *pOutData,
unsigned int *pOutLenBit );
char PcdAnticoll(unsigned char *pSnr);
//
u8 rc522_read_1_byte(u8 address);
void rc522_write_1_byte(u8 address,u8 input);
//static u8 SPI2_RW_Byte(u8 byte);
void Delay(unsigned int time); //延时约1ms
void loop(void);
#endif
rc522.c
#include "rc522.h"
uint16_t g_surplusTime = 0;
static u8 SPI3_RW_Byte(u8 byte);
u8 FUNCTION_STR[60]={ 0};
unsigned char CT[2];//卡类型
unsigned char SN[4]; //卡号
unsigned char RFID[32]; //存放RFID 16字节数据
u8 KEY[6]={ 0xff,0xff,0xff,0xff,0xff,0xff}; //保存密码的缓存
//密码开光 //保存密码的缓存
const u8 BLOCK_KEY[16]={ 0xD2,0x17,0x02,0x06,0x22,0xD0,0xff,0x07,0x80,0x29,0x5A,0x89,0xE5,0x4B,0x71,0x32};
u8 DEF_A[6]={ 0xD2,0x17,0x02,0x06,0x22,0xD0}; //保存密码a
const u8 DEF_B[6]={ 0x5A,0x89,0xE5,0x4B,0x71,0x32}; //保存密码B
//默认的每个扇区最后块的数据
unsigned char RFID1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x07,0x80,0x29,0xff,0xff,0xff,0xff,0xff,0xff};
unsigned char status;
u8 rc522_init_flag=0;
//如果变成1 说明读取到 不会再读取
u8 read_control_ok_flag=0;
void Delay(unsigned int time) //延时约1ms
{
volatile unsigned int i;
while(time--){
i=12550;
#ifdef NEED_FEED_DOG
//stm8_1_wdog_feed(); //喂狗
#endif
while(i--);
}
}
//读取卡片内固定块4的姓名
//返回108 表示名字是8字节
//u8 rc522_s50_read_name(u8 *buff)
//{
// u8 temp8_ret=0;
// temp8_ret=fast_read_s50_block(4);
//
// if(temp8_ret==0) //密码成功 读取姓名
// {
// if(PcdRead(4,RFID)==MI_OK) //读取成功
// {
// //RFID[0] 姓名字节数 一个汉字=2字节 最多14字节
// //RFID[1]-RFID[14] 姓名
// //RFID[15] 校验 暂时不用
// for(temp8_ret=1;temp8_ret<=RFID[0];temp8_ret++)
// {
// buff[temp8_ret-1]=RFID[temp8_ret];
// }
//
//
// //再读取块6 场馆名称 有效时间
// if(PcdRead(6,&buff[16])==MI_OK) //读取成功
// {
//
//
// temp8_ret=temp8_ret+100;
//
// }
// else
// {
// temp8_ret=7; //7 读取失败
// }
// }
// else
// {
// temp8_ret=6; //6 读取失败
// }
//
// }
// else
// {
// //return temp8_ret;
// }
//
//
//
//
// return temp8_ret;
//}
//0是距离MCU较远的那个 小天线
//1是距离MCU较近的 大天线
//void rc522_select_ic(u8 channel)
//{
// rc522_channel=channel;
//
//}
//mode 0 擦除读取标志 1=连续读取 2=复位
//mode 3 只要电机在转动 就读取
//连续读取 直到 读取成功或者超时
//u8 rc522_s50_read_control(u8 mode,u16 max_cnt,u8 *buff)
//{
//
// u8 read_error_flag=0;
// u16 temp16_cnt1=0;
//
// //强制变成0 会继续读卡
// if(mode==0)
// {
//
// read_control_ok_flag=0;
//
// //全局变量设定为默认值
// status=MI_ERR;
// SN[0]=0x00;
// SN[1]=0x00;
// SN[2]=0x00;
// SN[3]=0x00;
//
// rc522_select_ic(1);
// rc522_init();
//
// return 0;
// }
// else if(mode==1)
// {
// while((read_control_ok_flag==0)&&(temp16_cnt1<max_cnt))
// {
// //这里可以做一个计数 读卡累计1000次 就再次初始化
// read_error_flag=0;
// if(PcdRequest(PICC_REQALL,CT)==MI_OK)//寻卡成功
// {
//
// }
// else
// {
// //rc522_init_flag=1;
// //return 2; //没有卡片
// //printf("err 1\r\n");
//
// read_error_flag=1;
// }
//
// if(read_error_flag==0)
// {
// if(PcdAnticoll(SN)==MI_OK)//防衝撞成功
// {
//
// }
// else
// {
// //return 3; //防衝撞失败
//
// read_error_flag=2;
// }
// }
// if(read_error_flag==0)
// {
// if(PcdSelect(SN)==MI_OK)//選卡成功
// {
// buff[0]=SN[0];
// buff[1]=SN[1];
// buff[2]=SN[2];
// buff[3]=SN[3];
//
// printf("read ok\r\n");
// read_control_ok_flag=1;
// }
// else
// {
// //return 4; //选卡失败
//
// read_error_flag=3;
// }
// }
//
// temp16_cnt1++;
// }
//
//
//
// if(temp16_cnt1>=max_cnt)
// {
// printf("rc522 timeout\r\n");
//
// return 3;
// }
// else
// {
// printf("ok cnt=%d\r\n",temp16_cnt1);
//
// return 0;
// }
//
//
// }
// else if(mode==3) //只要电机在转动 就读取
// {
while((read_control_ok_flag==0)&&(read_step_state()>0))
{
//这里可以做一个计数 读卡累计1000次 就再次初始化
read_error_flag=0;
if(PcdRequest(PICC_REQALL,CT)==MI_OK)//寻卡成功
{
}
else
{
//rc522_init_flag=1;
//return 2; //没有卡片
//printf("err 1\r\n");
read_error_flag=1;
}
if(read_error_flag==0)
{
if(PcdAnticoll(SN)==MI_OK)//防衝撞成功
{
}
else
{
//return 3; //防衝撞失败
read_error_flag=2;
}
}
if(read_error_flag==0)
{
if(PcdSelect(SN)==MI_OK)//選卡成功
{
buff[0]=SN[0];
buff[1]=SN[1];
buff[2]=SN[2];
buff[3]=SN[3];
printf("read ok\r\n");
read_control_ok_flag=1;
}
else
{
//return 4; //选卡失败
read_error_flag=3;
}
}
temp16_cnt1++;
}
// if(read_control_ok_flag==1) //選卡成功
// {
// //
//
// printf("card ok\r\n");
//
// //等待电动机停止
while(read_step_state()>0)
{
Delay(1);
}
//
// return 0;
// }
// else
// {
// printf("motor stop\r\n");
//
// return 4;
// }
//
//
// }
//}
u8 rc522_s50_read_sn(u8 *buff)
{
if(rc522_init_flag)
{
rc522_init();
rc522_init_flag=0;
}
//全局变量设定为默认值
status=MI_ERR;
SN[0]=0x00;
SN[1]=0x00;
SN[2]=0x00;
SN[3]=0x00;
//这里可以做一个计数 读卡累计1000次 就再次初始化
if(PcdRequest(PICC_REQALL,CT)==MI_OK)//寻卡成功
{
}
else
{
//rc522_init_flag=1;
return 2; //没有卡片
}
if(PcdAnticoll(SN)==MI_OK)//防衝撞成功
{
}
else
{
return 3; //防衝撞失败
}
if(PcdSelect(SN)==MI_OK)//選卡成功
{
buff[0]=SN[0];
buff[1]=SN[1];
buff[2]=SN[2];
buff[3]=SN[3];
}
else
{
return 4; //选卡失败
}
return 0;
}
快速读取返回当前的卡号 4个字节
//void read_current_card_sn(u8 *buff)
//{
// buff[0]=SN[0];
// buff[1]=SN[1];
// buff[2]=SN[2];
// buff[3]=SN[3];
//
//}
读取卡片内固定块5的余额
//u8 rc522_s50_read_money(u8 *buff)
//{
// u8 temp8_ret;
// temp8_ret=fast_read_s50_block(5);
//
// if(temp8_ret==0) //密码成功 读取金额
// {
// if(PcdRead(5,RFID)==MI_OK) //读取成功
// {
// //RFID[0] 金额整数部分 MSB
// //RFID[1] 金额整数部分 LSB
// //RFID[2] 金额小数部分 0-99
// //RFID[3] 正负符号 0正 1负 一般不用
//
// //最大金额 65535.99
// //最小金额 0.00
//
// for(temp8_ret=0;temp8_ret<4;temp8_ret++)
// {
// buff[temp8_ret]=RFID[temp8_ret];
// }
//
//
// temp8_ret=0;
// }
// else
// {
// temp8_ret=6; //6 读取失败
// }
//
// }
// else
// {
// //return temp8_ret;
// }
//
//
// return temp8_ret;
//}
//修改卡片内固定块5的余额
//mode 0 直接写入一个新的金额
//mode 1 增加某个金额
//mode 2 减少某个金额
//u8 rc522_s50_write_money(u8 mode,u8 *buff)
//{
// u8 temp8_ret;
// u8 temp8_buff[4]={0};
// u16 temp16_1,temp16_2;
//
// temp8_ret=fast_read_s50_block(5);
//
// if(temp8_ret==0) //密码成功 读取金额
// {
// if(PcdRead(5,RFID)==MI_OK) //读取成功
// {
// //RFID[0] 金额整数部分 MSB
// //RFID[1] 金额整数部分 LSB
// //RFID[2] 金额小数部分 0-99
// //RFID[3] 正负符号 0正 1负 一般不用
//
// //最大金额 65535.99
// //最小金额 0.00
// for(temp8_ret=0;temp8_ret<4;temp8_ret++)
// {
// temp8_buff[temp8_ret]=RFID[temp8_ret];
// }
// }
// else
// {
// temp8_ret=6; //6 读取失败
// }
//
// if(mode==0) //mode 0 直接写入一个新的金额
// {
// for(temp8_ret=0;temp8_ret<4;temp8_ret++)
// {
// RFID[temp8_ret]=buff[temp8_ret];
// }
// }
// else if(mode==1) //mode 1 增加某个金额
// {
// temp16_1=buff[0]<<8;
// temp16_1=temp16_1+buff[1];
// temp16_2=RFID[0]<<8;
// temp16_2=temp16_2+RFID[1];
// RFID[2]=RFID[2]+buff[2];
//
// //进位控制
// if(RFID[2]>100)
// {
// RFID[2]=RFID[2]%100;
// temp16_1++;
// }
//
// //金额整数部分
// //不考虑超过65535元的处理
// temp16_2=temp16_2+temp16_1;
// RFID[0]=temp16_2>>8;
// RFID[1]=temp16_2&0x00ff;
//
// }
// else if(mode==2) //mode 2 减少某个金额
// {
// temp16_1=buff[0]<<8;
// temp16_1=temp16_1+buff[1];
// temp16_2=RFID[0]<<8;
// temp16_2=temp16_2+RFID[1];
//
// RFID[2]=RFID[2]+buff[2];
//
// //进位控制
// if(RFID[2]<buff[2]) //减法不顾
// {
// RFID[2]=RFID[2]+100;
// temp16_1++;
// }
// RFID[2]=RFID[2]-buff[2];
//
//
//
// //金额整数部分
// if(temp16_1>temp16_2) //减法不够 报错
// {
// temp8_ret=7;
// }
// else
// {
// temp16_2=temp16_2-temp16_1;
// RFID[0]=temp16_2>>8;
// RFID[1]=temp16_2&0x00ff;
// }
// }
// }
// else
// {
// //return temp8_ret;
// }
//
// if(temp8_ret==0)
// {
// if(PcdWrite(5,RFID)==MI_OK) //写入成功
// {
// temp8_ret=0;
// }
// else
// {
// temp8_ret=8; //写入失败
// }
// }
//
// return temp8_ret;
//}
//0 成功
//2 没有卡片
//3 防衝撞失败
//4 选卡失败
//5 密码错误
//u8 fast_read_s50_block(u8 address)
//{
// if(rc522_init_flag)
// {
// rc522_init();
// rc522_init_flag=0;
// }
//
// //全局变量设定为默认值
// status=MI_ERR;
// SN[0]=0x00;
// SN[1]=0x00;
// SN[2]=0x00;
// SN[3]=0x00;
//
// //这里可以做一个计数 读卡累计1000次 就再次初始化
//
// if(PcdRequest(PICC_REQALL,CT)==MI_OK)//寻卡成功
// {
//
// }
// else
// {
// return 2; //没有卡片
// }
//
// if(PcdAnticoll(SN)==MI_OK)//防衝撞成功
// {
//
// }
// else
// {
// return 3; //防衝撞失败
// }
//
// if(PcdSelect(SN)==MI_OK)//選卡成功
// {
//
// }
// else
// {
// return 4; //选卡失败
// }
//
//
//
// if(PcdAuthState(0x60,address,DEF_A,SN)==MI_OK) //密码A
// {
// rc522_init_flag=1;
// return 0;
// }
// else
// {
// return 5; //密码错误
// }
//
//}
//void test_write_name(void)
//{
//
// u8 temp8_buff[16]={0};
//
// if(fast_read_s50_block(4)==0)
// {
// printf("块4开启成功\r\n");
//
// }
// else
// {
// printf("块4开启失败\r\n");
//
// return;
// }
//
// temp8_buff[0]=6;
// memcpy(&temp8_buff[1], "王二小", 6);
//
// if(PcdWrite(4,temp8_buff)==MI_OK) //写入成功
// {
// printf("写入姓名成功\r\n");
// }
// else
// {
// printf("写入姓名失败\r\n");
// }
//
// Delay(200);
//
//}
//void test_write_block(u8 address,u8 *buff)
//{
//
//
// if(fast_read_s50_block(address)==0)
// {
// printf("块%d开启成功\r\n",address);
//
// }
// else
// {
// printf("块%d开启失败\r\n",address);
//
// return;
// }
//
//
// if(PcdWrite(address,buff)==MI_OK) //写入成功
// {
// printf("写入成功\r\n");
// }
// else
// {
// printf("写入失败\r\n");
// }
//
// Delay(200);
//
//}
void rc522_init(void)
{
u8 temp8_2;
//复位
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
Delay(5);
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay(5);
rc522_write_1_byte(CommandReg,PCD_RESETPHASE);
Delay(1) ;
rc522_write_1_byte(ModeReg,0x3D) ;
rc522_write_1_byte(TReloadRegL,30) ;
rc522_write_1_byte(TReloadRegH,0) ;
rc522_write_1_byte(TModeReg,0x8D) ;
rc522_write_1_byte(TPrescalerReg,0x3E) ;
//开启天线发射
rc522_write_1_byte(TxASKReg,0x40) ;
Delay(5) ;
temp8_2 = rc522_read_1_byte(TxControlReg) ;
if(!(temp8_2&0x03))
rc522_write_setbit_mask(TxControlReg, 0x03);
temp8_2=rc522_read_1_byte(TxASKReg) ;
Delay(10) ;
}
//char PcdAuthState ( u8 ucAuth_mode, u8 ucAddr, u8 * pKey, u8 * pSnr )
//{
// char cStatus;
// u8 uc, ucComMF522Buf [ MAXRLEN ];
// u32 ulLen;
// ucComMF522Buf [ 0 ] = ucAuth_mode;
// ucComMF522Buf [ 1 ] = ucAddr;
//
// for ( uc = 0; uc < 6; uc ++ )
// ucComMF522Buf [ uc + 2 ] = * ( pKey + uc );
//
// for ( uc = 0; uc < 6; uc ++ )
// ucComMF522Buf [ uc + 8 ] = * ( pSnr + uc );
// cStatus = PcdComMF522 ( PCD_AUTHENT, ucComMF522Buf, 12, ucComMF522Buf, & ulLen );
//
// if ( ( cStatus != MI_OK ) || ( ! ( rc522_read_1_byte ( Status2Reg ) & 0x08 ) ) )
//
// {
if(cStatus != MI_OK)
printf("密码无权限\n") ;
else
printf("密码错误!!!\n") ;
// cStatus = MI_ERR;
// }
// else
// {
// //printf("密码A正确\n");
//
// }
//
// return cStatus;
//
//}
char PcdSelect ( u8 * pSnr )
{
char ucN;
u8 uc;
u8 ucComMF522Buf [ MAXRLEN ];
u32 ulLen;
ucComMF522Buf [ 0 ] = PICC_ANTICOLL1;
ucComMF522Buf [ 1 ] = 0x70;
ucComMF522Buf [ 6 ] = 0;
for ( uc = 0; uc < 4; uc ++ )
{
ucComMF522Buf [ uc + 2 ] = * ( pSnr + uc );
ucComMF522Buf [ 6 ] ^= * ( pSnr + uc );
}
CalulateCRC ( ucComMF522Buf, 7, & ucComMF522Buf [ 7 ] );
rc522_write_clrbit_mask ( Status2Reg, 0x08 );
ucN = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 9, ucComMF522Buf, & ulLen );
if ( ( ucN == MI_OK ) && ( ulLen == 0x18 ) )
{
ucN = MI_OK;
}
else
ucN = MI_ERR;
return ucN;
}
//char PcdWrite ( u8 ucAddr, u8 * pData )
//{
// char cStatus;
// u8 uc, ucComMF522Buf [ MAXRLEN ];
// u32 ulLen;
// ucComMF522Buf [ 0 ] = PICC_WRITE;
// ucComMF522Buf [ 1 ] = ucAddr;
//
// CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );
//
// cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen );
// if ( ( cStatus != MI_OK ) || ( ulLen != 4 ) || ( ( ucComMF522Buf [ 0 ] & 0x0F ) != 0x0A ) )
// cStatus = MI_ERR;
//
// if ( cStatus == MI_OK )
// {
// memcpy(ucComMF522Buf, pData, 16);
// for ( uc = 0; uc < 16; uc ++ )
// ucComMF522Buf [ uc ] = * ( pData + uc );
//
// CalulateCRC ( ucComMF522Buf, 16, & ucComMF522Buf [ 16 ] );
// cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 18, ucComMF522Buf, & ulLen );
//
// if ( ( cStatus != MI_OK ) || ( ulLen != 4 ) || ( ( ucComMF522Buf [ 0 ] & 0x0F ) != 0x0A ) )
// cStatus = MI_ERR;
//
// }
// return cStatus;
//
//}
//
//char PcdRead ( u8 ucAddr, u8 * pData )
//{
// char cStatus;
// u8 uc, ucComMF522Buf [ MAXRLEN ];
// u32 ulLen;
// ucComMF522Buf [ 0 ] = PICC_READ;
// ucComMF522Buf [ 1 ] = ucAddr;
//
// CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );
//
// cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen );
//
// if ( ( cStatus == MI_OK ) && ( ulLen == 0x90 ) )
// {
// for ( uc = 0; uc < 16; uc ++ )
// * ( pData + uc ) = ucComMF522Buf [ uc ];
// }
//
// else
// cStatus = MI_ERR;
//
// return cStatus;
//}
void CalulateCRC ( u8 * pIndata, u8 ucLen, u8 * pOutData )
{
u8 uc, ucN;
rc522_write_clrbit_mask(DivIrqReg,0x04);
rc522_write_1_byte(CommandReg,PCD_IDLE);
rc522_write_setbit_mask(FIFOLevelReg,0x80);
for ( uc = 0; uc < ucLen; uc ++)
rc522_write_1_byte ( FIFODataReg, * ( pIndata + uc ) );
rc522_write_1_byte ( CommandReg, PCD_CALCCRC );
uc = 0xFF;
do
{
ucN = rc522_read_1_byte ( DivIrqReg );
uc --;
} while ( ( uc != 0 ) && ! ( ucN & 0x04 ) );
pOutData [ 0 ] = rc522_read_1_byte ( CRCResultRegL );
pOutData [ 1 ] = rc522_read_1_byte ( CRCResultRegM );
}
/
void rc522_write_setbit_mask(unsigned char reg,unsigned char mask)
{
char tmp = 0x00;
tmp = rc522_read_1_byte(reg)| mask;
rc522_write_1_byte(reg,tmp | mask); // set bit mask
}
void rc522_write_clrbit_mask(unsigned char reg,unsigned char mask)
{
char tmp = 0x0 ;
tmp = rc522_read_1_byte(reg)&(~mask);
rc522_write_1_byte(reg, tmp) ; // clear bit mask
}
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
char status ;
unsigned int unLen ;
unsigned char ucComMF522Buf[MAXRLEN] ;
rc522_write_clrbit_mask(Status2Reg,0x08) ;
rc522_write_1_byte(BitFramingReg,0x07) ;
rc522_write_setbit_mask(TxControlReg,0x03) ;
ucComMF522Buf[0] = req_code ;
//PCD_TRANSCEIVE 0x0C //发送并接收数据
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,
1,ucComMF522Buf,&unLen );
if ((status == MI_OK) && (unLen == 0x10))
{
*pTagType = ucComMF522Buf[0] ;
*(pTagType+1) = ucComMF522Buf[1] ;
}
else
status = MI_ERR ;
return status ;
}
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 ;
u8 j;
switch (Command)
{
case PCD_AUTHENT:
irqEn = 0x12 ;
waitFor = 0x10 ;
break ;
case PCD_TRANSCEIVE:
irqEn = 0x77 ;
waitFor = 0x30 ;
break ;
default:
break ;
}
rc522_write_1_byte(ComIEnReg,irqEn|0x80) ; //
rc522_write_clrbit_mask(ComIrqReg,0x80) ;
rc522_write_1_byte(CommandReg,PCD_IDLE) ;
rc522_write_setbit_mask(FIFOLevelReg,0x80) ; // 清空FIFO
for(i=0; i<InLenByte; i++)
rc522_write_1_byte(FIFODataReg,pInData[i]) ; // 数据写入FIFO
rc522_write_1_byte(CommandReg, Command) ; // 命令写入命令寄存器
if(Command == PCD_TRANSCEIVE)
rc522_write_setbit_mask(BitFramingReg,0x80) ; // 开始发送
i = 6000 ; //根据时钟频率调整,操作M1卡最大等待时间25ms
do
{
n = rc522_read_1_byte(ComIrqReg) ;
i-- ;
}
while((i!=0)&&!(n&0x01)&&!(n&waitFor)) ;
rc522_write_clrbit_mask(BitFramingReg,0x80) ;
if(i!=0)
{
j=rc522_read_1_byte(ErrorReg);
if(!(j&0x1B))
{
status = MI_OK ;
if (n&irqEn&0x01)
status = MI_NOTAGERR ;
if(Command==PCD_TRANSCEIVE)
{
n = rc522_read_1_byte(FIFOLevelReg) ;
lastBits = rc522_read_1_byte(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<n; i++)
pOutData[i] = rc522_read_1_byte(FIFODataReg) ;
}
}
else
{
//printf("命令错误=%x\n",j);
status = MI_ERR ;
}
}
rc522_write_setbit_mask(ControlReg,0x80) ;// stop timer now
rc522_write_1_byte(CommandReg,PCD_IDLE) ;
return status;
}
char PcdAnticoll(unsigned char *pSnr)
{
char status;
unsigned char i,snr_check=0;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
rc522_write_clrbit_mask(Status2Reg,0x08);//寄存器包含接收器和发送器和数据模式检测器的状态标志
rc522_write_1_byte(BitFramingReg,0x00);//不启动数据发送,接收的LSB位存放在位0,接收到的第二位放在位1,定义发送的最后一个字节的位数为8
rc522_write_clrbit_mask(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; }
}
rc522_write_setbit_mask(CollReg,0x80);
return status;
}
//
u8 rc522_read_1_byte(u8 address)
{
u8 temp8_ret;
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
address<<=1;
address|=0x80;
SPI3_RW_Byte(address);
temp8_ret=SPI3_RW_Byte(0xff);//读取1个字节数据
GPIO_SetBits(GPIOB,GPIO_Pin_1);
return temp8_ret;
}
void rc522_write_1_byte(u8 address,u8 input)
{
//u8 temp8_ret;
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
address<<=1;
address&=0x7e;
SPI3_RW_Byte(address);
SPI3_RW_Byte(input);
GPIO_SetBits(GPIOB,GPIO_Pin_1);
//return temp8_ret;
}
//SPI分频是8 4不正常
static u8 SPI3_RW_Byte(u8 byte)
{
while((SPI3->SR & SPI_I2S_FLAG_TXE)==RESET);
SPI3->DR = byte;
while((SPI3->SR & SPI_I2S_FLAG_RXNE)==RESET);
return(SPI3->DR);
}
//把4个字节 转换成为10位 10进制数字
void convert_4u8_dec(u8 *input,u8 *output)
{
u32 temp32_1=0;
u32 temp32_2=0;
//printf("convert输入=%x %x %x %x\r\n",input[0],input[1],input[2],input[3]);
temp32_2=(u32)input[0];
temp32_1=temp32_1+temp32_2;
temp32_1=temp32_1<<8;
temp32_2=(u32)input[1];
temp32_1=temp32_1+temp32_2;
temp32_1=temp32_1<<8;
temp32_2=(u32)input[2];
temp32_1=temp32_1+temp32_2;
temp32_1=temp32_1<<8;
temp32_2=(u32)input[3];
temp32_1=temp32_1+temp32_2;
//printf("convert 1=%x %d\r\n",temp32_1,temp32_1);
temp32_2=temp32_1/1000000000;
temp32_1=temp32_1%1000000000;
output[0]=((u8)temp32_2)+0x30;
temp32_2=temp32_1/100000000;
temp32_1=temp32_1%100000000;
output[1]=((u8)temp32_2)+0x30;
temp32_2=temp32_1/10000000;
temp32_1=temp32_1%10000000;
output[2]=((u8)temp32_2)+0x30;
temp32_2=temp32_1/1000000;
temp32_1=temp32_1%1000000;
output[3]=((u8)temp32_2)+0x30;
temp32_2=temp32_1/100000;
temp32_1=temp32_1%100000;
output[4]=((u8)temp32_2)+0x30;
temp32_2=temp32_1/10000;
temp32_1=temp32_1%10000;
output[5]=((u8)temp32_2)+0x30;
temp32_2=temp32_1/1000;
temp32_1=temp32_1%1000;
output[6]=((u8)temp32_2)+0x30;
temp32_2=temp32_1/100;
temp32_1=temp32_1%100;
output[7]=((u8)temp32_2)+0x30;
temp32_2=temp32_1/10;
temp32_1=temp32_1%10;
output[8]=((u8)temp32_2)+0x30;
temp32_2=temp32_1;
output[9]=((u8)temp32_2)+0x30;
//printf("convert 2=%s\r\n",output);
}
void loop(void)
{
u8 temp8_2;
rc522_init();
temp8_2=0;
temp8_2=rc522_s50_read_sn(FUNCTION_STR); //读卡
if(temp8_2==2)
{
printf("天线首次读卡失败\r\n");
temp8_2=rc522_s50_read_sn(FUNCTION_STR); //读卡
}
if(temp8_2==2)
{
printf("天线无ic卡\r\n");
WaterControlGpioSetOutput(1);
g_surplusTime = 0;
DisplayTime(g_surplusTime);
}
else if(temp8_2==0)
{
Delay(15);
convert_4u8_dec(FUNCTION_STR,&FUNCTION_STR[10]);
FUNCTION_STR[20]='#';
FUNCTION_STR[21]=0x00;
printf("report*input=");
printf("%s",&FUNCTION_STR[10]);
WaterControlGpioSetOutput(0);
g_surplusTime++;
DisplayTime(g_surplusTime);
}
}
main.c
int main(void)
{
...
GPIO_Configuration(); //--//引脚配置
SPI_INIT();
rc522_init();
...
// 这里用TIM5每秒调用loop
StartTim5ToCountdown();
while(1)
{
// Delay(1000);
}
}
#define General_TIM5_IRQHandler TIM5_IRQHandler
void StartTim5ToCountdown(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
}
void StopTim5ToCountdown(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, DISABLE);
}
void General_TIM5_IRQHandler(void)
{
if(TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM5, TIM_FLAG_Update);
loop();
}
}
• 由 青梅煮久 写于 2021 年 03 月 22 日