Module RFID
Giao tiếp với module thông qua SPI.
Code thư viện SPI. Sử dụng SPI2
file spi.h
#include "stm32f10x.h" /*======================================================================= Ngo Hung Cuong http://vidieukhien.org ngohungcuong@gmail.com 0989696971 =======================================================================*/ #ifndef KT_SPI_H_ #define KT_SPI_H_ void TM_SPI_Init(void); uint8_t TM_SPI_Send(uint8_t data); extern void TM_MFRC522_InitPins(void); #define MFRC522_CS_LOW GPIO_ResetBits(GPIOB, GPIO_Pin_12) #define MFRC522_CS_HIGH GPIO_SetBits(GPIOB, GPIO_Pin_12) #endif
file spi.c
#include "spi.h" uint8_t TM_SPI_Send(uint8_t data) { SPI_I2S_SendData(SPI2, data); while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET) { } return SPI_I2S_ReceiveData(SPI2); } void TM_SPI_Init(void) { GPIO_InitTypeDef gpioInit; SPI_InitTypeDef SPI_InitStructure; RCC_APB1PeriphClockCmd (RCC_APB1Periph_SPI2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); gpioInit.GPIO_Mode=GPIO_Mode_AF_PP; gpioInit.GPIO_Speed=GPIO_Speed_50MHz; gpioInit.GPIO_Pin=GPIO_Pin_13 | GPIO_Pin_15; GPIO_Init(GPIOB, &gpioInit); gpioInit.GPIO_Mode=GPIO_Mode_IN_FLOATING; gpioInit.GPIO_Speed=GPIO_Speed_50MHz; gpioInit.GPIO_Pin=GPIO_Pin_14; GPIO_Init(GPIOB, &gpioInit); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &SPI_InitStructure); SPI_Cmd(SPI2, ENABLE); } void TM_MFRC522_InitPins(void) { GPIO_InitTypeDef gpioInit; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); gpioInit.GPIO_Mode=GPIO_Mode_Out_PP; gpioInit.GPIO_Speed=GPIO_Speed_50MHz; gpioInit.GPIO_Pin=GPIO_Pin_12; GPIO_Init(GPIOB, &gpioInit); MFRC522_CS_HIGH; }
Thư viện MFRC522
file mfrc522.h
#ifndef TM_MFRC522_H #define TM_MFRC522_H #include "stm32f10x.h" /** * Status enumeration * * Used with most functions */ typedef enum { MI_OK = 0, MI_NOTAGERR, MI_ERR } TM_MFRC522_Status_t; /* MFRC522 Commands */ #define PCD_IDLE 0x00 //NO action; Cancel the current command #define PCD_AUTHENT 0x0E //Authentication Key #define PCD_RECEIVE 0x08 //Receive Data #define PCD_TRANSMIT 0x04 //Transmit data #define PCD_TRANSCEIVE 0x0C //Transmit and receive data, #define PCD_RESETPHASE 0x0F //Reset #define PCD_CALCCRC 0x03 //CRC Calculate /* Mifare_One card command word */ #define PICC_REQIDL 0x26 // find the antenna area does not enter hibernation #define PICC_REQALL 0x52 // find all the cards antenna area #define PICC_ANTICOLL 0x93 // anti-collision #define PICC_SElECTTAG 0x93 // election card #define PICC_AUTHENT1A 0x60 // authentication key A #define PICC_AUTHENT1B 0x61 // authentication key B #define PICC_READ 0x30 // Read Block #define PICC_WRITE 0xA0 // write block #define PICC_DECREMENT 0xC0 // debit #define PICC_INCREMENT 0xC1 // recharge #define PICC_RESTORE 0xC2 // transfer block data to the buffer #define PICC_TRANSFER 0xB0 // save the data in the buffer #define PICC_HALT 0x50 // Sleep /* MFRC522 Registers */ //Page 0: Command and Status #define MFRC522_REG_RESERVED00 0x00 #define MFRC522_REG_COMMAND 0x01 #define MFRC522_REG_COMM_IE_N 0x02 #define MFRC522_REG_DIV1_EN 0x03 #define MFRC522_REG_COMM_IRQ 0x04 #define MFRC522_REG_DIV_IRQ 0x05 #define MFRC522_REG_ERROR 0x06 #define MFRC522_REG_STATUS1 0x07 #define MFRC522_REG_STATUS2 0x08 #define MFRC522_REG_FIFO_DATA 0x09 #define MFRC522_REG_FIFO_LEVEL 0x0A #define MFRC522_REG_WATER_LEVEL 0x0B #define MFRC522_REG_CONTROL 0x0C #define MFRC522_REG_BIT_FRAMING 0x0D #define MFRC522_REG_COLL 0x0E #define MFRC522_REG_RESERVED01 0x0F //Page 1: Command #define MFRC522_REG_RESERVED10 0x10 #define MFRC522_REG_MODE 0x11 #define MFRC522_REG_TX_MODE 0x12 #define MFRC522_REG_RX_MODE 0x13 #define MFRC522_REG_TX_CONTROL 0x14 #define MFRC522_REG_TX_AUTO 0x15 #define MFRC522_REG_TX_SELL 0x16 #define MFRC522_REG_RX_SELL 0x17 #define MFRC522_REG_RX_THRESHOLD 0x18 #define MFRC522_REG_DEMOD 0x19 #define MFRC522_REG_RESERVED11 0x1A #define MFRC522_REG_RESERVED12 0x1B #define MFRC522_REG_MIFARE 0x1C #define MFRC522_REG_RESERVED13 0x1D #define MFRC522_REG_RESERVED14 0x1E #define MFRC522_REG_SERIALSPEED 0x1F //Page 2: CFG #define MFRC522_REG_RESERVED20 0x20 #define MFRC522_REG_CRC_RESULT_M 0x21 #define MFRC522_REG_CRC_RESULT_L 0x22 #define MFRC522_REG_RESERVED21 0x23 #define MFRC522_REG_MOD_WIDTH 0x24 #define MFRC522_REG_RESERVED22 0x25 #define MFRC522_REG_RF_CFG 0x26 #define MFRC522_REG_GS_N 0x27 #define MFRC522_REG_CWGS_PREG 0x28 #define MFRC522_REG__MODGS_PREG 0x29 #define MFRC522_REG_T_MODE 0x2A #define MFRC522_REG_T_PRESCALER 0x2B #define MFRC522_REG_T_RELOAD_H 0x2C #define MFRC522_REG_T_RELOAD_L 0x2D #define MFRC522_REG_T_COUNTER_VALUE_H 0x2E #define MFRC522_REG_T_COUNTER_VALUE_L 0x2F //Page 3:TestRegister #define MFRC522_REG_RESERVED30 0x30 #define MFRC522_REG_TEST_SEL1 0x31 #define MFRC522_REG_TEST_SEL2 0x32 #define MFRC522_REG_TEST_PIN_EN 0x33 #define MFRC522_REG_TEST_PIN_VALUE 0x34 #define MFRC522_REG_TEST_BUS 0x35 #define MFRC522_REG_AUTO_TEST 0x36 #define MFRC522_REG_VERSION 0x37 #define MFRC522_REG_ANALOG_TEST 0x38 #define MFRC522_REG_TEST_ADC1 0x39 #define MFRC522_REG_TEST_ADC2 0x3A #define MFRC522_REG_TEST_ADC0 0x3B #define MFRC522_REG_RESERVED31 0x3C #define MFRC522_REG_RESERVED32 0x3D #define MFRC522_REG_RESERVED33 0x3E #define MFRC522_REG_RESERVED34 0x3F //Dummy byte #define MFRC522_DUMMY 0x00 #define MFRC522_MAX_LEN 16 /** * Public functions */ /** * Initialize MFRC522 RFID reader * * Prepare MFRC522 to work with RFIDs * */ extern void TM_MFRC522_Init(void); /** * Check for RFID card existance * * Parameters: * - uint8_t* id: * Pointer to 5bytes long memory to store valid card id in. * ID is valid only if card is detected, so when function returns MI_OK * * Returns MI_OK if card is detected */ extern TM_MFRC522_Status_t TM_MFRC522_Check(uint8_t* id); /** * Compare 2 RFID ID's * Useful if you have known ID (database with allowed IDs), to compare detected card with with your ID * * Parameters: * - uint8_t* CardID: * Pointer to 5bytes detected card ID * - uint8_t* CompareID: * Pointer to 5bytes your ID * * Returns MI_OK if IDs are the same, or MI_ERR if not */ extern TM_MFRC522_Status_t TM_MFRC522_Compare(uint8_t* CardID, uint8_t* CompareID); /** * Private functions */ extern void TM_MFRC522_WriteRegister(uint8_t addr, uint8_t val); extern uint8_t TM_MFRC522_ReadRegister(uint8_t addr); extern void TM_MFRC522_SetBitMask(uint8_t reg, uint8_t mask); extern void TM_MFRC522_ClearBitMask(uint8_t reg, uint8_t mask); extern void TM_MFRC522_AntennaOn(void); extern void TM_MFRC522_AntennaOff(void); extern void TM_MFRC522_Reset(void); extern TM_MFRC522_Status_t TM_MFRC522_Request(uint8_t reqMode, uint8_t* TagType); extern TM_MFRC522_Status_t TM_MFRC522_ToCard(uint8_t command, uint8_t* sendData, uint8_t sendLen, uint8_t* backData, uint16_t* backLen); extern TM_MFRC522_Status_t TM_MFRC522_Anticoll(uint8_t* serNum); extern void TM_MFRC522_CalculateCRC(uint8_t* pIndata, uint8_t len, uint8_t* pOutData); extern uint8_t TM_MFRC522_SelectTag(uint8_t* serNum); extern TM_MFRC522_Status_t TM_MFRC522_Auth(uint8_t authMode, uint8_t BlockAddr, uint8_t* Sectorkey, uint8_t* serNum); extern TM_MFRC522_Status_t TM_MFRC522_Read(uint8_t blockAddr, uint8_t* recvData); extern TM_MFRC522_Status_t TM_MFRC522_Write(uint8_t blockAddr, uint8_t* writeData); extern void TM_MFRC522_Halt(void); #endif
file mfrc522.c
/** * |---------------------------------------------------------------------- * | Copyright (C) Tilen Majerle, 2014 * | * | This program is free software: you can redistribute it and/or modify * | it under the terms of the GNU General Public License as published by * | the Free Software Foundation, either version 3 of the License, or * | any later version. * | * | This program is distributed in the hope that it will be useful, * | but WITHOUT ANY WARRANTY; without even the implied warranty of * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | GNU General Public License for more details. * | * | You should have received a copy of the GNU General Public License * | along with this program. If not, see <http://www.gnu.org/licenses/>. * |---------------------------------------------------------------------- */ #include "mfrc522.h" #include "spi.h" void TM_MFRC522_Init(void) { TM_MFRC522_InitPins(); TM_SPI_Init(); TM_MFRC522_Reset(); TM_MFRC522_WriteRegister(MFRC522_REG_T_MODE, 0x8D); TM_MFRC522_WriteRegister(MFRC522_REG_T_PRESCALER, 0x3E); TM_MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_L, 30); TM_MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_H, 0); /* 48dB gain */ TM_MFRC522_WriteRegister(MFRC522_REG_RF_CFG, 0x70); TM_MFRC522_WriteRegister(MFRC522_REG_TX_AUTO, 0x40); TM_MFRC522_WriteRegister(MFRC522_REG_MODE, 0x3D); TM_MFRC522_AntennaOn(); //Open the antenna } TM_MFRC522_Status_t TM_MFRC522_Check(uint8_t* id) { TM_MFRC522_Status_t status; //Find cards, return card type status = TM_MFRC522_Request(PICC_REQIDL, id); if (status == MI_OK) { //Card detected //Anti-collision, return card serial number 4 bytes status = TM_MFRC522_Anticoll(id); } TM_MFRC522_Halt(); //Command card into hibernation return status; } TM_MFRC522_Status_t TM_MFRC522_Compare(uint8_t* CardID, uint8_t* CompareID) { uint8_t i; for (i = 0; i < 5; i++) { if (CardID[i] != CompareID[i]) { return MI_ERR; } } return MI_OK; } //================================================== //ham nay can thay doi vi cau truc F1 khac F4 void TM_MFRC522_WriteRegister(uint8_t addr, uint8_t val) { //CS low MFRC522_CS_LOW; //Send address TM_SPI_Send((addr << 1) & 0x7E); //Send data TM_SPI_Send(val); //CS high MFRC522_CS_HIGH; } uint8_t TM_MFRC522_ReadRegister(uint8_t addr) { uint8_t val; //CS low MFRC522_CS_LOW; TM_SPI_Send(((addr << 1) & 0x7E) | 0x80); val = TM_SPI_Send(MFRC522_DUMMY); //CS high MFRC522_CS_HIGH; return val; } void TM_MFRC522_SetBitMask(uint8_t reg, uint8_t mask) { TM_MFRC522_WriteRegister(reg, TM_MFRC522_ReadRegister(reg) | mask); } void TM_MFRC522_ClearBitMask(uint8_t reg, uint8_t mask){ TM_MFRC522_WriteRegister(reg, TM_MFRC522_ReadRegister(reg) & (~mask)); } void TM_MFRC522_AntennaOn(void) { uint8_t temp; temp = TM_MFRC522_ReadRegister(MFRC522_REG_TX_CONTROL); if (!(temp & 0x03)) { TM_MFRC522_SetBitMask(MFRC522_REG_TX_CONTROL, 0x03); } } void TM_MFRC522_AntennaOff(void) { TM_MFRC522_ClearBitMask(MFRC522_REG_TX_CONTROL, 0x03); } void TM_MFRC522_Reset(void) { TM_MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_RESETPHASE); } TM_MFRC522_Status_t TM_MFRC522_Request(uint8_t reqMode, uint8_t* TagType) { TM_MFRC522_Status_t status; uint16_t backBits; //The received data bits TM_MFRC522_WriteRegister(MFRC522_REG_BIT_FRAMING, 0x07); //TxLastBists = BitFramingReg[2..0] ??? TagType[0] = reqMode; status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits); if ((status != MI_OK) || (backBits != 0x10)) { status = MI_ERR; } return status; } TM_MFRC522_Status_t TM_MFRC522_ToCard(uint8_t command, uint8_t* sendData, uint8_t sendLen, uint8_t* backData, uint16_t* backLen) { TM_MFRC522_Status_t status = MI_ERR; uint8_t irqEn = 0x00; uint8_t waitIRq = 0x00; uint8_t lastBits; uint8_t n; uint16_t i; switch (command) { case PCD_AUTHENT: { irqEn = 0x12; waitIRq = 0x10; break; } case PCD_TRANSCEIVE: { irqEn = 0x77; waitIRq = 0x30; break; } default: break; } TM_MFRC522_WriteRegister(MFRC522_REG_COMM_IE_N, irqEn | 0x80); TM_MFRC522_ClearBitMask(MFRC522_REG_COMM_IRQ, 0x80); TM_MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80); TM_MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_IDLE); //Writing data to the FIFO for (i = 0; i < sendLen; i++) { TM_MFRC522_WriteRegister(MFRC522_REG_FIFO_DATA, sendData[i]); } //Execute the command TM_MFRC522_WriteRegister(MFRC522_REG_COMMAND, command); if (command == PCD_TRANSCEIVE) { TM_MFRC522_SetBitMask(MFRC522_REG_BIT_FRAMING, 0x80); //StartSend=1,transmission of data starts } //Waiting to receive data to complete i = 2000; //i according to the clock frequency adjustment, the operator M1 card maximum waiting time 25ms??? do { //CommIrqReg[7..0] //Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq n = TM_MFRC522_ReadRegister(MFRC522_REG_COMM_IRQ); i--; } while ((i!=0) && !(n&0x01) && !(n&waitIRq)); TM_MFRC522_ClearBitMask(MFRC522_REG_BIT_FRAMING, 0x80); //StartSend=0 if (i != 0) { if (!(TM_MFRC522_ReadRegister(MFRC522_REG_ERROR) & 0x1B)) { status = MI_OK; if (n & irqEn & 0x01) { status = MI_NOTAGERR; } if (command == PCD_TRANSCEIVE) { n = TM_MFRC522_ReadRegister(MFRC522_REG_FIFO_LEVEL); lastBits = TM_MFRC522_ReadRegister(MFRC522_REG_CONTROL) & 0x07; if (lastBits) { *backLen = (n - 1) * 8 + lastBits; } else { *backLen = n * 8; } if (n == 0) { n = 1; } if (n > MFRC522_MAX_LEN) { n = MFRC522_MAX_LEN; } //Reading the received data in FIFO for (i = 0; i < n; i++) { backData[i] = TM_MFRC522_ReadRegister(MFRC522_REG_FIFO_DATA); } } } else { status = MI_ERR; } } return status; } TM_MFRC522_Status_t TM_MFRC522_Anticoll(uint8_t* serNum) { TM_MFRC522_Status_t status; uint8_t i; uint8_t serNumCheck = 0; uint16_t unLen; TM_MFRC522_WriteRegister(MFRC522_REG_BIT_FRAMING, 0x00); //TxLastBists = BitFramingReg[2..0] serNum[0] = PICC_ANTICOLL; serNum[1] = 0x20; status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen); if (status == MI_OK) { //Check card serial number for (i = 0; i < 4; i++) { serNumCheck ^= serNum[i]; } if (serNumCheck != serNum[i]) { status = MI_ERR; } } return status; } void TM_MFRC522_CalculateCRC(uint8_t* pIndata, uint8_t len, uint8_t* pOutData) { uint8_t i, n; TM_MFRC522_ClearBitMask(MFRC522_REG_DIV_IRQ, 0x04); //CRCIrq = 0 TM_MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80); //Clear the FIFO pointer //Write_MFRC522(CommandReg, PCD_IDLE); //Writing data to the FIFO for (i = 0; i < len; i++) { TM_MFRC522_WriteRegister(MFRC522_REG_FIFO_DATA, *(pIndata+i)); } TM_MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_CALCCRC); //Wait CRC calculation is complete i = 0xFF; do { n = TM_MFRC522_ReadRegister(MFRC522_REG_DIV_IRQ); i--; } while ((i!=0) && !(n&0x04)); //CRCIrq = 1 //Read CRC calculation result pOutData[0] = TM_MFRC522_ReadRegister(MFRC522_REG_CRC_RESULT_L); pOutData[1] = TM_MFRC522_ReadRegister(MFRC522_REG_CRC_RESULT_M); } uint8_t TM_MFRC522_SelectTag(uint8_t* serNum) { uint8_t i; TM_MFRC522_Status_t status; uint8_t size; uint16_t recvBits; uint8_t buffer[9]; buffer[0] = PICC_SElECTTAG; buffer[1] = 0x70; for (i = 0; i < 5; i++) { buffer[i+2] = *(serNum+i); } TM_MFRC522_CalculateCRC(buffer, 7, &buffer[7]); //?? status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, buffer, 9, buffer, &recvBits); if ((status == MI_OK) && (recvBits == 0x18)) { size = buffer[0]; } else { size = 0; } return size; } TM_MFRC522_Status_t TM_MFRC522_Auth(uint8_t authMode, uint8_t BlockAddr, uint8_t* Sectorkey, uint8_t* serNum) { TM_MFRC522_Status_t status; uint16_t recvBits; uint8_t i; uint8_t buff[12]; //Verify the command block address + sector + password + card serial number buff[0] = authMode; buff[1] = BlockAddr; for (i = 0; i < 6; i++) { buff[i+2] = *(Sectorkey+i); } for (i=0; i<4; i++) { buff[i+8] = *(serNum+i); } status = TM_MFRC522_ToCard(PCD_AUTHENT, buff, 12, buff, &recvBits); if ((status != MI_OK) || (!(TM_MFRC522_ReadRegister(MFRC522_REG_STATUS2) & 0x08))) { status = MI_ERR; } return status; } TM_MFRC522_Status_t TM_MFRC522_Read(uint8_t blockAddr, uint8_t* recvData) { TM_MFRC522_Status_t status; uint16_t unLen; recvData[0] = PICC_READ; recvData[1] = blockAddr; TM_MFRC522_CalculateCRC(recvData,2, &recvData[2]); status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, recvData, 4, recvData, &unLen); if ((status != MI_OK) || (unLen != 0x90)) { status = MI_ERR; } return status; } TM_MFRC522_Status_t TM_MFRC522_Write(uint8_t blockAddr, uint8_t* writeData) { TM_MFRC522_Status_t status; uint16_t recvBits; uint8_t i; uint8_t buff[18]; buff[0] = PICC_WRITE; buff[1] = blockAddr; TM_MFRC522_CalculateCRC(buff, 2, &buff[2]); status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &recvBits); if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) { status = MI_ERR; } if (status == MI_OK) { //Data to the FIFO write 16Byte for (i = 0; i < 16; i++) { buff[i] = *(writeData+i); } TM_MFRC522_CalculateCRC(buff, 16, &buff[16]); status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, buff, 18, buff, &recvBits); if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) { status = MI_ERR; } } return status; } void TM_MFRC522_Halt(void) { uint16_t unLen; uint8_t buff[4]; buff[0] = PICC_HALT; buff[1] = 0; TM_MFRC522_CalculateCRC(buff, 2, &buff[2]); TM_MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &unLen); }
Ví dụ sử dụng LCD1602 để hiển thị. Mỗi khi quẹt thẻ thì hiển thị ID
file main.c
#include "stm32f10x.h" #include "delay.h" #include "mfrc522.h" #include "i2c_lcd.h" #include <stdio.h> void My_GPIO_Init(void); uint8_t CardID[5]; char szBuff[100]; int main() { Delay_Init(); My_GPIO_Init(); TM_MFRC522_Init(); I2C_LCD_Init(); I2C_LCD_Clear(); I2C_LCD_BackLight(1); I2C_LCD_Puts("STM32 - MFRC522"); I2C_LCD_NewLine(); I2C_LCD_Puts("vidieukhien.org"); while(1) { if (TM_MFRC522_Check(CardID) == MI_OK) { sprintf(szBuff, "ID: 0x%02X%02X%02X%02X%02X", CardID[0], CardID[1], CardID[2], CardID[3], CardID[4]); I2C_LCD_Clear(); I2C_LCD_Puts("STM32 - MFRC522"); I2C_LCD_NewLine(); I2C_LCD_Puts(szBuff); GPIO_SetBits(GPIOC, GPIO_Pin_13); Delay_Ms(2000); GPIO_ResetBits(GPIOC, GPIO_Pin_13); } } } void My_GPIO_Init(void) { GPIO_InitTypeDef gpioInit; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); gpioInit.GPIO_Mode=GPIO_Mode_Out_PP; gpioInit.GPIO_Speed=GPIO_Speed_50MHz; gpioInit.GPIO_Pin=GPIO_Pin_13; GPIO_Init(GPIOC, &gpioInit); }
Kết nối với module LCD
Chân PB6 – I2C CLK
Chân PB7 – I2C DATA
Kết nối với module RFID
Chân PB12 – SS
Chân PB13 – SCK
Chân PB14 – MISO
Chân PB15 – MOSI
Kết quả:
Project:
https://drive.google.com/open?id=1smxj96Wv8oSAJO_pQEcqmEKZzdM6ypDi