今天,我们抽空来弄下STM32F103RBT6通过SPI方式驱动RC522 NFC模块读写S50复旦卡~6 H+ r& @* j0 Q. }
一个简单的下例子,NFC的应用在生活中随处可见了。我们这里的假设应用场景是在不同杯子
/ E l6 b# _0 k9 ~; O# G- V& N' I底部粘上复旦卡,来辨别不同的杯子TYPE型号~这里仅对块地址17的第一个字节进行判断!& x2 L2 D" [3 n
复旦卡就是常见的那种门禁卡钥匙扣形状的:: z9 R' h7 y8 Z5 \- k) D
' f6 _+ J- x3 U; d# W$ Q
主板用自制的STM32F103RBT6的一个小板:
4 m5 `4 d3 Q3 b% m
- M0 |" g0 B l
下载器用CMSIS DAP 带串口的:
& _. E, T6 h1 C1 {
+ M" Q. x+ q9 ^- H8 Q4 r! S好,下面开始接线:' o+ D* }7 {6 k+ s
" S) N) M* B# g( X. u* T接好线的图:/ v& J" G0 ~( T+ [" m$ d
& @# P5 ~( h7 X0 |
STM32F103RBT6 和RC522 及S50复旦卡就不多说了,网上大把资料。 M! V r% t* x* j
上程序:
% K, x/ d6 S( M& Wspi.h4 g. W1 h. ]! `0 E' N; J
- #ifndef __SPI_H
) U0 V0 c' v' `( k' u9 }% ] - #define __SPI_H
0 f& `. P. b3 ^# V2 ?6 o - #include "sys.h"
# i1 z) K2 C2 I- D. s' z, v, m - & m- S2 D- s, z8 L
2 |' ?1 k+ @( e. @, k9 ?- //#define RC522_RST PCout(7)& T3 o5 V Z* C
- #define RC522_RST PCout(7) //测试后恢复PCout(7)6 v* i9 v% T( {: u$ ?9 R" ~9 }# c e$ [
- #define RC522_CS PBout(9), x! ^7 }- v( S5 v! b
- #define SPIReadByte() SPIWriteByte(0)
: U* U, u! F. i& A n/ z - // SPI总线速度设置 " _ n. F4 Z4 J7 Z' Y* Y
- #define SPI_SPEED_2 0) ~0 s# t1 T* X8 o m" H
- #define SPI_SPEED_4 1
. `5 g' A# S) r5 P* E0 d% m - #define SPI_SPEED_8 28 r( Y" {, Z3 d1 O6 u1 {3 ?3 Y7 I
- #define SPI_SPEED_16 3( E. H7 T) f+ s9 ?0 k1 G; `6 N# L
- #define SPI_SPEED_32 4* |1 P3 O6 x, `$ n% X* f5 P/ s
- #define SPI_SPEED_64 5
2 W' ^+ D5 p3 H' M& z% \! [ - #define SPI_SPEED_128 6- V6 E3 X$ P* C
- #define SPI_SPEED_256 7
3 V3 J- r9 H. O) J/ z7 ^. ]/ x -
+ g3 h- J) m8 z0 i! w" K - void SPI2_Init(void); //初始化SPI口
' u m1 e- s! ~: V: M4 o - void SPI2_SetSpeed(u8 SpeedSet); //设置SPI速度
! o" ~8 u3 B) l2 p - u8 SPIWriteByte(u8 TxData);//SPI总线读写一个字节/ T q! w0 W" N$ [; Y( [, ?
-
8 Q/ c' t# c: `, M1 { S$ t - #endif
! N0 b! o( W% Y) R6 S+ W# Z - $ p% K2 D0 n( b0 ~7 O7 b
复制代码 spi.c0 h% G& ^. D) h& H* d; W, V; t- ~% P
- #include "spi.h", \: u, Z0 K: Y1 D* o$ ?! _
+ L: a; o/ M7 J: k3 _7 U- //这里针是对SPI2的初始化- Q* W2 y/ K( j: g, h1 e8 a
- void SPI2_Init(void): L) v/ S2 r+ H, A. F* P+ F( c
- { 7 |' R4 s5 h7 O ?$ ?/ C* D
- RCC->APB2ENR|=1<<3; //PORTB时钟使能
5 H) N t! J) q3 r* H0 M y' Q - RCC->APB2ENR|=1<<4; //PORTC时钟使能
% V2 {8 |9 j0 P - RCC->APB1ENR|=1<<14; //SPI2时钟使能
& e, I0 d+ H) m* @/ [; I0 Q) z8 k - GPIOB->CRH&=0XFFFFFF0F;
$ \% T& M& R) C9 G7 L2 i - GPIOB->CRH|=0X00000030;//PB.9 推挽输出
6 n3 d T8 {1 K; F. D; j1 i - GPIOC->CRL&=0X0FFFFFFF; ; j7 Y, x8 n: s1 l
- GPIOC->CRL|=0X30000000;//PC. 7 推挽输出
0 G. X* Y* w% K) U" I) J - // GPIOB->CRH&=0XFFFFFFF0;
# {9 U# t- p, C8 ]) W3 N - // GPIOB->CRH|=0X00000003;//PB. 8 推挽输出 此脚做测试用,测试完恢复PC7复位RFID功能
, _, y) O1 ^, ^+ S" [* e4 w - RC522_RST=1; //RC522 复位脚置1
8 `$ M% V9 U- p& f( H; T$ F - RC522_CS=1;% r: n9 Z# D) c; |; a
. r8 d1 C0 q3 [- * w" r+ u" C* d5 O( \$ W
- //这里只针对SPI口初始化( s7 ]% O# z" J' o
- GPIOB->CRH&=0X000FFFFF; / S! @- G% {0 t& {
- GPIOB->CRH|=0XBBB00000; //PB13/14/15复用
( ]7 F, D8 ]* U9 l - GPIOB->ODR|=0X7<<13; //PB13/14/15上拉
. u$ W1 y$ @7 m - SPI2->CR1|=0<<10; //全双工模式 u$ x8 D1 D7 L. g6 K
- SPI2->CR1|=1<<9; //软件nss管理4 c" j8 L5 C( h( y
- SPI2->CR1|=1<<8; ( u/ M( d& x6 A
* Q" \- m8 q0 {# i- SPI2->CR1|=1<<2; //SPI主机
, d8 L, M4 z! N! q+ R6 d5 o7 b - SPI2->CR1|=0<<11; //8bit数据格式
# d# W% I) T8 H - SPI2->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
/ t7 C, {( r+ ~6 T6 F+ t# ? - SPI2->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1 4 M& e- Q' D9 V6 D
- //对SPI2属于APB1的外设.时钟频率最大为36M., k' C* y, {( ^2 b0 \
- SPI2->CR1|=3<<3; //Fsck=Fpclk1/256
2 x; O9 z6 H1 I- b, v' l - SPI2->CR1|=0<<7; //MSBfirst
0 C; E* |5 i7 l: }" n - SPI2->CR1|=1<<6; //SPI设备使能
4 j3 Z; q! b* ?) h2 g7 z - SPI2_SetSpeed(5); ' v1 S) [3 t% y, f
- SPIWriteByte(0xff);//启动传输 6 w" L4 b0 X! g
- }
( W2 u* w/ W; a- w$ u - //SPI2速度设置函数% m% K- G8 \ N2 x0 t; d8 j6 ~
- //SpeedSet:0~7
3 {, E: g: h X0 ]2 w& Z - //SPI速度=fAPB2/2^(SpeedSet+1)9 X# A! B, g* ?6 @' A" z0 }
- //fAPB2时钟一般为90Mhz1 Z9 N2 l" q( | e
- void SPI2_SetSpeed(u8 SpeedSet)
. _. P* T& P Q# V! `/ A4 z - {" y( [; V6 m# Z& g2 J
- SpeedSet&=0X07; //限制范围1 ^1 S/ z1 ?9 { l
- SPI2->CR1&=0XFFC7;
0 S* p8 S- ]/ V7 S1 x- | - SPI2->CR1|=SpeedSet<<3; //设置SPI5速度 ! D- t, ~- u' d
- SPI2->CR1|=1<<6; //SPI设备使能 2 R- F5 L% j) Z/ K r
- }
7 a% i/ D: ` v* p& ^8 N5 e+ o - //SPI2 读写一个字节. M# I1 g$ i+ d5 M# x' Z8 X$ T
- //TxData:要写入的字节* g2 X: l V% M/ D
- //返回值:读取到的字节+ C' k5 y! ^5 K' X" J! o
- u8 SPIWriteByte(u8 TxData), f1 U. Y5 t2 q: h' w
- {
) C' |5 k) U$ X1 u! v - u16 retry=0;
, y$ g. w3 t4 ~8 J D j - while((SPI2->SR&1<<1)==0) //等待发送区空
% h7 S$ v) d* I( x) k+ O - {
3 v# S% x6 X% I9 q4 b( H - retry++;
6 X \" Z( u, a; p7 _' v - if(retry>=0XFFFE)return 0; //超时退出) t B* A# N- N" R' Y
- } $ e0 W: x L; \* M% W. Q# s3 Q7 G0 u
- SPI2->DR=TxData; //发送一个byte
7 w+ h! y: U6 R. N4 e+ q6 f- ^5 c - retry=0;
2 e' C6 H4 T% B8 R } - while((SPI2->SR&1<<0)==0) //等待接收完一个byte
0 |5 D3 L: I" N) A2 n - {9 y% _( d$ X6 S$ X: H
- retry++;
( I: L( P, m. E J) S - if(retry>=0XFFFE)return 0; //超时退出" d7 q# Z5 g3 ~0 f$ d
- } : b- I" S: X6 C6 s) c- ]2 t
- return SPI2->DR; //返回收到的数据
7 }5 p, G' v: t9 t/ f# j0 X6 ~ - }
+ ^) {6 U6 H: Z7 p; e
$ t8 c( y4 v% P: a
% i/ b" r/ j, O% h+ ~; r% U+ A2 Q' h
, }0 Z, {. V |: Q* e
复制代码 rc522.h
& X4 ~* P" a" C/ B" _- #ifndef _RC522_H_
6 w9 H7 x" a( j. v% G! I# I% O - #define _RC522_H_. _% a) u, U* J# Q8 O" o
' ~3 b/ D1 W8 j% [- #include <stm32f10x.h>
; ~3 m( [, R7 t( r( |; X# a7 M - #include "sys.h"5 ]0 I1 R& F3 A" P q
- #include "spi.h"
0 U4 T0 |2 G5 m: |. ^& G
' E/ m' @" Y+ H1 W4 ~0 o$ W- - U p j3 l, c2 {+ l
- extern u8 CupType;3 [, h( O: T+ g% F! f& x' E
) T# j0 ?* N* s1 A
$ }2 v- @" B4 Y9 T4 d# c- /////////////////////////////////////////////////////////////////////- Y; U$ o2 a5 o+ Q$ w0 l3 y% f
- //MF522命令字; k& `+ `& l: [# H) U; B
- /////////////////////////////////////////////////////////////////////
6 d+ L* S: O9 m! b% _ - #define PCD_IDLE 0x00 //取消当前命令
! b5 }4 e) y& M; F1 ~# N& F7 ]8 S - #define PCD_AUTHENT 0x0E //验证密钥# q" U8 i& X7 r; f( |2 X( O
- #define PCD_RECEIVE 0x08 //接收数据
+ I& V7 A; B) o) G) n0 m) q$ j - #define PCD_TRANSMIT 0x04 //发送数据
# A) j/ }, F4 ] B& O) W7 e - #define PCD_TRANSCEIVE 0x0C //发送并接收数据 J ~& u% G$ T7 D9 I
- #define PCD_RESETPHASE 0x0F //复位! c! `8 g9 | i) P* o
- #define PCD_CALCCRC 0x03 //CRC计算
7 u0 @9 a- U1 ?& t( j' ^
. j+ K c8 ]0 u- h4 ]% T8 D3 h- /////////////////////////////////////////////////////////////////////
) |1 L! w9 U: ~2 q1 c0 R - //Mifare_One卡片命令字
1 i) L# b8 j: k! C* i1 ~. W* t+ M - /////////////////////////////////////////////////////////////////////
9 h3 Q) e+ I; B* C, ~, Y% c5 ?% e& S - #define PICC_REQIDL 0x26 //寻天线区内未进入休眠状态6 \$ o [! `: ?
- #define PICC_REQALL 0x52 //寻天线区内全部卡
% M4 g7 r! }9 l - #define PICC_ANTICOLL1 0x93 //防冲撞) V; Z$ Q' L4 C( h3 w
- #define PICC_ANTICOLL2 0x95 //防冲撞
* K4 a/ w6 {1 Z5 @* R+ @' ~ - #define PICC_AUTHENT1A 0x60 //验证A密钥1 y7 c+ g& m$ e3 M* Z% ?
- #define PICC_AUTHENT1B 0x61 //验证B密钥+ j+ `& M2 E4 m. ~/ o! S
- #define PICC_READ 0x30 //读块
* R9 ], I# |8 V7 ~# h/ w0 `3 { - #define PICC_WRITE 0xA0 //写块
6 j2 Z2 [; m- K* F# r3 ` - #define PICC_DECREMENT 0xC0 //扣款" J; R5 r) w5 ~$ }6 n
- #define PICC_INCREMENT 0xC1 //充值# w3 n& i8 y. X# v4 I) T% u g
- #define PICC_RESTORE 0xC2 //调块数据到缓冲区
! H9 `* y3 s0 ~+ {- c( x: n4 P - #define PICC_TRANSFER 0xB0 //保存缓冲区中数据; Y8 N2 i: y5 O5 S
- #define PICC_HALT 0x50 //休眠7 k8 h2 I# \6 Y1 U4 F7 e
9 q. m+ D7 I, h: _4 b' `) B8 X- /////////////////////////////////////////////////////////////////////
# s) M8 {6 C+ X9 |* `$ S - //MF522 FIFO长度定义( c5 h$ [1 A% S) Z% F1 v) k8 Y
- /////////////////////////////////////////////////////////////////////
* n: J. C8 l+ [! a - #define DEF_FIFO_LENGTH 64 //FIFO size=64byte0 q4 r, t; Q: i2 P; Z
- #define MAXRLEN 18
3 {9 y W: H b - ' g, [* ~8 O; l9 s4 E1 H
- /////////////////////////////////////////////////////////////////////; W1 ?; J) X& `! K- R0 `: q: h
- //MF522寄存器定义
4 B6 o. z' r. C8 B; ~ - /////////////////////////////////////////////////////////////////////# Z7 g( l$ U% w( ?: s0 z: W
- // PAGE 0
l8 @: d$ ]9 j& f6 c: E+ f3 U$ Y - #define RFU00 0x00 9 g. v: d) _8 S2 x2 k- E
- #define CommandReg 0x01 * ] c1 R5 A/ S( _4 e- G3 K4 Y
- #define ComIEnReg 0x02 ( T8 n" v7 w. p D- e1 ~5 S2 n+ U
- #define DivlEnReg 0x03 $ D! Q! F9 U4 k8 w- E8 \5 q
- #define ComIrqReg 0x04 E, s) l6 W s ^
- #define DivIrqReg 0x057 w, E+ p6 i' {
- #define ErrorReg 0x06 # x' D& e; e. }
- #define Status1Reg 0x07
6 d) d" v$ {1 o* v& q - #define Status2Reg 0x08 / a6 t, ^+ N( _/ r
- #define FIFODataReg 0x09
1 o' B7 g& j2 U1 R - #define FIFOLevelReg 0x0A$ [; y5 c2 s2 \, j+ |3 A2 A& i8 V0 K
- #define WaterLevelReg 0x0B
+ B: N6 T0 i) v. w" w) R. G% N - #define ControlReg 0x0C
1 r% |: N1 D) a$ c$ _2 A6 N# d - #define BitFramingReg 0x0D* F6 E; I$ B0 ]4 W% t/ S
- #define CollReg 0x0E. C2 s) R; f5 p+ N0 d9 \) z
- #define RFU0F 0x0F- [4 l9 n6 A+ q9 y# u
- // PAGE 1
7 t! Y9 @6 d2 C, I! x% l3 z - #define RFU10 0x10
/ u2 i6 m* X+ N0 Z, d* l3 y, n/ d5 Q - #define ModeReg 0x116 V& Y+ Y! v, j& h; U" u7 B
- #define TxModeReg 0x12
6 e2 k5 I/ [1 B4 c% i - #define RxModeReg 0x13
/ k D U8 T0 Y2 q - #define TxControlReg 0x14" }1 G; k3 o0 A2 i; y
- #define TxAutoReg 0x15
" L" T; C% g- H2 z' X - #define TxSelReg 0x165 f$ Z/ q8 a M3 d& J, @
- #define RxSelReg 0x17! A4 c' `% f3 J& s7 E# Z: M
- #define RxThresholdReg 0x18' }2 V6 v/ ^; {, y( w
- #define DemodReg 0x19
$ e& t6 @( z6 M6 P e i+ h$ o. Z3 l- a - #define RFU1A 0x1A
& z( ^* J0 @1 z* `- v. f r1 ]6 l - #define RFU1B 0x1B: O8 h: T2 ^3 B3 T8 H& g
- #define MifareReg 0x1C
8 ?2 r3 I, P+ c# T- i - #define RFU1D 0x1D
. q9 H* P' s' ~) V+ W" m - #define RFU1E 0x1E
$ P4 L! }$ n- @, n- R0 c' Z% ` - #define SerialSpeedReg 0x1F
5 w, {- W4 {4 K7 C ]6 _ - // PAGE 2 E6 p% Q- Y; Y/ ~% y
- #define RFU20 0x20
8 M. k9 Z( I$ m - #define CRCResultRegM 0x21
0 ~" p$ }: }" G" x9 h - #define CRCResultRegL 0x22
& B0 L1 x3 w- |+ `- E# G( u i9 E6 o6 C2 R - #define RFU23 0x23
+ H) d0 |; D+ g: {2 k. u$ Z - #define ModWidthReg 0x241 N9 K, o* O ~0 T9 a
- #define RFU25 0x25
& e8 l2 J! s, r - #define RFCfgReg 0x26: {* F/ O3 ?; ? W% T
- #define GsNReg 0x274 J! }+ K; Z: F
- #define CWGsCfgReg 0x28; [, D1 _( A! H
- #define ModGsCfgReg 0x295 u" N4 T' x) Z
- #define TModeReg 0x2A/ \8 i) L% ^9 N! e, a$ M% e" X
- #define TPrescalerReg 0x2B
3 ~( B& `+ H- Z1 ? - #define TReloadRegH 0x2C
" z# @/ w, J* B8 I& M# T/ R1 c - #define TReloadRegL 0x2D6 C; w: o2 o7 |, k* i6 k
- #define TCounterValueRegH 0x2E+ J" \9 g- [3 ~# b& i: B, u4 G
- #define TCounterValueRegL 0x2F( s6 S ^+ x. F k
- // PAGE 3 ! ]; F1 M% D; S; J
- #define RFU30 0x30$ X" N6 W- v! d6 M) \1 f. i2 L, W
- #define TestSel1Reg 0x315 X' J \% R: ?; i
- #define TestSel2Reg 0x32
! Z# G' C+ e1 n/ k - #define TestPinEnReg 0x33& G/ c' S. C" q! Y
- #define TestPinValueReg 0x34
6 C. ]9 F8 g! m( Y2 r - #define TestBusReg 0x357 o3 `: @0 |7 I. L9 S$ P+ \
- #define AutoTestReg 0x36
V N/ P8 O9 m( g - #define VersionReg 0x37- X0 n, R4 J1 \( ]; s, d% G
- #define AnalogTestReg 0x38 S# P/ i. s! w$ t
- #define TestDAC1Reg 0x39 ; O3 j: ~4 R: N* p; U9 W+ ]3 ?& I
- #define TestDAC2Reg 0x3A ; a/ B8 J' V2 k3 c1 w+ o# }8 h/ S
- #define TestADCReg 0x3B
; u+ c( R0 a* k( A& r) _ - #define RFU3C 0x3C
# ]9 c" O, ~/ y8 d3 T' U- j - #define RFU3D 0x3D : [! R: Y( c9 C4 x. D
- #define RFU3E 0x3E
+ u% S& o) z4 M& d' a0 l1 t4 Z - #define RFU3F 0x3F9 Z% e( e+ t4 T' A6 ?2 h
% d; F1 E$ l' x1 u1 j8 _" j. L, J- /////////////////////////////////////////////////////////////////////
; x6 |" j' W' N& e6 E - //和MF522通讯时返回的错误代码
2 |2 S! p7 d/ W4 W - /////////////////////////////////////////////////////////////////////
c' Q `2 x1 j; g - #define MI_OK 0) e( G7 m: U5 d; ?
- #define MI_NOTAGERR 12 w8 C, I9 f5 y
- #define MI_ERR 2
5 k8 v8 }2 |& w, U1 w+ ^5 N
2 P* j; i% ?0 b% [3 f- #define SHAQU1 0X01. S" L7 }2 H3 w- l5 J) z8 E
- #define KUAI4 0X047 _5 u$ T9 G1 o: H( M5 T, Q- _
- #define KUAI7 0X07 ?4 d+ K* T$ Y
- #define REGCARD 0xa1( k: d2 x0 O7 c1 V2 I3 B
- #define CONSUME 0xa2
% H* p& I! }) k( X+ F - #define READCARD 0xa36 v1 g$ _3 X8 }: e0 J6 f9 _
- #define ADDMONEY 0xa4
/ C9 s7 N) A) m4 f. n' U- E' G - ! z5 w' i* e1 \% z* |* R# t" W
- //
6 ]9 h- L' f$ p( w - //#define spi_cs 1;$ _% H* ^$ x& V9 x8 k
- //sbit spi_ck=P0^6;
0 f# r' P F# K' ?# g - //sbit spi_mosi=P0^7;) H, I' b1 c; u" Y5 x; c! `
- //sbit spi_miso=P4^1;
, C4 ^& \8 u1 v) q - //sbit spi_rst=P2^7;: F/ Y) T- W' G" d
- #define SPIReadByte() SPIWriteByte(0)# N4 C% r; a, Q8 M, m" ]- E
- //u8 SPIWriteByte(u8 byte);( x/ M8 _* t# |/ p2 X$ |4 g0 A
- //void SPI2_Init(void);
) M% D( ]7 C3 _; L' T - , r2 J& h4 B9 a" Z( a
- + z1 l4 v6 a8 x# [
- //#define MYRC522_CS PAout(4)
`& S1 M. m& ]- S& e - //#define MYRC522_RST PAout(6)
' D' B' Y% \( D9 M( I( v" F - : r; l8 m5 d+ J+ R2 T% r5 o/ x' M
" {! x6 ^0 X) W/ O' W$ W- C- ! T( u" g+ c4 |' P2 a
- void InitRc522(void);
9 B/ s: r$ C3 y - void ClearBitMask(u8 reg,u8 mask);) u; X# W; F O/ o" k5 K
- void WriteRawRC(u8 Address, u8 value);) m- l/ ~& _7 }% S6 y2 ], q
- void SetBitMask(u8 reg,u8 mask);
$ r" V1 c8 [3 ]+ E3 G4 U% ^ - char PcdComMF522(u8 Command, h1 M# U, v8 |, S$ \
- u8 *pIn ,
@1 P+ f5 r% ^ - u8 InLenByte,8 c C5 @" d9 ]4 s% Q
- u8 *pOut , . x+ ?( D0 _' S5 x! V0 R
- u8 *pOutLenBit);, {8 T. \' b% v
- void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut );
' j! b7 @9 M% Q1 f2 ~/ u- e - u8 ReadRawRC(u8 Address);7 w& a# m ~$ y" |" P
- void PcdAntennaOn(void); ^( T# {4 U, P' ~' l' d
' v- y9 v q% l4 K O- char PcdReset(void);
* c' f( _% I+ m" R2 Y - char PcdRequest(unsigned char req_code,unsigned char *pTagType);
1 S* R# m3 l! }/ g. f - void PcdAntennaOn(void);
3 x; T3 L3 U4 t - void PcdAntennaOff(void);8 m7 V& X. ?: R: s
- char M500PcdConfigISOType(unsigned char type);
# e4 Q" R0 X" D - char PcdAnticoll(unsigned char *pSnr);
, C1 }7 C. Z% Z - char PcdSelect(unsigned char *pSnr);# k1 V! ? y7 v0 A Y( E
- char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr);7 }1 |* L7 k6 w1 ~2 Q; D
- char PcdWrite(unsigned char addr,unsigned char *pData);" p9 f. C2 n* I/ `
- char PcdRead(unsigned char addr,unsigned char *pData);
: S9 x8 F5 f" |( O- s, i2 b7 ]& O - char PcdHalt(void);! @0 `6 g9 x. D9 K
- void Reset_RC522(void);
' q, A& M% r) d# h% {9 }& ]# r - u8 RfidTest(void);! s$ H7 s7 {2 @
- u8 ReadCupType(void);; o* Z% {/ @. w2 I7 p
- u8 WriteCupType1(void);, m; g! v, Y& b# M1 f p
- u8 WriteCupType2(void);' R P ^: Y- Y7 g3 E) N3 i
6 j# o X. x0 R( y/ c3 I( I- #endif5 x5 e9 s7 T" R+ O4 B
复制代码 rc522.c* y/ J5 k' I" E' N8 H3 v
- #include "sys.h"
h: m5 N& Y: k - #include "delay.h"
" b) H* U) q! j! k9 i1 q4 I - #include "rc522.h"
& S2 |+ U0 K' S. K& m - #include <stdio.h>& k3 b/ b. B! z- X
- #include <string.h>
" m* N3 t4 T7 x% a0 k# l6 r - #include <ctype.h>& K' A. l' \6 @2 c. `
- #include <stdlib.h>
9 w! g q0 F5 |& T' C! m0 n" y - #include <stdarg.h>, g3 [$ {& @' k" \
- #include <math.h>
6 S1 t) j' @5 n B) C1 k8 n
* H( F/ E0 ~1 G- u8 CupType;
( `$ v& K8 n; a' V# c7 | - $ D( N( v# P F; R; D/ R7 b
- /*0扇区的第0块是不能写的,只能读,前4字节是卡片ID*/* F/ i W7 _- A0 x* @9 u
- /*块3前6字节是A密钥,中间4字节是控制块,后6字节是B密钥*/
2 \+ x) G' C- N2 c9 _/ w - /*扇区0:0-3块 扇区1:4-7块 扇区2:8-11块 扇区3:12-15块*/6 \' F6 p' i2 ^9 {- p3 B, b
- /*3、7、11、15块存储密钥*/
0 c. e, o/ r2 H) i+ o - void delay_ns(u32 ns)) q; t7 ~& ^) Y \2 _) H
- {
/ h" X2 d& y" M- Y6 {9 ]6 W, j$ V - u32 i;; D; T. `# n) R! `: p6 l
- for(i=0;i<ns;i++)
4 ?; m. V1 Y- D# l - {
8 p/ p9 Y- w9 V# I5 q: } - __nop();
$ ?. m7 g5 o5 r$ D' Z7 i6 F3 y6 Z - __nop();
& a1 F% B( S2 e1 F- r9 T: B - __nop();% I e% ]" y( z3 k& c
- __nop();3 i4 y+ q5 c/ Q2 ^$ n- X
- __nop();
# y- y' ?% M9 I4 c5 ~9 A! b6 ^ - }0 |" o1 p* Y9 u E
- }* L; j- ]) g2 S. a1 ^) p
/ a; d! a2 v( L* P* N- % g% r) y+ }/ m P: ~* m9 Z
- void InitRc522(void)
}1 q6 F w- ^2 ] - { E8 a! g2 _. b1 r
- SPI2_Init(); {7 m9 I' `4 s! y
- PcdReset();- u& `1 p! u! y% Q, s! Y" E
- PcdAntennaOff(); 3 _# a. m2 E A) g8 q1 x. S6 W
- PcdAntennaOn();
/ _2 D3 ^8 y. Z N% U- a3 Z - M500PcdConfigISOType( 'A' );
& l) Z' l. Y+ U- p4 E7 q! [ - }& {$ d8 v& b2 f+ z9 I
- 5 y3 Y& F( y& m) H
- void Reset_RC522(void)
: @5 b- A* m" n" K - {
5 e( W4 h) H( z, \3 A) T - PcdReset();
) B5 F5 a' \2 c5 C% C$ v - PcdAntennaOff(); 3 Q R& ]8 \. [3 k! f# h
- PcdAntennaOn();3 D2 f/ T8 K( L
- }
5 H' w' S# K5 a5 y" U+ s6 e - /////////////////////////////////////////////////////////////////////
' d( x, G9 w2 P& R4 u6 S - //功 能:寻卡! F, P& i3 v7 e! I$ _" @. K
- //参数说明: req_code[IN]:寻卡方式
: j) l1 t, `1 k1 W - // 0x52 = 寻感应区内所有符合14443A标准的卡/ b1 J, ~5 @1 F d1 Y0 Z
- // 0x26 = 寻未进入休眠状态的卡
4 p& E0 W @! q# B b/ Y4 R - // pTagType[OUT]:卡片类型代码) C3 p% {, P2 Y0 I) l; E- y( C
- // 0x4400 = Mifare_UltraLight$ r2 L$ y' }: ?; O
- // 0x0400 = Mifare_One(S50)
2 Z% g8 c7 i9 q' P9 j2 B* l8 ? - // 0x0200 = Mifare_One(S70)7 \. w5 q8 k& h5 k/ v3 T1 F
- // 0x0800 = Mifare_Pro(X)
Z# P7 d; z' m. L* U) M - // 0x4403 = Mifare_DESFire
4 F- v5 J# M' J) K7 A- E9 E - //返 回: 成功返回MI_OK
8 v2 i$ }# }0 {4 {: _ - /////////////////////////////////////////////////////////////////////: g5 j/ U2 X6 b+ W, g! P
- char PcdRequest(u8 req_code,u8 *pTagType)/ q% ~) _+ j$ L9 ^) j& P; k' W
- {
7 X! L% w" k0 ^# o; l0 ]) ~, P7 l. x - char status; 3 i8 o5 P* {; \& f
- u8 unLen;2 F+ w+ U* u4 R2 l: b$ y
- u8 ucComMF522Buf[MAXRLEN];
6 c2 f/ G- J- C( s1 ?6 V
: C- z5 I, R* ?( V% W- ClearBitMask(Status2Reg,0x08);
/ V N& x# ~. |3 ^ - WriteRawRC(BitFramingReg,0x07);
+ D% v [% Z# j, c4 l7 G - SetBitMask(TxControlReg,0x03);( A; q C# u9 F9 O' s( d% B
-
* r+ } T, u. ~ - ucComMF522Buf[0] = req_code;
) D( D2 T6 ^" U/ q+ M, w - & A7 e( x' y' g
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
; }) p' N( z$ O8 s9 O& g# d+ V- |& C
6 z+ ]2 W- e' P5 P2 W/ H) ]- if ((status == MI_OK) && (unLen == 0x10))% S# I& W& B5 P1 {: y) Q8 G
- {
8 l& C; O" d8 b8 X; k - *pTagType = ucComMF522Buf[0];
& J- |2 w: W% |2 x, g6 G" V' i; m - *(pTagType+1) = ucComMF522Buf[1];! d5 C& G9 a7 i
- }
0 K( O; c5 z8 l( @ - else
: F! s# z+ ^* E' O% @ - { status = MI_ERR; }
( Q* K( n' L3 ?- B: k -
6 t* `% n" v) t - return status;% v' r) H* j) u3 m
- }
/ R* r+ o, E4 K. p" b - ( d: h' K, }0 W0 y$ x2 H
- /////////////////////////////////////////////////////////////////////
7 b# l( U# B. D, C+ g. o - //功 能:防冲撞8 x6 t/ ~5 X Z0 X, f! U
- //参数说明: pSnr[OUT]:卡片序列号,4字节) l7 f" l. I! e! X
- //返 回: 成功返回MI_OK0 S' \- }& m8 y7 m* k# y1 W0 b
- ///////////////////////////////////////////////////////////////////// - i; o& I+ ]5 f8 m+ f& I: p
- char PcdAnticoll(u8 *pSnr)) ?$ ~5 ]3 L. Z8 ?# ?; o
- {
& h3 ?: \/ a7 P8 a- W8 c* E - char status;/ i3 ]/ Z& j i& Z* V6 v7 f: {
- u8 i,snr_check=0;
& h# s* _3 g' F, }3 r - u8 unLen;
( H7 ?% h& j, R( _ - u8 ucComMF522Buf[MAXRLEN]; 6 `+ J3 L( ?& j( D s- [
-
7 O, v6 W% n, |9 O* W
1 J3 K- b! Z. @1 F/ h# M R# T- ClearBitMask(Status2Reg,0x08);5 E4 y4 C& B8 L7 z) D3 \/ B
- WriteRawRC(BitFramingReg,0x00);* [0 v: v2 Q x- w
- ClearBitMask(CollReg,0x80);, b7 R2 D. c; \3 K" E2 ~/ _' G
-
' C& D ?) T$ F3 |( V8 n- a - ucComMF522Buf[0] = PICC_ANTICOLL1;
/ E* W% z; s; `9 k8 v; A( D - ucComMF522Buf[1] = 0x20;+ d0 m/ c- L# L; g+ r
- % E" A4 S, h: y% W) _1 F% H
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);8 f2 M- X1 [& @9 D% K% V" X
- ' z6 R0 u1 q n& v: B* K& R
- if (status == MI_OK)1 \0 ~0 Y4 \/ B4 ~0 S+ h
- {
6 |2 E k K3 n) e - for (i=0; i<4; i++){ 9 Q0 q6 T& i. g: `4 |
- *(pSnr+i) = ucComMF522Buf[i];
1 @, F, D' S8 p g$ d0 l: U' W - snr_check ^= ucComMF522Buf[i];: x0 g3 }3 Y7 y) x7 N% J& |
- }: f* F& `3 ~7 N' [5 { \% H
- if (snr_check != ucComMF522Buf[i]){
: O4 w3 ]0 Z/ |- b v - status = MI_ERR; " _5 [6 E( }: ?3 L4 Y
- }
/ z5 z+ ]4 z& ^ - }
1 R) T9 \' e" }4 C }. y% {: L - " N) F: h! r9 s
- SetBitMask(CollReg,0x80); _# ^9 e' ?+ B- C1 ]' }
- return status;4 P1 @% y' F0 \& P- _3 X
- }; t/ a9 o [9 I6 c
- ! f* I9 r, X Q. `0 [/ {! x
- /////////////////////////////////////////////////////////////////////# i' f: @( }1 D+ m! A6 J. f
- //功 能:选定卡片
0 B T7 Y8 e5 }* n - //参数说明: pSnr[IN]:卡片序列号,4字节0 g3 Z6 _" P( u/ X8 u; {2 [
- //返 回: 成功返回MI_OK5 `$ f7 U1 A2 ]( U
- /////////////////////////////////////////////////////////////////////
x% ? {5 a5 C; U- ? - char PcdSelect(u8 *pSnr)
3 @2 k( U/ q6 A+ G# {5 _7 u - {: [* d n5 v1 N
- char status;
( [ [' p8 x6 l4 J4 X - u8 i;) H! h" {. G7 I& f) X
- u8 unLen;0 m# E! i9 P- [4 l; @
- u8 ucComMF522Buf[MAXRLEN];
* [3 J6 I) i8 g6 i& S6 r2 } -
0 e# z8 @% C- `' c/ r, u - ucComMF522Buf[0] = PICC_ANTICOLL1;! a3 @/ P4 n% |5 ?) q& c& [" F& K6 c: e
- ucComMF522Buf[1] = 0x70;5 [2 E- d1 {* n3 u4 o
- ucComMF522Buf[6] = 0;
$ Y' J& H$ Z- C- }% R" B - for (i=0; i<4; i++)3 P [; R2 l0 W5 ?$ ?
- {# X5 S1 n7 H$ t$ E
- ucComMF522Buf[i+2] = *(pSnr+i);0 y7 G4 v( [# F
- ucComMF522Buf[6] ^= *(pSnr+i);
1 C% |" @ q) w# J8 n - }
0 `1 b6 ?& H/ O8 E - CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);; S7 q/ P3 j L1 |! U- G$ n
-
) q+ [+ c' @, u9 O# X8 r/ Z' u; E - ClearBitMask(Status2Reg,0x08);4 L; Q* o: T5 G p
- : D2 y; R$ ?# F+ }6 D1 ^8 z
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
' E: G7 w4 y+ e" |6 B% T; s! }0 v - ) b1 Z: V0 j+ P7 J
- if ((status == MI_OK) && (unLen == 0x18))& E1 V! P4 ^. m
- { status = MI_OK; }
. p" E) d' b: a0 w5 i6 N - else3 {( [0 A U; p6 x6 l" ?2 u) t) R* Q
- { status = MI_ERR; }$ r4 X; E% E- S9 H% H/ G
- K" F$ a s6 ~8 @1 \: V- return status;8 [& X' |( l) r
- }% q% Z$ n9 O! j. c/ W& q4 @
* a3 t# x( { J- /////////////////////////////////////////////////////////////////////
( @7 M0 Z! C( p7 F - //功 能:验证卡片密码
' Y' d+ a. O! w - //参数说明: auth_mode[IN]: 密码验证模式
H; W8 Y% |2 c/ } - // 0x60 = 验证A密钥
% a9 [9 O" l$ ?2 n - // 0x61 = 验证B密钥 ) h' p, O7 C9 [% g8 g
- // addr[IN]:块地址7 o' D2 }: y# y$ C
- // pKey[IN]:密码
9 t" X+ K6 Z2 v2 f7 y9 E* s7 [ - // pSnr[IN]:卡片序列号,4字节
; ~1 f; T1 X7 O' j - //返 回: 成功返回MI_OK/ n8 e( r5 B0 G% t" e
- /////////////////////////////////////////////////////////////////////
s: h1 ^, j: P+ N( N& A3 o, O - char PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr)
. L# P' m# g+ l. ]# Y - {
$ l) O3 _0 W' I G7 C - char status;
0 J% j% [+ V& p) ?* n4 m - u8 unLen;
6 d; U5 f7 i* W- f }& V& C( P - u8 ucComMF522Buf[MAXRLEN]; $ j" O. M P1 z2 c' D; O8 B% a
- 2 Y$ i4 s i* a
- ucComMF522Buf[0] = auth_mode;+ `4 I. k% {7 T+ X
- ucComMF522Buf[1] = addr;
4 a4 c8 w/ D( f$ w2 i9 z - memcpy(&ucComMF522Buf[2], pKey, 6);
: \ U' M* m% X6 _3 h - memcpy(&ucComMF522Buf[8], pSnr, 4); " r/ f2 V! w4 |- ]. B1 c+ a3 S
- ; N# b& d2 T- x0 h% b1 P# ]
- status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
) x" ] b* _. F3 G% a - if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08))). [; q" S+ ?6 W8 n m( F0 ~2 H
- { status = MI_ERR; }
) F6 s3 p6 U9 G! X" c; ?5 z, g9 Y+ n -
2 q5 `. N8 A" U4 Y; \1 l O# B - return status;1 Z) H: K4 W, s+ @% D5 a, d
- }/ X1 z6 \* ` s2 t
- ( q5 P( O: v/ K$ _; o5 e
- /////////////////////////////////////////////////////////////////////
9 T" D; \1 I" j+ l - //功 能:读取M1卡一块数据
/ {/ z) F. q# j - //参数说明: addr[IN]:块地址# A& b9 _; K) T: m. X# j% q
- // p [OUT]:读出的数据,16字节
, K, s3 w) R; u* n2 [0 ^! c - //返 回: 成功返回MI_OK
% ?6 h$ A: R1 ?4 N - /////////////////////////////////////////////////////////////////////
" ~7 s8 B) z4 G - char PcdRead(u8 addr,u8 *p )
5 d1 d# G2 H6 i7 ?1 W/ z3 v y - {: Q6 b$ }( Z1 c- ]5 n
- char status;
8 v! H$ C0 G( I* m- G/ i5 m - u8 unLen;
9 e _: S; k2 }9 v/ D, M - u8 i,ucComMF522Buf[MAXRLEN];
$ i7 v8 R% z5 _
* W) w9 y* A! r$ Y- ucComMF522Buf[0] = PICC_READ;
6 {0 t8 h$ \, w9 t6 a# u - ucComMF522Buf[1] = addr;8 e& @- @- X8 P5 H1 d% b& z
- CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
8 J" \9 N3 H5 Q6 ^; U, z: z% l -
5 j( k Y) Y9 S# } - status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);; E1 _+ m# x0 m" s/ d
- if ((status == MI_OK) && (unLen == 0x90)) T( O( \, o2 A0 u
- {; Z1 F/ E1 P3 w' i. s& M
- for (i=0; i<16; i++)
1 N/ J: z/ x- k4 J* }4 U - { *(p +i) = ucComMF522Buf[i]; }
2 J4 W; e& k' J! [) t - }
3 P1 R, N e$ Y3 l' k4 i - else
1 K) ?, z$ \- c0 a' q% i. w - { status = MI_ERR; }
: c- W$ ~( C4 K; r - B" u) r: Y k: a% q. L
- return status;6 ~% P9 x6 G& j# Q0 v$ @7 }
- }
* ~, F8 q( ^9 w) t1 Y- _
8 Z( ^8 W" R5 @- /////////////////////////////////////////////////////////////////////! I# M9 {; E2 b- D- W+ a" I
- //功 能:写数据到M1卡一块1 _7 W& ], b* ^+ F/ O v
- //参数说明: addr[IN]:块地址
2 x8 }5 c' e/ X - // p [IN]:写入的数据,16字节
# r( ^3 p" z& T3 l3 d - //返 回: 成功返回MI_OK /*读01扇区数据,改密码只能写3、7、11、15扇区*/
/ L4 W/ }) F Q - /////////////////////////////////////////////////////////////////////
* J/ _% t2 V0 z! M( s v - char PcdWrite(u8 addr,u8 *p )
# `- L' Z6 B1 `6 _1 g) p - {) z! X2 p2 ?$ E; J
- char status;8 N; M& R5 N9 |+ c0 {! b
- u8 unLen;
. j' B% S1 ]- X. T - u8 i,ucComMF522Buf[MAXRLEN]; : U; v" k9 n% P, [+ H
- # j3 h& a7 ~# C- H
- ucComMF522Buf[0] = PICC_WRITE;
. _6 E: Z% O7 K- C' G0 y - ucComMF522Buf[1] = addr;2 f8 ]- W' V c, w; K
- CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
7 \& |7 y- }& L3 Y/ z a. e -
" U; k+ N+ @! }4 j. S% T - status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);, L, I3 |# M+ t; `" w* C
3 Z9 P( ]; W. C+ u% S& U, v: a4 j- if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))) I4 {6 g2 Q% q2 R } [
- { status = MI_ERR; }1 u( w, A9 V2 ?8 K8 h4 c
-
. C. q; k4 s9 S6 ^5 N% V - if (status == MI_OK)
* m+ Y8 n- F2 W5 l' J: D" b - {
+ F ]5 b! i. C$ s- F5 z& s. ` - //memcpy(ucComMF522Buf, p , 16);0 b7 Z2 y) l4 E$ o, l
- for (i=0; i<16; i++)* a: s2 F5 Y( {7 j, F
- {
, s6 X/ R/ d3 |# g9 d ]( a - ucComMF522Buf[i] = *(p +i); 7 F0 ^5 t; g; D# p1 ^- O6 l
- }
& x5 d2 d: j0 W! c - CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);& Z* ^( l; U# l
- & x7 B) b( b V, G5 ]: x
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);& z. ~+ A* B# `3 f1 v
- if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
6 ?) d6 J# o% I% q% {8 B - { status = MI_ERR; }3 l! ]- @/ P1 _1 T. g$ T
- }6 o* `1 t" C% l0 z. V* s, J
- ( X9 E) H/ ^6 P$ f5 T* T, s
- return status;9 x# s2 q2 \. ~- \+ o3 \$ X1 T5 Q+ j
- }
5 x' A+ j0 V- F& ]+ w" r0 c
E- W6 q, K( o; j3 N2 m k8 ~- /////////////////////////////////////////////////////////////////////; A# [7 d) ]9 R! l" ?
- //功 能:命令卡片进入休眠状态) S! p2 w& W: m A
- //返 回: 成功返回MI_OK4 W1 S+ V" C. V3 b5 F |" } T
- /////////////////////////////////////////////////////////////////////
, B! C' _6 E$ u+ D% d& P& } - char PcdHalt(void)
0 t$ K, D% x& s% S% f - {* S( c; r4 r" b" f# n
- uint8_t status;
" }. o) a# A( H, G" B7 e+ C - uint8_t unLen;
5 R" b' Q7 i% k6 J* V( _0 I. e - uint8_t ucComMF522Buf[MAXRLEN]; 1 a. |, }4 _3 v( p4 J
1 J3 A& ~" x, `- ucComMF522Buf[0] = PICC_HALT;
% s0 r. x) @7 O! }/ v* k1 { - ucComMF522Buf[1] = 0;+ D v( Z* I8 A; ?# B
- CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
9 p u+ P* @5 e: y r -
. u- Q9 R3 o2 b p8 d# G5 p - status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);& Z" V) _ R1 D# I
6 N/ V u* C* W2 y- return status;8 M! ^* h* L; A* O q# |
- }
% Q1 E2 l0 d5 k - / |$ {* W9 b4 H
- /////////////////////////////////////////////////////////////////////; L+ t* r& i* |/ S
- //用MF522计算CRC16函数( j& D6 H& V2 X
- /////////////////////////////////////////////////////////////////////9 w! x4 C& V1 L# f& H1 A9 U: T5 c
- void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut )* ~. _% w2 O) ~4 u0 E, b0 l
- {
( Z. q' i4 v6 G3 j - u8 i,n;
6 n' b; ` J+ K; \ - ClearBitMask(DivIrqReg,0x04);
) G& [5 k4 p, t! g - WriteRawRC(CommandReg,PCD_IDLE);1 ~5 D9 H) p7 N0 I
- SetBitMask(FIFOLevelReg,0x80);5 q3 A& ?0 ^+ W
- for (i=0; i<len; i++)0 G C4 f2 k3 e8 r, d9 l m
- { WriteRawRC(FIFODataReg, *(pIn +i)); }
: s% B1 C1 I6 _1 e5 d3 t( E8 A; x - WriteRawRC(CommandReg, PCD_CALCCRC);# m7 Y$ x& `# ? k
- i = 0xFF;
' I) V1 U4 V. m - do ' Y2 A0 y( K5 ?. p" Y
- {
0 A* A( `9 y# \! T7 c - n = ReadRawRC(DivIrqReg);9 I5 X, h' Z- z/ j% Y: \0 Y6 S
- i--;
( c2 \: }& r' E7 K - }/ ^& a- r1 R: B0 Q9 n' v2 i+ i8 H
- while ((i!=0) && !(n&0x04));5 |; L" z5 P' f
- pOut [0] = ReadRawRC(CRCResultRegL);8 V) {# w% G4 _, Q8 {7 ?3 ~
- pOut [1] = ReadRawRC(CRCResultRegM);
, r( I1 l5 [- ? - }2 M: X+ X9 `6 w
! `$ f/ U# e9 ?: h0 Q- /////////////////////////////////////////////////////////////////////
n4 I+ s! z& I7 O' n - //功 能:复位RC5223 M9 B/ \7 s g# j7 r0 ^" X
- //返 回: 成功返回MI_OK
' U* d9 N! N: l7 W$ V - /////////////////////////////////////////////////////////////////////* T2 V+ j1 o9 [# G
- char PcdReset(void)
( i$ K2 L1 {: I; b$ _' y - {
: @" K5 ~8 i- Y& V -
2 l1 c0 s3 W' w% P% m! Z, L: C - RC522_RST=1;9 ~/ e) ?$ g r, i$ {" M; X
- delay_ns(1000);
. _7 C6 Q6 H. b' C3 t - RC522_RST=0;4 f4 f& x6 Q3 [7 W, Q2 D+ M& t
- delay_ns(1000);
9 U) j. S( z: O% u - RC522_RST=1;
0 c3 G8 \0 T, W6 g7 x8 u - delay_ns(1000);% }+ q' C4 L5 x: Z
- WriteRawRC(CommandReg,PCD_RESETPHASE);2 {) Q& s3 Z- w' ?# R3 W$ G: ~
- delay_ns(1000);3 `- \# z3 b% g# W7 U) v
-
7 M: k) j; j; }- W; `/ n0 O# k - WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363
. |6 d! I# U) v - WriteRawRC(TReloadRegL,30);
+ `' u( M5 [& Z" W - WriteRawRC(TReloadRegH,0);3 P3 B3 P1 K0 W" l" g" M4 M/ ]
- WriteRawRC(TModeReg,0x8D);, B6 L$ p6 m3 i& V f# m: J6 \
- WriteRawRC(TPrescalerReg,0x3E);4 ?! M, V5 a) h2 I* u
-
* S* C, K" j7 p+ r: U - WriteRawRC(TxAutoReg,0x40); //2 k9 K# E" b5 K( S3 b* J
- //WriteRawRC(ComIEnReg,0x20); 9 Z- j* }0 V$ |& I, n
- //WriteRawRC(DivlEnReg,0x90);
4 W9 X3 G5 E' N( d6 h( m - I9 I4 W. U" ?) l+ o
- return MI_OK;
9 Q8 J6 Q( x* n7 d" |: K0 P - }
) _2 o" h- B) i# J0 ?0 j ~ - //////////////////////////////////////////////////////////////////////
6 M5 u! |6 ~. D M- o( x- p2 L - //设置RC632的工作方式 & t1 c: z% O) v* ^% u
- //////////////////////////////////////////////////////////////////////
: e: ], b: l- l; l0 Q9 s2 G - char M500PcdConfigISOType(u8 type)
8 V0 M/ v. J( Z - {
: v* O; e+ O$ D: O; [ - if (type == 'A') //ISO14443_A1 k$ f( \3 m) l( ~4 v* i4 @
- {
V* L# e- G& s* A) { T3 M9 S L- R - ClearBitMask(Status2Reg,0x08);
# J0 J' M$ |7 t - WriteRawRC(ModeReg,0x3D);//3F
+ v5 _( [" D( I! Y - WriteRawRC(RxSelReg,0x86);//84
4 }3 t1 s& }$ u1 p1 N - WriteRawRC(RFCfgReg,0x7F); //4F
3 V( \6 L5 A; { - WriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec) . A# ?1 x( m! f2 j7 C
- WriteRawRC(TReloadRegH,0);( G* ?6 [ f( R: i4 Y/ k/ t
- WriteRawRC(TModeReg,0x8D);
2 K* h& l- @) G4 m( x - WriteRawRC(TPrescalerReg,0x3E);- ^0 a9 K4 Q$ Y" k9 f
- delay_ns(1000);: q1 G* ?% o, B* w% i$ e: Q8 Q
- PcdAntennaOn();
$ e7 Y+ z* ?. W, [2 z - }: F: k5 ?9 v3 B' A2 e
- else{ return 1; }8 c- K/ A. F7 S/ V( A! H4 D
- $ @4 B& m7 {8 ]# t
- return MI_OK;
3 t1 h) W: T0 e4 k! D- q$ Q- d - }+ Y: t* N: {) a* Y# F9 L# Z
- /////////////////////////////////////////////////////////////////////& h3 C- }2 B8 ]8 y" C
- //功 能:读RC632寄存器. Y& h+ F% f- Z
- //参数说明:Address[IN]:寄存器地址1 R5 f4 Q/ p( g# G6 z6 K
- //返 回:读出的值" G/ }* m0 J. D3 S
- /////////////////////////////////////////////////////////////////////
/ x* u7 x+ `3 k+ `& d - u8 ReadRawRC(u8 Address)
5 t# F) M& w8 X& O4 E X - {& g# b3 b' S# m Q& U
- u8 ucAddr;" M0 o _6 W( ^% S& Q1 y0 ^
- u8 ucResult=0;( Q: O$ o: A0 W6 j/ l
- RC522_CS=0;- ]- |9 V8 Y& V' f3 X# m/ b
- ucAddr = ((Address<<1)&0x7E)|0x80;) ?- Q8 T H0 d6 I9 q; v0 M7 U
-
. e* o3 }% n3 h - SPIWriteByte(ucAddr);* z9 m5 O' v$ m8 F: ^1 W# R
- ucResult=SPIReadByte();
" S- d' Q w3 [5 ] - RC522_CS=1;
) p$ J2 o. M6 w$ g4 m! { - return ucResult; B3 A% B0 [7 F6 J8 g
- } z, S1 P( P- x6 v) P. A7 u- T
1 g( i3 ?% G& z" b& I2 v1 `. E- /////////////////////////////////////////////////////////////////////# x4 k/ k) q; v' h$ t
- //功 能:写RC632寄存器- {9 _8 a( j: Z- B" D5 ~
- //参数说明:Address[IN]:寄存器地址
8 @( R( W5 V) U4 {7 o - // value[IN]:写入的值
7 | f% G) G2 h+ P2 y% F: I - /////////////////////////////////////////////////////////////////////
0 I, g: R2 J$ u8 @5 q9 u% M - void WriteRawRC(u8 Address, u8 value)& I N$ t6 G, i7 c
- { " _, ]9 [9 z8 w; x
- u8 ucAddr;
# {1 E% u7 i/ R$ P6 I$ \
8 k; D. ?% M# }8 X1 F. ~2 R- RC522_CS=0;! v4 u1 l. A! R3 Z7 M* I% o" y
- ucAddr = ((Address<<1)&0x7E);
' o3 q0 w) m: A; \* w8 L
& V$ S: n) v3 U- SPIWriteByte(ucAddr);8 w# Y; Y+ ~4 V' f" g% m, L
- SPIWriteByte(value);1 |, o" K( L* o. [
- RC522_CS=1;0 \8 t7 e+ O0 Y( f( R
- }6 K3 ^& T0 {1 t, _$ }& a$ W
- /////////////////////////////////////////////////////////////////////
$ ~6 U5 \, i, Y! i7 ~4 T8 ` - //功 能:置RC522寄存器位
- E0 h$ e' L$ C$ a - //参数说明:reg[IN]:寄存器地址 R" L- ^; ?# ?
- // mask[IN]:置位值
. `8 w, Q) e% q+ ]$ { - /////////////////////////////////////////////////////////////////////
: N2 G" {6 _* Q' s7 |. |5 B1 H - void SetBitMask(u8 reg,u8 mask) 1 F$ B! B* P$ O. @
- {2 f# H5 r. G4 _7 ]' X) t
- char tmp = 0x0;
' L |0 g+ \3 }5 R - tmp = ReadRawRC(reg);' ^' T7 p3 X- h- r4 Z- J! {) [& \
- WriteRawRC(reg,tmp | mask); // set bit mask' v/ w; n* Y( v8 n2 |3 U
- }: E6 m2 {/ b/ t2 ^5 s
- * s) a: _. v f8 Z: f4 Q# _/ ?. _$ e; J l
- /////////////////////////////////////////////////////////////////////# y0 D! w1 s3 J
- //功 能:清RC522寄存器位2 w! y! E# M# p! d% ^5 g/ e+ j
- //参数说明:reg[IN]:寄存器地址. |& j& }4 \/ u( }
- // mask[IN]:清位值
7 P" T# a0 Z* g7 z' \( b$ q( Y - /////////////////////////////////////////////////////////////////////. O; S2 ?8 ^5 N
- void ClearBitMask(u8 reg,u8 mask) 9 _" g6 S% S Y; i
- {
- A+ W3 b! L, C: ^2 f. h( | - char tmp = 0x0;
" l' b' Z. ^- K/ |2 ?5 K# d3 O - tmp = ReadRawRC(reg);
& J+ }- Y9 \4 v! R( L8 I9 A, E- D" b - WriteRawRC(reg, tmp & ~mask); // clear bit mask
& V) U/ i( T( J" T; p8 z - } 1 ]# Q1 Z% M7 N9 N+ Y
- 2 L0 S. F9 \/ R- ]# Q
- ////////////////////////////////////////////////////////////////////// b% o D/ V+ |- T8 S% r
- //功 能:通过RC522和ISO14443卡通讯
. {$ d- T8 ?" l. f* [" v* l - //参数说明:Command[IN]:RC522命令字
" K0 G( p. e1 \4 r4 Z - // pIn [IN]:通过RC522发送到卡片的数据6 f) ?* I, _, ^* ^* H7 G+ S v
- // InLenByte[IN]:发送数据的字节长度
& C. E3 W- Q7 { a3 O+ x' U - // pOut [OUT]:接收到的卡片返回数据
$ `( P7 p) S+ F. T6 h1 s2 G. o - // *pOutLenBit[OUT]:返回数据的位长度, ]2 ?& I3 v& v4 a% |! ?. ` B
- /////////////////////////////////////////////////////////////////////4 W$ I0 G b% F) D5 o& o' @" u
- char PcdComMF522(u8 Command,
1 h' Q: V1 z; ?& x - u8 *pIn , 6 \+ j7 `+ _6 f0 {, E
- u8 InLenByte,
# x# A: c9 }3 Z9 Y* J: r4 F - u8 *pOut , $ x- A2 D' H) S% y/ S0 b }$ F
- u8 *pOutLenBit)4 g; q1 I$ k8 s7 s6 E7 q" {$ A# w( s
- {/ s! I B2 j! k6 c3 w- T; o. K
- char status = MI_ERR;
5 D. n% k+ [! E, S# u - u8 irqEn = 0x00;2 x9 p# r; k& g, R% T6 @7 c( K1 f
- u8 waitFor = 0x00;
. o) P' m* ]" h* _9 H - u8 lastBits;2 M3 v& d4 b3 ^ [4 d, A; i
- u8 n;
' s# F3 H. ?. ? H/ { - long i;0 ?- D/ i4 p# v0 Z
- switch (Command){
- m8 I r: w4 h! `% S; ~. \ - case PCD_AUTHENT:* A1 H0 E3 [6 u; e
- irqEn = 0x12;# @1 V( q/ V0 ~8 j, j) F; v$ A
- waitFor = 0x10;+ t# R/ |, [3 }. \" d' {
- break;
/ |1 r" [4 s, I+ P r: } - case PCD_TRANSCEIVE:
% w; W- w7 n Z1 R! _. q4 V - irqEn = 0x77;
2 S# ~" ^7 Q& y5 w- H0 G - waitFor = 0x30;. J K$ x9 y: H
- break;9 x- W% M' M9 I. M
- default:: Y$ k2 @# p& Q* U0 l% d
- break;( Y2 g8 M1 S, K0 S5 M6 p* s
- }
$ m" c8 r4 @$ E- p - : g7 k; ]- ~- o
- WriteRawRC(ComIEnReg,irqEn|0x80);* F5 ?9 n- U( ^
- ClearBitMask(ComIrqReg,0x80); //清所有中断位# u& n: Q! C0 `: b! p! w0 o6 `6 E
- WriteRawRC(CommandReg,PCD_IDLE);/ u# X8 z& z4 H
- SetBitMask(FIFOLevelReg,0x80); //清FIFO缓存
' S- g' ]8 r( s1 G, j3 a - 5 y4 r- |4 V2 z w8 F
- for (i=0; i<InLenByte; i++){ " |( m8 f, e8 F
- WriteRawRC(FIFODataReg, pIn [i]); 0 j9 T& N3 x$ F9 ]3 A
- }$ u F; f# ]2 |. [0 i
- WriteRawRC(CommandReg, Command); & V* `! ^0 O* z" }) v$ t
- 9 _2 Y0 P# T5 U+ Z
- if (Command == PCD_TRANSCEIVE){
- {% h: o# m2 d4 b. O0 q/ V - SetBitMask(BitFramingReg,0x80);
0 E7 \4 O+ M7 r, d5 D4 W) K8 s - } //开始传送) J" A& B, B2 z* y* H4 D5 d2 [& `: F
- : h9 f+ Z/ Y6 `; ?* z) h) ]7 p& n" Z
- //i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms. G; C* f5 |' P( ?
- i = 100000;
. n$ ~( f; n) ?) m- T, U - do
9 p9 P5 O& F& E [$ h) S$ p* l2 N - {
- }- K' X) f& h& v - n = ReadRawRC(ComIrqReg);
# W3 ^: R2 Y- T3 x7 r E$ B - i--;
6 W5 T& T) a1 y - }while ((i!=0) && !(n&0x01) && !(n&waitFor));
/ I- S e5 ]8 H - ClearBitMask(BitFramingReg,0x80);
1 S; u. s- H) V- Y d
, [8 g% G! @; F* W2 y- z' I- if (i!=0){ ) Y/ Y; S: p2 _+ f' Y) w6 `
- if(!(ReadRawRC(ErrorReg)&0x1B)){+ b8 E0 ]: l% C
- status = MI_OK;
0 A" |: X$ R0 D( i& @ - if (n & irqEn & 0x01){ , H! ]2 ]6 @% W& W) k
- status = MI_NOTAGERR;" K) q7 `* b9 F5 H3 D$ ?* L0 W
- }
* M9 [$ k8 J, _+ A& A* r1 Q0 ?$ @ - if (Command == PCD_TRANSCEIVE){
% z4 E" d2 d! z - n = ReadRawRC(FIFOLevelReg);
3 \- O; m, F% P* R/ j - lastBits = ReadRawRC(ControlReg) & 0x07;. B/ X, s) @& c
- if (lastBits){
0 F: H$ h/ U7 h% f. f0 O. b - *pOutLenBit = (n-1)*8 + lastBits; , F5 |2 Q% }) f. o2 x
- }else{ ( |( k$ u' ~( Q( w) ]% @& o
- *pOutLenBit = n*8;
) }" _: t& P) B$ t# a/ g" K( Y - }
# A! ~* N1 l! E- {9 K) P - if (n == 0){
! V& y5 k! x/ X - n = 1;
7 K4 Q p3 E4 ` - }
( E1 e7 f& n, z! j5 k4 H7 T - if (n > MAXRLEN){ 3 Q' j" N3 e9 \- x7 b6 Z( a+ E
- n = MAXRLEN; N& l( v7 d- h: \' U$ ~1 g R
- }
& W0 M o7 `, x; Y2 ~ - for (i=0; i<n; i++){ + s; q7 u; d, Z7 o) O- I
- pOut [i] = ReadRawRC(FIFODataReg); ( {3 X2 Z R6 z1 X1 W' |- `- p
- }
% L" ~! l5 q4 `/ g4 ~# Z5 b - }: `% i, n$ E- E) U: Z+ r
- }else{ 9 F& ?7 D' ] c( r0 c$ C
- status = MI_ERR; 1 h N( x8 | X2 o/ v9 G
- }
* R5 w' j h6 u& ^ -
, Y% v9 [/ P; | - }
( H" m% d* Y3 B0 F! K# p - SetBitMask(ControlReg,0x80); // stop timer now' U+ C& J1 ^1 N/ Y/ B- E7 E2 U; k% L
- WriteRawRC(CommandReg,PCD_IDLE);
1 x, S+ y f: K* e* v+ }: N% H - return status;
2 |5 {( |! a1 f" d - }
% I5 g0 f! p% d. F. ~& J3 l; X, G
9 H( V0 j: Z! Z- T% k6 d! V; Z- /////////////////////////////////////////////////////////////////////
' K1 G0 k$ B) ~0 X/ G5 V - //开启天线 8 ^" R, t& O+ p( b: Y: Q
- //每次启动或关闭天险发射之间应至少有1ms的间隔
( @. y4 W4 e+ P' B3 U9 o - /////////////////////////////////////////////////////////////////////9 f' f, {& [5 F. P* ]- l" ~( I
- void PcdAntennaOn(void)
, e# V0 Z8 }1 F, p Z - {' g0 o* J+ p$ }
- u8 i;$ c8 ~$ {) W/ E' |- Q) j% J7 c
- i = ReadRawRC(TxControlReg);: v% G5 e) v6 f% G$ Z5 N
- if (!(i & 0x03)){
$ ]5 z9 J# @. g7 { A - SetBitMask(TxControlReg, 0x03); N, V) u A) s" M! }) N
- } l! u( |: ]1 _$ F* Z
- }
: U8 P& t7 c5 g! S' D0 t6 N - 1 T' F( R* h- h" t6 O" `- h
- . `# u- _. Z; F3 N& W# Q
- /////////////////////////////////////////////////////////////////////
; N3 H9 `$ u4 M" b( A - //关闭天线7 |3 x$ D. ]$ u0 b
- /////////////////////////////////////////////////////////////////////
# `% R5 a7 M* G% r1 d; q, W - void PcdAntennaOff(void). ~( d0 e4 {6 M* f2 q9 y
- {1 H: ~" Y& r1 x: n4 m
- ClearBitMask(TxControlReg, 0x03);
6 U7 \/ w7 W5 ~ Z9 G - }
1 b9 A6 z8 |9 j4 A - extern unsigned char CT[2];//卡类型/ r8 K. y$ c+ V8 t3 I g
- extern unsigned char SN[4]; //卡号& E- w. i6 I9 a9 V' C; ^' D6 x
- extern unsigned char pptr[64];
3 r- f9 f+ L% s) h' o6 X! K8 ^ - extern unsigned char KEY[6];: O& j+ q2 ^; c9 j3 w) J
3 I7 U% k( f0 v \1 r/ P
! a. Q! K0 g2 [2 {7 N) v0 |% Q- u8 RfidTest(void)
6 |$ y: a6 ]! x( g - {2 s- N6 ^2 M5 S9 z
- static u8 oncnt;
5 q, F% u$ F) q7 m% T/ I; R* A - static u16 allcnt;% H2 u, t9 M2 f( K% }5 L
- static u8 res=1;) Q( ~* l# l9 a4 D
- u8 status;
) w2 ]' a0 @1 M! _. q) j' R - allcnt++; /*未明确什么含义 RF卡扫描次数?*/9 u- H: K! ?* r, q# }
- if(PcdRequest(PICC_REQALL,CT)==0) /*扫描卡*/9 C. T) g. m$ v" a5 z) I! N$ l
- {
" N7 v8 F1 l; x) W2 ] - status = PcdAnticoll(SN); /*防冲撞--获取卡号*/
7 e7 q1 Z$ Q2 A3 E& R% E" l) {: y - status = PcdSelect(SN); /*根据卡号选择卡*/2 c3 Q1 n. E+ k9 O
- //1个扇区4个块 每个块16个字节 密码长度6个字节
& z* B& g$ p2 \. O$ F5 v, J# } - //块地址=扇区编号×4+扇区内的块编号 17 代表4扇区 块1
; q# W9 N: ^& B$ ? - //将保存在块地址17内的6个字节的密码与秘钥B进行比较1 n! O6 r, m" t- D: B$ ~
- //调用该函数需要选择密码验证是KEYA还是KEYB,
. H9 b/ l: a: S- Y4 T - //然后输入你要操作的块地址(想要读写的)()0 U* j. E+ h7 Q, X( F' n' @
- //存放密码数组和存放卡片序列号的数组。(感觉仅用来计算扇区)
/ r, J$ V- ]' {) n' M/ H+ ^- y - //验证成功后就可以对该块所在的扇区内所有的块进行操作了
& I1 `) x9 W8 [- v3 A# u' N% i& g; }& F - //读、写、加值、减值、转移、恢复)
6 x, U1 [8 K! u3 p. }( `+ ~ - //KEYA KEYB 默认密码都是0XFF
! _8 i4 H+ a& h - status = PcdAuthState(PICC_AUTHENT1B,17,KEY,SN); /*解密:验证B密钥,密码所在地址 3-7-11-15-19*/' j0 I, {) ^0 L/ K) j' Q* E+ ?
- status = PcdRead(17,pptr); /*读4扇区01块数据 返回16个字节数据*// Y- v/ s' G9 i" m
- if(status == MI_OK) //5次以上成功# d3 U, {8 [4 u& Y1 i' t
- {
; Q5 H3 [" T$ f' _. I1 j/ j - oncnt++;8 l0 G9 @6 Y; |( }- u
- CupType = pptr[0];//茶杯类型在0位置) a4 }1 I3 C, f/ z" Z
- }$ Q. W6 x! F" A) C, u- A
- }: l9 g9 t4 H$ J W' v( @+ L
- if(allcnt>13)//检测13次( ^% ?1 j" G$ Q0 d
- {
- m' {0 C/ ^. f. ~" w' w% E. {$ w - if(oncnt>5)//5次以上成功- _! Z8 J( K1 Z# Z
- {8 l8 G' _4 ?0 @# q+ z1 k1 P) x
- res= 0;0 _# V1 w3 P6 V8 @: O2 m4 ~
- }6 ~, W) w+ n* h5 n& G
- else
+ Y/ i W; |: H4 \) H# l - {" M: M4 y1 Y7 V4 \
- res = 1;
5 q' i7 L" j. G" G4 b( M B k1 e - CupType=0xff;
" T; p/ p/ M0 S; i - }
" Y, m: e" z2 L - allcnt=0;oncnt=0;
& N& X' t+ W. L: [% F% [2 v - }
' k! x. }$ A& u! k" F0 N - return res;, n2 l) A; q' R s8 S! I
- }
/ l4 l1 u3 o% k. a/ Z5 I8 _8 R' A - /////////////////////////////////////////////////////////////////////* } k9 c: p$ s! b- `4 w- X
- //功 能:读取杯子类型
. R7 h( g/ H" r, J% n7 x - /// Q: R) P$ ~- k
- //返 回: 失败 返回0xff 型号一返回01 型号二返回02 空白卡返回00
& u7 _! N* e/ b# k& d& Y3 }( l - /////////////////////////////////////////////////////////////////////
; {3 G5 f2 N: m& Z# U4 B - 5 w- j2 Y7 n1 q9 u8 D1 H; k1 E
- extern u8 CheckRFTime;4 [8 f3 d0 ?3 \ {0 J% i. P% O/ d
- u8 AllCnt=0;
2 A8 L8 y! d+ r- c/ ]# S# J# g - 7 F/ {2 t3 v8 @$ ^% O9 w
- u8 ReadCupType(void)
r/ |5 z I& o/ E# s; d8 c - {0 o% j# z5 Z7 k+ g a
- u8 status; & J. l0 i I9 j' Y
& p' Z3 d) @( M- AllCnt++;
# o: D* W( e" q: P4 f - /*无卡次数,也就是非MI_OK的次数*/# a* ?' u) `1 N, ^- k. ^
- status = PcdRequest(PICC_REQALL,CT); /*扫描卡 0 OK 2失败*/. l; E0 p+ G2 |: p% R
- if(status==MI_OK)
4 s3 q2 C5 X! m& m - printf("寻卡状态:成功\r\n");
, n9 j: m+ H s' G l9 ? w - else \- u0 o* }4 U$ Z& f
- {
1 |) q* ]% P4 p+ {# R- \# X1 l2 }4 { - printf("寻卡状态:失败\r\n");
; D/ e# K6 H0 A4 H( u& b x u - return 0XDF;
/ u: E" x/ N& ]! s h - }
/ o4 c/ c- g' x6 a1 i1 i- G - ! C( Z/ C' ^2 I1 L, Q6 Y. C+ \: V
- status = PcdAnticoll(SN); /*防冲撞*/1 J5 j# v- V1 n/ h& S& e) c8 I
- if(status==MI_OK)& j+ n G: x. ?2 q+ N* ?
- printf("防冲撞:成功\r\n");
/ G% s5 V% q9 P" W2 K' c# I - else: ~$ {0 K$ C9 f9 m: {8 p c
- {
5 e; g y7 o: H3 p" z3 k5 X - printf("防冲撞:失败\r\n");
2 U6 E, x' ?: J - return 0XDF;& r( d) _3 y% v, r4 B# [: _
- }
; o4 O0 V& `: M! a0 {8 g+ [ -
, b! C! M) G5 U Q; V/ L# K1 d - status = PcdSelect(SN); /*选卡*/( t, D. @$ j; z/ |* O9 \
- if(status==MI_OK)
/ }2 Y3 s' ^; y' z9 [8 p( { - printf("选卡:成功\r\n");9 I1 }8 f$ r8 A: R
- else2 h$ W. Z/ k4 ~2 O2 T
- {; J) J0 O0 H* J5 r+ S
- printf("选卡:失败\r\n");
9 w* H5 i! Y3 s; b( l - return 0XDF;0 Z, E/ y! ]! I% y
- }
/ n. z0 b$ W+ g% I$ Z, W - / x3 t, Y- i3 h6 {( u
- //PS:块地址17之前被强制性写入了杯子的型号(用另一个程序)1 T1 z9 G' Y$ k
- status = PcdAuthState(PICC_AUTHENT1A,17,KEY,SN); ; }- `( A1 H3 R
- if(status==MI_OK)) e5 W) @6 _+ L- ~6 q9 v: E
- printf("密码校验:成功\r\n");
$ I6 |; P7 G) u* B - else5 v3 J2 q+ X# I6 l: K$ a) |
- {
/ W1 T* u$ p5 x/ ]5 x- A8 `* N! `6 [4 l - printf("密码校验:失败\r\n");% f& V" B/ {) p! T! m9 \3 l( T
- return 0XDF; 6 ^1 A$ y( F5 Q* S/ J% G0 l
-
( M, n, l6 ]% T5 t% i* } - }
: @- |+ Q4 F+ A& M9 n -
2 f* ? h/ r3 z d5 Y - status = PcdRead(17,pptr);
+ D, ] O% k( C6 G# c -
) k" |# a2 {+ m7 v - if(status == MI_OK)# i2 B; h& [4 ~/ P0 u7 Y6 D
- {
% t& t2 S+ h; j) H8 V - return pptr[0];+ G8 k- I X5 H8 p: @. o! h7 `
- ( w: `8 P% a* d9 g1 _* o3 h! D
- }3 \: y2 r7 G+ E5 a# L {2 } ~& Z
- else2 A, A4 r' B2 {
- {
: G0 m# ^! `9 S& {8 p& \6 z5 b, a# [9 H - return 0XEF;6 o. s3 W9 s. h) P9 h6 K# ^
- }4 o% R1 B+ O# i
- 2 ^8 k0 Q9 _$ u4 B! _/ N, G a
- ! r5 o# V" c+ x$ \ J# w, Z6 |# A+ z
- }9 c2 z0 z* |) Q0 L0 t' b# Z- j
$ y. ?: U$ s. H2 f, o3 Q- /*写杯子类型1*/
$ v4 \' | D6 S) M; g% q - u8 WriteCupType1(void)
. Y' I3 ?+ j3 N - {
5 I/ Q5 L' @9 ?- W( c9 V' B - ' T7 K0 u% N$ m/ k
- u8 status;
* |/ R5 j g i8 @# ^8 w - u8 CUP1KEY[16]={0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF};& C m) E3 n [! J* G# {9 c
2 W' W2 I2 A5 M& V- AllCnt++;* P% A6 A5 N' S, c ]
- /*无卡次数,也就是非MI_OK的次数*/
( n% p g+ S- x" r - status = PcdRequest(PICC_REQALL,CT); /*扫描卡 0 OK 2失败*/
' I5 t' @7 X w+ a! Z. i' c - printf("%d%s",PICC_REQALL,CT);
: c( |6 j4 }2 E' u. b1 k0 s - if(status==MI_OK)3 F/ L8 N8 S- d, l! @
- printf("寻卡状态:成功\r\n");
2 Q# S7 i+ c; O% C9 ^- x - else6 v) j+ N! q* u7 \' W+ d' p U; V5 |
- {" Z+ U0 V6 i+ ?8 d! p4 F* e, E
- printf("寻卡状态:失败\r\n");
8 f: K( i4 b+ \ I1 ?2 x/ r - return 0XDF;
* r7 W, n) U/ _* t - }
& F' n P8 |1 r0 T4 ^' c -
/ b, W0 H! P' i' J0 p$ `$ ` - status = PcdAnticoll(SN); /*防冲撞*/% C" q" S) c* m; u/ s: C7 w
- if(status==MI_OK)
" Z) K( i) V* K5 F% @9 O - printf("防冲撞:成功\r\n");5 `% t+ N% c7 m
- else7 H6 v5 B/ k, _$ i7 z
- {3 ~1 } m- m( Y7 T: L& P Y4 P
- printf("防冲撞:失败\r\n");
$ }1 t( X4 S9 p - return 0XDF;
- t1 H; E$ L# d - }
! u4 f8 a' |8 ]3 ^4 [& ]. a/ z - / `- \1 o" y, Y4 U" I/ A' a* z
- status = PcdSelect(SN); /*选卡*/6 t! C* X$ d$ W9 {
- if(status==MI_OK)
5 c' q9 m2 i) ~2 d- i$ B) Q - printf("选卡:成功\r\n");& O7 k. K- h3 j* f$ [9 I* n
- else
+ ~: L3 E' k( v - {
2 s0 i( x4 _; D - printf("选卡:失败\r\n");: j9 S1 W* b! t( p7 \4 A+ h$ k
- return 0XDF;0 t. F; Z" E7 I$ C! L' n' A: f
- }# C4 g C H: R
- + P0 j6 E" E2 A. w; S, A' E
- //PS:块地址17之前被强制性写入了杯子的型号(用另一个程序)# ]' M" c1 a l2 ?
- status = PcdAuthState(PICC_AUTHENT1A,17,KEY,SN); 3 U8 `' t# v+ a6 y6 ^) s' k* D
- if(status==MI_OK)' ~% h( Z( [, ^) B
- printf("密码校验:成功\r\n");
/ G' X ?7 m; L7 N. ~% {1 c - else
k* ~ t8 B' h1 Y1 ^, c# q3 S9 B - {+ t9 Z# r, g9 U2 J3 V
- printf("密码校验:失败\r\n");
8 ?8 y1 Q8 K6 [: W& E8 S2 Z - return 0XDF; $ i4 A. S! O/ |" I
-
* Y0 z: B3 y9 H( | i0 h5 ? - }
; g( }, v% t, ` -
+ d* i9 v, N) ]% ^4 x - status = PcdWrite(17,CUP1KEY);
0 z, t/ |$ G; |3 \ v - printf("%S",CUP1KEY);
/ i" S# c* N9 I' [) I - if(status == MI_OK)
, s2 Q e" R6 m8 S5 W: P) B! ]/ X - {9 X7 l3 ~! B7 E
- return MI_OK;+ k. P( e, k- n- ?' [# Y" z' O0 w
- 3 o9 }' y+ G& z9 Y9 E! M; [
- }0 z. d* H+ R- [3 G+ ]+ ]
- else
" ^& ~& R9 t. S; _& q0 _; B! \ - {
' ?5 w3 W v; F. z - return 0XEF;1 B t* s( @( Z/ l7 ?* R V
- }: U* ]& A$ Z3 J+ \7 ?) j
- }+ x. m0 t8 c4 w8 d/ c
- /*写杯子类型2*/
- H: U- O) B& }2 \7 l' [$ J - u8 WriteCupType2(void) t4 Y8 N, d1 l8 Q$ \1 h
- {: a5 [/ I! b) t2 P* `' t, Y
1 |8 X; @3 |( `( r2 [, x: ]/ P- u8 status;
/ i" |0 ~2 O& H/ D; P8 v- e) q - u8 CUP2KEY[16]={0X02,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF};
& ]2 y3 C7 |# w9 I% S- y; f - ( |- U k& z0 P/ g
- AllCnt++;
" V! M+ a- H$ _" R4 U% p# E - /*无卡次数,也就是非MI_OK的次数*/
* u6 k( I. |! d- @( K6 A - status = PcdRequest(PICC_REQALL,CT); /*扫描卡 0 OK 2失败*/0 K( W5 W9 J$ p+ P' Z M
- if(status==MI_OK), C/ k" R4 x) c, Q r
- printf("寻卡状态:成功\r\n");
% H; l$ A& H+ A9 C - else
1 O2 _4 m% x. y* O' Q - {
( e" Y& S! \3 K5 i. z, @ - printf("寻卡状态:失败\r\n");- c7 }+ Z& T/ N; t
- return 0XDF;( ]+ R: q/ k; L2 u
- }
5 B! b( D( Z; q( T -
2 w5 y* Q/ }4 }3 V2 U( B - status = PcdAnticoll(SN); /*防冲撞*/
! P. s: C9 h7 V- @& K, o5 S - if(status==MI_OK)
0 P" j+ C' N1 S: T# H, P/ s0 N8 D - printf("防冲撞:成功\r\n");3 M3 A4 M' \& y2 K- [
- else, Y( D) j& y5 Q
- {; Y, s$ o# E" v0 f! X7 G
- printf("防冲撞:失败\r\n");4 F+ J, E* m, d; J# ]* ^2 U& n
- return 0XDF;
* t% q( ^$ J6 G8 e7 ]% @4 m - }
! ^; W9 D% \% l+ |4 D - 5 h5 q1 p0 P* }4 H; O( x2 f( X
- status = PcdSelect(SN); /*选卡*/: u- ?) o* N; y* c" K0 j3 X
- if(status==MI_OK)
$ u- X3 ^7 ~! \ - printf("选卡:成功\r\n");
: B1 g t- p% P - else
. |" Z7 ]: R8 T; T) [ - {
0 @1 x/ y- Q. J' d5 F# V* K+ P - printf("选卡:失败\r\n");
+ ^) q5 _, @/ W& V2 \8 l - return 0XDF;
- \5 Q6 ~, f% f& Y' {, A4 a/ m* V; { - }3 Q o' |' ?" h+ M4 C: n
- * E2 f# m; e# v; K" l* m1 o
- //PS:块地址17之前被强制性写入了杯子的型号(用另一个程序)
}6 o* J, J3 ~- a5 x) s& ~ - status = PcdAuthState(PICC_AUTHENT1A,17,KEY,SN); . G: e$ z) R& b& @# g p
- if(status==MI_OK)8 b& y/ c: c8 u: }( {
- printf("密码校验:成功\r\n");
0 ~8 o0 K, J. Q9 W# ~ - else. O K/ u- k* G7 N. U% f; }9 S, D
- {
: l5 p' z/ Q2 g( x6 j7 K( U - printf("密码校验:失败\r\n");
' u7 B9 L6 F b+ T% T3 j0 u6 R - return 0XDF;
: @( H: l( e% s0 y; j, x7 Z( ~ -
$ h$ f) Q1 H" p* Q* y3 e - }
# \2 w% e, e' F" O: R1 ? S2 h0 z- ? -
/ T' Q0 g8 E# J5 }+ P. G - status = PcdWrite(17,CUP2KEY);3 L3 A! t# z, e& j) X
- 6 {; v7 t, T! F6 H
- if(status == MI_OK)' m! V, R) m* r2 X+ e* D
- {
& o( M, M# a6 p( A2 t( d - return MI_OK;
2 s7 |7 C- B8 [ v n - ; x& H5 i9 \' g
- }8 |' s) J2 x" Q5 R! L9 e. U) }
- else! j( w, h( m# w
- {- `" |, m& m: z p: V
- return 0XEF;
: X9 j; K2 F$ K) U( m - }
. a% g% c8 k$ q - }, D3 T. y. |$ g" X
; o% k+ P, u7 T d8 x0 l* O- /////////////////////////////////////////////////////////////////////& z. J. e* W8 d j* E# B% v
- //功 能:扣款和充值8 U( A; N8 T. f b2 @$ ^( t N/ f7 c
- //参数说明: dd_mode[IN]:命令字( T( m" W# @' ~* ^4 {% ^
- // 0xC0 = 扣款, G! Q# ~( s% ^* t2 A% U
- // 0xC1 = 充值. h7 j) i# C- b3 E2 T# I
- // addr[IN]:钱包地址
3 ]& x1 p+ i7 g* C - // pValue[IN]:4字节增(减)值,低位在前
1 e' F Z, F8 t% P) o5 P! k; G - //返 回: 成功返回MI_OK. ], D3 ^2 Y- j; W9 D k* y/ ^
- /////////////////////////////////////////////////////////////////////
]( I1 p0 t1 Q7 D - /*char PcdValue(u8 dd_mode,u8 addr,u8 *pValue)" w8 w7 X t( _/ K! T
- {
* D7 z9 r5 h5 j4 y - char status;
" D& ], Y+ w9 s7 E0 Y0 Y( s - u8 unLen;
) F' V) E4 f9 @ U! J - u8 ucComMF522Buf[MAXRLEN]; # {% j9 Y6 i- @ O9 r5 B F2 |; I
- //u8 i;' r1 F1 z5 k( I+ e
- + t8 l, F1 l% J' @( c, m
- ucComMF522Buf[0] = dd_mode;! W8 f: n7 E2 s+ G2 l# J
- ucComMF522Buf[1] = addr;6 l6 @) ~2 T' c7 x2 q7 M
- CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
( [7 I# P% ?/ j2 c7 V. ?4 o - ! }& K D* }- o6 i1 y: c+ C) Z: e) h
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
7 a6 U! f2 D0 C
/ R. ]& l7 G- I* e( ?& H8 ^- if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))/ T$ H9 }/ G$ F
- { status = MI_ERR; }
* h7 w6 P. x1 h g: Y7 X$ d -
1 t; n+ G, z, N | - if (status == MI_OK)
0 [: v3 L' Q y, S - {
( y! I# |7 }1 s; x - memcpy(ucComMF522Buf, pValue, 4);, E3 @; f# p, K1 C9 R
- //for (i=0; i<16; i++)
$ f: p; e! C+ s' g# |! i* h - //{ ucComMF522Buf[i] = *(pValue+i); }2 {" o) ~# l1 q' b
- CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
( n& {3 v G5 N1 {' P - unLen = 0;1 l5 ^( }, g6 T* m5 R
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);5 p4 X% p; y4 I# v2 A m3 Q
- if (status != MI_ERR)* ^; j( a7 f; M; o+ k
- { status = MI_OK; }8 x! Y9 T! g& |" h2 A, ~' ^
- }
0 U5 t5 T6 E. ^7 z# \ - % f- Q# ~% i2 H K7 j
- if (status == MI_OK)
, v4 [% v* ]; M - {% t n/ C* H. E( L
- ucComMF522Buf[0] = PICC_TRANSFER;; Y" {. j+ B j: l9 t
- ucComMF522Buf[1] = addr;* R5 _4 ~1 d* G/ A: I
- CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 0 r- Y; ^1 Y, | S
-
( w9 j; J3 ?4 ~ G - status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);% `* w1 p, ]. w6 G& y$ x6 z: ~5 \, n
- Z+ a( b" ?1 \5 M& w' a- if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
$ b+ o: v8 j) |9 Z5 ~- K5 f - { status = MI_ERR; }" \: b! ]( D( f: w3 K
- }5 e: Q, v+ s: k# \/ m
- return status;
$ T: W5 p( d. g; J& X& b9 Y# i p - }*/0 n5 [5 s& }/ T' }9 F$ w
- 5 V. W* C1 ?: g% z, p
- /////////////////////////////////////////////////////////////////////& G& }/ Z0 `( l* x6 J& H
- //功 能:备份钱包
1 l7 Q* }( y2 k9 `* e - //参数说明: sourceaddr[IN]:源地址+ B; K$ a8 t2 P9 e
- // goaladdr[IN]:目标地址; o/ p: y6 N- D4 f. @( f8 Y
- //返 回: 成功返回MI_OK" W, o6 \7 H O% d
- /////////////////////////////////////////////////////////////////////2 v8 L9 g8 `8 N' k
- /*char PcdBakValue(u8 sourceaddr, u8 goaladdr)' _4 I3 A, R( n3 J/ T
- {% }9 F5 X5 ~0 F# y- L
- char status;
' \9 `: y; K) W$ ?, i" [- _( u1 m - u8 unLen;5 G/ X! a- U' N t% K
- u8 ucComMF522Buf[MAXRLEN]; 9 X6 |2 c! H7 h( s( B
' q0 N/ y- J* Q! g+ _0 L% R- ucComMF522Buf[0] = PICC_RESTORE;# G9 Y( X! d* g2 {* E
- ucComMF522Buf[1] = sourceaddr;% l. G( _" C' t3 g8 H% t8 t% y
- CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);! p5 M. K/ e9 c9 A, P J, D+ i; K8 H
- 7 a6 L1 Q, l) z; |2 k' F) J4 m
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);: \( T4 F% O0 F% V0 ]5 j$ |
- h: b" ]: Q7 M" i4 h% T z/ {- if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))4 N4 {( e; _1 A
- { status = MI_ERR; }
, r% I. K: q; K% t" S \ - 3 g! W+ ^, f& C6 A0 K4 Y
- if (status == MI_OK) Q* R- L% G4 ]" [! |
- {7 g* w, l+ K/ E9 q$ t1 E) N
- ucComMF522Buf[0] = 0;
( B& ^3 I: l; S C, h" } a - ucComMF522Buf[1] = 0;# B+ Z, `8 m7 j+ N" G
- ucComMF522Buf[2] = 0;
, @- B, F9 {) |! r - ucComMF522Buf[3] = 0;
: }% ]1 B/ C3 \7 Y - CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
( Z. H3 l+ S2 \& S. ]- t - 1 `* m4 W4 q( ]% I+ B6 M
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
* P6 E8 T- y* ^0 S: D* \8 s! Q - if (status != MI_ERR)* X6 M& {2 K9 O
- { status = MI_OK; }
/ v* x1 @5 W- s7 T- }( W - }) S: q! T( ^9 W
- ' X+ @8 R" `& ^/ O0 g
- if (status != MI_OK)6 d' v) B+ m# [
- { return MI_ERR; }) J- b* n/ C# y# s, h( K# z
-
) S! b1 W# G4 A2 }# u4 l0 j - ucComMF522Buf[0] = PICC_TRANSFER;
# G: ^) Q4 n J t0 K$ S5 S" y - ucComMF522Buf[1] = goaladdr;' d* v$ D2 K% l8 `
- 5 y! Y5 D0 c8 A; S1 S- |9 {. ^
- CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
" G4 `& |8 X' r! c" L; Z" e -
4 O/ m* b" {. o - status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);) i6 ?2 v$ a: t. r
- 8 n2 F2 e. i. C* W: R0 ]
- if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))7 L$ w. E& V( ^: O
- { status = MI_ERR; }& y/ F% B# Z- d0 h- x% y' |7 u. D
9 R( u9 \4 Y) W- return status;/ M1 G, E F; O {4 I7 W1 ~: ^
- }*/4 F: T$ w r4 V6 u% r( ?6 S
复制代码 通过串口来读写RF卡(仅块地址17):% n2 |) L" y. i" e
指令:SS11PP //查询杯子RFID型号
: o2 G& D! b' C' }8 b1 U指令:SS22PP //强制写杯子RFID卡为型号1
% R0 p; w' n; L指令:SS22PP //强制写杯子RFID卡为型号2( x1 H" k Q5 [: J
3 G& B" }* X! \# |; \+ x8 H$ m
编译下载,通过串口操作(S50卡放读写模块上):
2 Y; V4 y) Z# _
9 G# Y2 a2 L' F/ y好了,简单的分析就到这了~大神勿喷~感谢观看~
3 J. ]' u( z6 @+ u" T i代码:
& ]4 d/ M2 s; Z% p
STM32F103RBT6_RC522_NFC_DEMO.rar
(511.74 KB, 下载次数: 4)
|