QAQ ==!
Dependencies: mbed QEI-1 nRF24L01P xiugai
PN532/PN532_HSU.cpp@15:934289377f7a, 2019-12-14 (annotated)
- Committer:
- AlexQian
- Date:
- Sat Dec 14 05:45:16 2019 +0000
- Revision:
- 15:934289377f7a
- Parent:
- 9:d03b1af2b8d8
Balance_Car;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
zhangyx | 9:d03b1af2b8d8 | 1 | //////////////////////////////////////////////////////////////////////////////// |
zhangyx | 9:d03b1af2b8d8 | 2 | // pn532 hsu interface for mbed platform |
zhangyx | 9:d03b1af2b8d8 | 3 | // |
zhangyx | 9:d03b1af2b8d8 | 4 | // by dotnfc@163.com |
zhangyx | 9:d03b1af2b8d8 | 5 | // 2016/09/10 18:16:00 |
zhangyx | 9:d03b1af2b8d8 | 6 | |
zhangyx | 9:d03b1af2b8d8 | 7 | #include "PN532_HSU.h" |
zhangyx | 9:d03b1af2b8d8 | 8 | #include "PN532_debug.h" |
zhangyx | 9:d03b1af2b8d8 | 9 | |
zhangyx | 9:d03b1af2b8d8 | 10 | |
zhangyx | 9:d03b1af2b8d8 | 11 | PN532_HSU::PN532_HSU(HardwareSerial &serial) |
zhangyx | 9:d03b1af2b8d8 | 12 | { |
zhangyx | 9:d03b1af2b8d8 | 13 | _serial = &serial; |
zhangyx | 9:d03b1af2b8d8 | 14 | command = 0; |
zhangyx | 9:d03b1af2b8d8 | 15 | } |
zhangyx | 9:d03b1af2b8d8 | 16 | |
zhangyx | 9:d03b1af2b8d8 | 17 | void PN532_HSU::begin() |
zhangyx | 9:d03b1af2b8d8 | 18 | { |
zhangyx | 9:d03b1af2b8d8 | 19 | _serial->baud(115200); |
zhangyx | 9:d03b1af2b8d8 | 20 | } |
zhangyx | 9:d03b1af2b8d8 | 21 | |
zhangyx | 9:d03b1af2b8d8 | 22 | void PN532_HSU::wakeup() |
zhangyx | 9:d03b1af2b8d8 | 23 | { |
zhangyx | 9:d03b1af2b8d8 | 24 | const uint8_t wakeup_cmd[] = { 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x05, 0xFB, 0xD4, 0x14, 0x01, 0x00, 0x01, 0x16, 0x00 }; |
zhangyx | 9:d03b1af2b8d8 | 25 | _serial->write(wakeup_cmd, sizeof(wakeup_cmd)); |
zhangyx | 9:d03b1af2b8d8 | 26 | |
zhangyx | 9:d03b1af2b8d8 | 27 | delay (50); |
zhangyx | 9:d03b1af2b8d8 | 28 | |
zhangyx | 9:d03b1af2b8d8 | 29 | /** dump serial buffer */ |
zhangyx | 9:d03b1af2b8d8 | 30 | if(_serial->readable()){ |
zhangyx | 9:d03b1af2b8d8 | 31 | DMSG("Dump sperial buffer: "); |
zhangyx | 9:d03b1af2b8d8 | 32 | } |
zhangyx | 9:d03b1af2b8d8 | 33 | while(_serial->readable()){ |
zhangyx | 9:d03b1af2b8d8 | 34 | uint8_t ret = _serial->getc(); |
zhangyx | 9:d03b1af2b8d8 | 35 | DMSG_HEX(ret); |
zhangyx | 9:d03b1af2b8d8 | 36 | } |
zhangyx | 9:d03b1af2b8d8 | 37 | DMSG("\n"); |
zhangyx | 9:d03b1af2b8d8 | 38 | } |
zhangyx | 9:d03b1af2b8d8 | 39 | |
zhangyx | 9:d03b1af2b8d8 | 40 | int8_t PN532_HSU::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) |
zhangyx | 9:d03b1af2b8d8 | 41 | { |
zhangyx | 9:d03b1af2b8d8 | 42 | /** dump serial buffer */ |
zhangyx | 9:d03b1af2b8d8 | 43 | if(_serial->readable()){ |
zhangyx | 9:d03b1af2b8d8 | 44 | DMSG("Dump sperial buffer: "); |
zhangyx | 9:d03b1af2b8d8 | 45 | } |
zhangyx | 9:d03b1af2b8d8 | 46 | while(_serial->readable()){ |
zhangyx | 9:d03b1af2b8d8 | 47 | uint8_t ret = _serial->getc(); |
zhangyx | 9:d03b1af2b8d8 | 48 | DMSG_HEX(ret); |
zhangyx | 9:d03b1af2b8d8 | 49 | } |
zhangyx | 9:d03b1af2b8d8 | 50 | DMSG("\n"); |
zhangyx | 9:d03b1af2b8d8 | 51 | |
zhangyx | 9:d03b1af2b8d8 | 52 | command = header[0]; |
zhangyx | 9:d03b1af2b8d8 | 53 | |
zhangyx | 9:d03b1af2b8d8 | 54 | _serial->write(PN532_PREAMBLE); |
zhangyx | 9:d03b1af2b8d8 | 55 | _serial->write(PN532_STARTCODE1); |
zhangyx | 9:d03b1af2b8d8 | 56 | _serial->write(PN532_STARTCODE2); |
zhangyx | 9:d03b1af2b8d8 | 57 | |
zhangyx | 9:d03b1af2b8d8 | 58 | uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA |
zhangyx | 9:d03b1af2b8d8 | 59 | _serial->write(length); |
zhangyx | 9:d03b1af2b8d8 | 60 | _serial->write(~length + 1); // checksum of length |
zhangyx | 9:d03b1af2b8d8 | 61 | |
zhangyx | 9:d03b1af2b8d8 | 62 | _serial->write(PN532_HOSTTOPN532); |
zhangyx | 9:d03b1af2b8d8 | 63 | uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA |
zhangyx | 9:d03b1af2b8d8 | 64 | |
zhangyx | 9:d03b1af2b8d8 | 65 | DMSG("\nWrite: "); |
zhangyx | 9:d03b1af2b8d8 | 66 | |
zhangyx | 9:d03b1af2b8d8 | 67 | _serial->write(header, hlen); |
zhangyx | 9:d03b1af2b8d8 | 68 | for (uint8_t i = 0; i < hlen; i++) { |
zhangyx | 9:d03b1af2b8d8 | 69 | sum += header[i]; |
zhangyx | 9:d03b1af2b8d8 | 70 | |
zhangyx | 9:d03b1af2b8d8 | 71 | DMSG_HEX(header[i]); |
zhangyx | 9:d03b1af2b8d8 | 72 | } |
zhangyx | 9:d03b1af2b8d8 | 73 | |
zhangyx | 9:d03b1af2b8d8 | 74 | _serial->write(body, blen); |
zhangyx | 9:d03b1af2b8d8 | 75 | for (uint8_t i = 0; i < blen; i++) { |
zhangyx | 9:d03b1af2b8d8 | 76 | sum += body[i]; |
zhangyx | 9:d03b1af2b8d8 | 77 | |
zhangyx | 9:d03b1af2b8d8 | 78 | DMSG_HEX(body[i]); |
zhangyx | 9:d03b1af2b8d8 | 79 | } |
zhangyx | 9:d03b1af2b8d8 | 80 | |
zhangyx | 9:d03b1af2b8d8 | 81 | uint8_t checksum = ~sum + 1; // checksum of TFI + DATA |
zhangyx | 9:d03b1af2b8d8 | 82 | _serial->write(checksum); |
zhangyx | 9:d03b1af2b8d8 | 83 | _serial->write(PN532_POSTAMBLE); |
zhangyx | 9:d03b1af2b8d8 | 84 | |
zhangyx | 9:d03b1af2b8d8 | 85 | delay (50); |
zhangyx | 9:d03b1af2b8d8 | 86 | return readAckFrame(); |
zhangyx | 9:d03b1af2b8d8 | 87 | } |
zhangyx | 9:d03b1af2b8d8 | 88 | |
zhangyx | 9:d03b1af2b8d8 | 89 | int16_t PN532_HSU::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout) |
zhangyx | 9:d03b1af2b8d8 | 90 | { |
zhangyx | 9:d03b1af2b8d8 | 91 | uint8_t tmp[3]; |
zhangyx | 9:d03b1af2b8d8 | 92 | |
zhangyx | 9:d03b1af2b8d8 | 93 | delay(100); |
zhangyx | 9:d03b1af2b8d8 | 94 | |
zhangyx | 9:d03b1af2b8d8 | 95 | DMSG("\nRead: "); |
zhangyx | 9:d03b1af2b8d8 | 96 | |
zhangyx | 9:d03b1af2b8d8 | 97 | /** Frame Preamble and Start Code */ |
zhangyx | 9:d03b1af2b8d8 | 98 | if(receive(tmp, 3, timeout)<=0){ |
zhangyx | 9:d03b1af2b8d8 | 99 | return PN532_TIMEOUT; |
zhangyx | 9:d03b1af2b8d8 | 100 | } |
zhangyx | 9:d03b1af2b8d8 | 101 | if(0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]){ |
zhangyx | 9:d03b1af2b8d8 | 102 | DMSG("Preamble error"); |
zhangyx | 9:d03b1af2b8d8 | 103 | return PN532_INVALID_FRAME; |
zhangyx | 9:d03b1af2b8d8 | 104 | } |
zhangyx | 9:d03b1af2b8d8 | 105 | |
zhangyx | 9:d03b1af2b8d8 | 106 | /** receive length and check */ |
zhangyx | 9:d03b1af2b8d8 | 107 | uint8_t length[2]; |
zhangyx | 9:d03b1af2b8d8 | 108 | if(receive(length, 2, timeout) <= 0){ |
zhangyx | 9:d03b1af2b8d8 | 109 | return PN532_TIMEOUT; |
zhangyx | 9:d03b1af2b8d8 | 110 | } |
zhangyx | 9:d03b1af2b8d8 | 111 | if( 0 != (uint8_t)(length[0] + length[1]) ){ |
zhangyx | 9:d03b1af2b8d8 | 112 | DMSG("Length error\n"); |
zhangyx | 9:d03b1af2b8d8 | 113 | return PN532_INVALID_FRAME; |
zhangyx | 9:d03b1af2b8d8 | 114 | } |
zhangyx | 9:d03b1af2b8d8 | 115 | length[0] -= 2; |
zhangyx | 9:d03b1af2b8d8 | 116 | if( length[0] > len){ |
zhangyx | 9:d03b1af2b8d8 | 117 | return PN532_NO_SPACE; |
zhangyx | 9:d03b1af2b8d8 | 118 | } |
zhangyx | 9:d03b1af2b8d8 | 119 | |
zhangyx | 9:d03b1af2b8d8 | 120 | /** receive command byte */ |
zhangyx | 9:d03b1af2b8d8 | 121 | uint8_t cmd = command + 1; // response command |
zhangyx | 9:d03b1af2b8d8 | 122 | if(receive(tmp, 2, timeout) <= 0){ |
zhangyx | 9:d03b1af2b8d8 | 123 | return PN532_TIMEOUT; |
zhangyx | 9:d03b1af2b8d8 | 124 | } |
zhangyx | 9:d03b1af2b8d8 | 125 | if( PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]){ |
zhangyx | 9:d03b1af2b8d8 | 126 | DMSG("Command error\n"); |
zhangyx | 9:d03b1af2b8d8 | 127 | return PN532_INVALID_FRAME; |
zhangyx | 9:d03b1af2b8d8 | 128 | } |
zhangyx | 9:d03b1af2b8d8 | 129 | |
zhangyx | 9:d03b1af2b8d8 | 130 | if(receive(buf, length[0], timeout) != length[0]){ |
zhangyx | 9:d03b1af2b8d8 | 131 | return PN532_TIMEOUT; |
zhangyx | 9:d03b1af2b8d8 | 132 | } |
zhangyx | 9:d03b1af2b8d8 | 133 | uint8_t sum = PN532_PN532TOHOST + cmd; |
zhangyx | 9:d03b1af2b8d8 | 134 | for(uint8_t i=0; i<length[0]; i++){ |
zhangyx | 9:d03b1af2b8d8 | 135 | sum += buf[i]; |
zhangyx | 9:d03b1af2b8d8 | 136 | } |
zhangyx | 9:d03b1af2b8d8 | 137 | |
zhangyx | 9:d03b1af2b8d8 | 138 | /** checksum and postamble */ |
zhangyx | 9:d03b1af2b8d8 | 139 | if(receive(tmp, 2, timeout) <= 0){ |
zhangyx | 9:d03b1af2b8d8 | 140 | return PN532_TIMEOUT; |
zhangyx | 9:d03b1af2b8d8 | 141 | } |
zhangyx | 9:d03b1af2b8d8 | 142 | if( 0 != (uint8_t)(sum + tmp[0]) || 0 != tmp[1] ){ |
zhangyx | 9:d03b1af2b8d8 | 143 | DMSG("Checksum error\n"); |
zhangyx | 9:d03b1af2b8d8 | 144 | return PN532_INVALID_FRAME; |
zhangyx | 9:d03b1af2b8d8 | 145 | } |
zhangyx | 9:d03b1af2b8d8 | 146 | |
zhangyx | 9:d03b1af2b8d8 | 147 | DMSG ("\n"); |
zhangyx | 9:d03b1af2b8d8 | 148 | return length[0]; |
zhangyx | 9:d03b1af2b8d8 | 149 | } |
zhangyx | 9:d03b1af2b8d8 | 150 | |
zhangyx | 9:d03b1af2b8d8 | 151 | int8_t PN532_HSU::readAckFrame() |
zhangyx | 9:d03b1af2b8d8 | 152 | { |
zhangyx | 9:d03b1af2b8d8 | 153 | const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; |
zhangyx | 9:d03b1af2b8d8 | 154 | uint8_t ackBuf[sizeof(PN532_ACK)]; |
zhangyx | 9:d03b1af2b8d8 | 155 | |
zhangyx | 9:d03b1af2b8d8 | 156 | delay(100); |
zhangyx | 9:d03b1af2b8d8 | 157 | |
zhangyx | 9:d03b1af2b8d8 | 158 | DMSG("\nAck: "); |
zhangyx | 9:d03b1af2b8d8 | 159 | |
zhangyx | 9:d03b1af2b8d8 | 160 | if( receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0 ){ |
zhangyx | 9:d03b1af2b8d8 | 161 | DMSG("Timeout\n"); |
zhangyx | 9:d03b1af2b8d8 | 162 | return PN532_TIMEOUT; |
zhangyx | 9:d03b1af2b8d8 | 163 | } |
zhangyx | 9:d03b1af2b8d8 | 164 | |
zhangyx | 9:d03b1af2b8d8 | 165 | if( memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK)) ){ |
zhangyx | 9:d03b1af2b8d8 | 166 | DMSG("Invalid\n"); |
zhangyx | 9:d03b1af2b8d8 | 167 | return PN532_INVALID_ACK; |
zhangyx | 9:d03b1af2b8d8 | 168 | } |
zhangyx | 9:d03b1af2b8d8 | 169 | return 0; |
zhangyx | 9:d03b1af2b8d8 | 170 | } |
zhangyx | 9:d03b1af2b8d8 | 171 | |
zhangyx | 9:d03b1af2b8d8 | 172 | /** |
zhangyx | 9:d03b1af2b8d8 | 173 | @brief receive data . |
zhangyx | 9:d03b1af2b8d8 | 174 | @param buf --> return value buffer. |
zhangyx | 9:d03b1af2b8d8 | 175 | len --> length expect to receive. |
zhangyx | 9:d03b1af2b8d8 | 176 | timeout --> time of reveiving |
zhangyx | 9:d03b1af2b8d8 | 177 | @retval number of received bytes, 0 means no data received. |
zhangyx | 9:d03b1af2b8d8 | 178 | */ |
zhangyx | 9:d03b1af2b8d8 | 179 | int8_t PN532_HSU::receive(uint8_t *buf, int len, uint16_t timeout) |
zhangyx | 9:d03b1af2b8d8 | 180 | { |
zhangyx | 9:d03b1af2b8d8 | 181 | int read_bytes = 0; |
zhangyx | 9:d03b1af2b8d8 | 182 | int ret; |
zhangyx | 9:d03b1af2b8d8 | 183 | Timer tmr_hsu; |
zhangyx | 9:d03b1af2b8d8 | 184 | unsigned long start_millis; |
zhangyx | 9:d03b1af2b8d8 | 185 | |
zhangyx | 9:d03b1af2b8d8 | 186 | tmr_hsu.start(); |
zhangyx | 9:d03b1af2b8d8 | 187 | while (read_bytes < len) { |
zhangyx | 9:d03b1af2b8d8 | 188 | start_millis = tmr_hsu.read_ms(); // millis(); |
zhangyx | 9:d03b1af2b8d8 | 189 | do { |
zhangyx | 9:d03b1af2b8d8 | 190 | ret = _serial->getc(); |
zhangyx | 9:d03b1af2b8d8 | 191 | if (ret >= 0) { |
zhangyx | 9:d03b1af2b8d8 | 192 | break; |
zhangyx | 9:d03b1af2b8d8 | 193 | } |
zhangyx | 9:d03b1af2b8d8 | 194 | delay(10); |
zhangyx | 9:d03b1af2b8d8 | 195 | } while((timeout == 0) || ((tmr_hsu.read_ms() /* millis() */ - start_millis ) < timeout)); |
zhangyx | 9:d03b1af2b8d8 | 196 | |
zhangyx | 9:d03b1af2b8d8 | 197 | if (ret < 0) { |
zhangyx | 9:d03b1af2b8d8 | 198 | if(read_bytes){ |
zhangyx | 9:d03b1af2b8d8 | 199 | tmr_hsu.stop (); |
zhangyx | 9:d03b1af2b8d8 | 200 | return read_bytes; |
zhangyx | 9:d03b1af2b8d8 | 201 | }else{ |
zhangyx | 9:d03b1af2b8d8 | 202 | tmr_hsu.stop (); |
zhangyx | 9:d03b1af2b8d8 | 203 | return PN532_TIMEOUT; |
zhangyx | 9:d03b1af2b8d8 | 204 | } |
zhangyx | 9:d03b1af2b8d8 | 205 | } |
zhangyx | 9:d03b1af2b8d8 | 206 | buf[read_bytes] = (uint8_t)ret; |
zhangyx | 9:d03b1af2b8d8 | 207 | DMSG_HEX(ret); |
zhangyx | 9:d03b1af2b8d8 | 208 | read_bytes++; |
zhangyx | 9:d03b1af2b8d8 | 209 | } |
zhangyx | 9:d03b1af2b8d8 | 210 | |
zhangyx | 9:d03b1af2b8d8 | 211 | tmr_hsu.stop (); |
zhangyx | 9:d03b1af2b8d8 | 212 | return read_bytes; |
zhangyx | 9:d03b1af2b8d8 | 213 | } |
zhangyx | 9:d03b1af2b8d8 | 214 |