/******************************************************************************/ /** \file fm175xx.c ** ** fm175xx driver API. ** @link Driver Group Some description @endlink ** ** - 2020-07-29 1.0 Ronnie First version for Device Driver Library of ** Module. ** ******************************************************************************/ /******************************************************************************* * Include files ******************************************************************************/ #include "fm175xx.h" #include "lpcd.h" #define TAG "fm175xx" /****************************************************************************** * Local pre-processor symbols/macros ('#define') ******************************************************************************/ #define MI_NOTAGERR 0xEE #define MAXRLEN 64 /* FIFO最大长度 */ #define Anticollision 0x02 /****************************************************************************** * Global variable definitions (declared in header file with 'extern') ******************************************************************************/ /****************************************************************************** * Local type definitions ('typedef') ******************************************************************************/ /****************************************************************************** * Local function prototypes ('static') ******************************************************************************/ /****************************************************************************** * Local variable definitions ('static') * ******************************************************************************/ /***************************************************************************** * Function implementation - global ('extern') and local ('static') ******************************************************************************/ /********************************************************************************************************* ** Function name: Read_Reg ** Descriptions: 读取寄存器 ** input parameters: reg_add:寄存器数值 ** output parameters: N/A ** Returned value: 寄存器数值 *********************************************************************************************************/ uint8_t GetReg(uint8_t reg_add,uint8_t *regData) { *regData=ReadRawRC(reg_add); return *regData; } /********************************************************************************************************* ** Function name: Read_Reg ** Descriptions: 读取寄存器 ** input parameters: reg_add:寄存器数值 ** output parameters: N/A ** Returned value: 寄存器数值 *********************************************************************************************************/ uint8_t SetReg(uint8_t reg_add,uint8_t ucRegVal) { WriteRawRC(reg_add, ucRegVal); return 1; } /********************************************************************************************************* ** Function name: Read_Reg ** Descriptions: 读取寄存器数值 ** input parameters: reg_add:寄存器地址 ** output parameters: N/A ** Returned value: 寄存器数值 *********************************************************************************************************/ uint8_t Read_Reg(uint8_t reg_addr) { uint8_t reg_value = ReadRawRC(reg_addr); return reg_value; } /********************************************************************************************************* ** Function name: Read_Reg_All ** Descriptions: 读取全部寄存器 ** input parameters: reg_value:寄存器数值 ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ bool Read_Reg_All(uint8_t *reg_value) { uint8_t i; for(i = 0; i < 64; i++) { *(reg_value + i) = ReadRawRC(i); } return true; } /********************************************************************************************************* ** Function name: Write_Reg ** Descriptions: 写寄存器操作 ** input parameters: reg_addr:寄存器地址 ** reg_value:寄存器数值 ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ bool Write_Reg(uint8_t reg_addr, uint8_t reg_value) { WriteRawRC(reg_addr, reg_value); return true; } /********************************************************************************************************* ** Function name: Read_FIFO ** Descriptions: 读出FIFO的数据 ** input parameters: length:读取数据长度 ** *fifo_data:数据存放指针 ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ void Read_FIFO(uint8_t length, uint8_t *fifo_data) { uint8_t i; if (length == 0) return; for (i = 0; i < length; i++) { *(fifo_data + i) = Read_Reg(FIFODataReg); } } /********************************************************************************************************* ** Function name: Write_FIFO ** Descriptions: 写入FIFO ** input parameters: length:读取数据长度 ** *fifo_data:数据存放指针 ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ void Write_FIFO(uint8_t length, uint8_t *fifo_data) { uint8_t i; if(length == 0) return; for (i = 0; i < length; i++) { Write_Reg(FIFODataReg, *(fifo_data + i)); } } /********************************************************************************************************* ** Function name: Clear_FIFO ** Descriptions: 清空FIFO ** input parameters: ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ bool Clear_FIFO(void) { Set_BitMask(FIFOLevelReg, 0x80); /* 清除FIFO缓冲 */ if ( Read_Reg(FIFOLevelReg) == 0 ) return true; else return false; } /********************************************************************************************************* ** Function name: Set_BitMask ** Descriptions: 置位寄存器操作 ** input parameters: reg_add,寄存器地址 ** mask,寄存器写1位 ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ bool Set_BitMask(uint8_t reg_addr, uint8_t mask) { bool result; result = Write_Reg(reg_addr, Read_Reg(reg_addr) | mask); /* set bit mask */ return result; } /********************************************************************************************************* ** Function name: Clear_BitMask ** Descriptions: 清除位寄存器操作 ** input parameters: reg_add,寄存器地址 ** mask,寄存器清除位 ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ bool Clear_BitMask(uint8_t reg_addr, uint8_t mask) { bool result; result = Write_Reg(reg_addr, Read_Reg(reg_addr) & ~mask); /* clear bit mask */ return result; } /********************************************************************************************************* ** Function name: Read_Ext_Reg ** Descriptions: 读取扩展寄存器 ** input parameters: reg_add,寄存器地址; ** output parameters: reg_value,寄存器数值 ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ uint8_t Read_Ext_Reg(uint8_t reg_add) { Write_Reg(JREG_EXT_REG_ENTRANCE, JBIT_EXT_REG_RD_ADDR + reg_add); return Read_Reg(JREG_EXT_REG_ENTRANCE); } /********************************************************************************************************* ** Function name: Write_Ext_Reg ** Descriptions: 写入扩展寄存器 ** input parameters: reg_add,寄存器地址; ** reg_value,寄存器数值 ** output parameters: ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ bool Write_Ext_Reg(uint8_t reg_add, uint8_t reg_value) { Write_Reg(JREG_EXT_REG_ENTRANCE, JBIT_EXT_REG_WR_ADDR + reg_add); return Write_Reg(JREG_EXT_REG_ENTRANCE, JBIT_EXT_REG_WR_DATA + reg_value); } /********************************************************************************************************* ** Function name: ModifyReg_Ext ** Descriptions: 扩展寄存器位操作 ** input parameters: reg_add,寄存器地址; ** reg_value,寄存器数值 ** output parameters: ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ bool ModifyReg_Ext(uint8_t ExtRegAddr, uint8_t mask, uint8_t set) { uint8_t regdata; regdata = Read_Ext_Reg(ExtRegAddr); if(set) { regdata |= mask; } else{ regdata &= ~(mask); } return Write_Ext_Reg(ExtRegAddr, regdata); } /********************************************************************************************************* ** Function name: Get_FIFODataLenth ** Descriptions: 读取FIFO接收数据长度信息 ** input parameters: FIFOLen: FIFO有效字节长度 ** LastBitsLen: 最后字节的有效位长度 ** pRecBitsLen: 所有数据的位长度 ** output parameters: N/A ** Returned value: true:操作成功 false:操作失败 *********************************************************************************************************/ bool Get_FIFODataLenth(uint8_t *FIFOLen,uint8_t *LastBitsLen,uint32_t *pRecBitsLen) { *FIFOLen = Read_Reg(FIFOLevelReg); /* 读取FIFO有效字节长度 */ *LastBitsLen = Read_Reg(ControlReg) & 0x07; /* 读取FIFO最后字节的有效位长度 */ if(*LastBitsLen) { /* 计算所有字节的的有效位长度和 */ *pRecBitsLen = *LastBitsLen; if(*FIFOLen > 1){ *pRecBitsLen += (*FIFOLen-1)*8; } if(*FIFOLen == 0) { *FIFOLen = 1; } } else { *pRecBitsLen = (*FIFOLen) * 8; } return true; } /********************************************************************************************************* ** Function name: Set_RF ** Descriptions: 设置射频输出 ** input parameters: mode,射频输出模式 ** 0,关闭输出 ** 1,仅打开TX1输出 ** 2,仅打开TX2输出 ** 3,TX1,TX2打开输出,TX2为反向输出 ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ bool Set_Rf(uint8_t mode) { uint8_t regVal; bool result = false; if( (Read_Reg(TxControlReg) & 0x03) == mode ) return true; if( mode == 0 ) result = Clear_BitMask(TxControlReg, 0x03); /* 关闭TX1,TX2输出 */ if( mode== 1 ) { regVal = Read_Reg(TxControlReg); regVal = regVal & 0xFC; result = Write_Reg(TxControlReg, regVal | 0x01); /* 仅打开TX1输出 */ } if( mode == 2) { regVal = Read_Reg(TxControlReg); regVal = regVal & 0xFC; result = Write_Reg(TxControlReg, regVal |0x02); /* 仅打开TX2输出 */ } if (mode == 3) { result = Set_BitMask(TxControlReg,0x03); /* 打开TX1,TX2输出 */ } Delay_Ms(10); return result; } /********************************************************************************************************* ** Function name: Pcd_Comm ** Descriptions: 读卡器通信 不利用IRQ管脚的情况 ** input parameters: Command:通信操作命令 ** pInData:发送数据数组 ** InLenByte:发送数据数组字节长度 ** pOutData:接收数据数组 ** pOutLenBit:接收数据的位长度 ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ bool Pcd_Comm(uint8_t Command, uint8_t *pInData, uint8_t InLenByte, uint8_t *pOutData, uint32_t *pOutLenBit) { uint8_t status = false; uint8_t irqEn = 0x00; /* 使能的中断 */ uint8_t waitFor = 0x00; /* 等待的中断 */ uint8_t lastBits = 0x00; uint8_t n; /* 获取中断请求寄存器 */ uint8_t sendLen = 0x00; /* 发送数据长度 */ uint8_t sendPi = 0x00; uint8_t revLen = 0x00; /* 接收数据长度 */ uint8_t fifoLen = 0x00; uint8_t errorReg = 0x00; /* 错误标志位 */ uint8_t collPos = 0x00; /* 冲突位 */ uint32_t i; Write_Reg(ComIrqReg, 0x7F); /* 清楚IRQ标记 */ Write_Reg(TModeReg, 0x80); /* 设置TIMER自动启动 */ switch (Command) { case MFAuthent: /* Mifare认证 */ irqEn = 0x12; waitFor = 0x10; break; case Transceive: /* 发送FIFO中的数据到天线,传输后激活接收电路*/ irqEn = 0x77; waitFor = 0x30; break; default: break; } Write_Reg(ComIEnReg, irqEn | 0x80); Write_Reg(CommandReg, Idle); Set_BitMask(FIFOLevelReg, 0x80); /* 最高位置1,立刻清除FIFO的读写指针和寄存器ErrReg里的BufferOvfl位 */ Clear_FIFO(); /* 清空FIFO数据 */ sendLen = InLenByte > MAXRLEN ? MAXRLEN:InLenByte; /* 限制发送数据长度,最大长度为FIFO长度64字节 */ sendPi += sendLen; InLenByte -= sendLen; Write_FIFO(sendLen, pInData); /* 数据写入FIFO */ Write_Reg(CommandReg, Command); /* 设置数据发送命令 */ if (Command == Transceive) { Set_BitMask(BitFramingReg, 0x80); /* 开启数据发送 */ } i = 30000; /* 根据时钟频率调整,操作M1卡最大等待时间25ms*/ do { n = Read_Reg(ComIrqReg); /* 读取控制中断请求寄存器 */ i--; } // while ((i != 0) && !(n & 0x03) && !(n & waitFor)); delay_ms(2); /* n&0x01=0x00表示PCDsettimer时间未到未超时(如果换成(n&0x03)则需要加一定延时Mifare卡才能写成功)*/ while ((i != 0) && !(n & 0x01) && !(n & waitFor)); /* n&waitFor!=0x00表示接收到一串有效数据流 */ // ESP_LOGI(TAG, "ComIrqReg=0x%x\r\n", n); Clear_BitMask(BitFramingReg, 0x80); /* 关闭发送 */ if (i != 0) { errorReg = Read_Reg(ErrorReg); if(!(errorReg & 0x1B)) { /* 无错误 */ status = true; if (n & irqEn & 0x01) { /* 等待超时 */ status = MI_NOTAGERR; } if (Command == Transceive) { fifoLen = Read_Reg(FIFOLevelReg); /* 读取接收数据字节数 */ lastBits = Read_Reg(ControlReg) & 0x07; /* 读取该接收最后一字节的有效位 */ if (lastBits) { *pOutLenBit = lastBits; if(fifoLen > 1) *pOutLenBit += (fifoLen-1) * 8; if (fifoLen == 0) fifoLen = 1; } else { *pOutLenBit = fifoLen * 8; } Read_FIFO(fifoLen, &pOutData[revLen]); /* 读取FIFO数据 */ } } else if(errorReg & 0x08) { /* 有冲突 */ // ESP_LOGI(TAG, "冲突\r\n"); Write_Reg(ErrorReg, ~(0x08)); /* 清除接收中断 */ collPos = Read_Reg(CollReg); /* 获取冲突位置 冲突在第几位(1-32)*/ collPos &= 0x1f; *pOutLenBit = (collPos == 0 )?32:collPos; fifoLen =*pOutLenBit/8 +(*pOutLenBit%8?1:0); /* 字节长度 */ Read_FIFO(fifoLen, &pOutData[revLen]); status = Anticollision; } else { status = false; } } Clear_BitMask(BitFramingReg, 0x80);//关闭发送 return status; } /********************************************************************************************************* ** Function name: Pcd_SetTimer ** Descriptions: 设置接收延时 ** input parameters: delaytime,延时时间(单位为毫秒) 最大不能超过5000ms ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ bool Pcd_SetTimer(uint32_t delaytime) { uint32_t TimeReload; uint32_t Prescaler; Prescaler = 0; TimeReload = 0; while(Prescaler < 0xfff) { TimeReload = ((delaytime * (long)13560) - 1) / (Prescaler * 2 + 1); if (TimeReload < 0xffff) break; Prescaler++; } TimeReload = TimeReload & 0xFFFF; Set_BitMask(TModeReg, Prescaler >> 8); /* 先写高字节 */ Write_Reg(TPrescalerReg, Prescaler & 0xFF); /* 再低字节 高低字节在两个不同寄存器 */ Write_Reg(TReloadMSBReg, TimeReload >> 8); /* 先高字节 */ Write_Reg(TReloadLSBReg, TimeReload & 0xFF); /* 低字节 */ return true; } /********************************************************************************************************* ** Function name: Pcd_ConfigISOType ** Descriptions: 配置ISO14443A/B协议 ** input parameters: type = 0:ISO14443A协议; ** type = 1,ISO14443B协议; ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ bool Pcd_ConfigISOType(uint8_t type) { if(type == 0){ /* 配置为ISO14443_A */ Set_BitMask(ControlReg, 0x10); /* ControlReg 0x0C 设置reader模式 */ Set_BitMask(TxAutoReg, 0x40); /* TxASKReg 0x15 设置100%ASK有效 */ Write_Reg(TxModeReg, 0x00); /* TxModeReg 0x12 设置TX CRC无效,TX FRAMING =TYPE A */ Write_Reg(RxModeReg, 0x00); /* RxModeReg 0x13 设置RX CRC无效,RX FRAMING =TYPE A */ Write_Reg(RxThresholdReg, 0x55); /* 接收译码器阈值 */ Write_Reg(RFCfgReg, 0x48); /* 接收增益 默认值 */ /* 发射功率 */ Write_Reg(GsNOnReg, 0xf8); /* 天线开启时N驱动电导 */ Write_Reg(CWGsPReg, 0x3f); /* 无调制时P驱动的电导 */ /* A卡使用米勒编码100%调制,调制深度不随天线设计变化,所以不需要调整调制深度寄存器 */ } if(type == 1){ /* 配置为ISO14443_B */ Write_Reg(ControlReg, 0x10); Write_Reg(TxAutoReg, 0x00); Write_Reg(TxModeReg, 0x83); /* BIT1~0 = 2'b11:ISO/IEC 14443B */ Write_Reg(RxModeReg, 0x83); /* BIT1~0 = 2'b11:ISO/IEC 14443B */ Write_Reg(RxThresholdReg, 0x55); /* 接收译码器阈值 */ Write_Reg(RFCfgReg, 0x48); /* 接收增益 默认值 */ Write_Reg(TxBitPhaseReg, 0x87); /* 默认值 */ /* B卡使用不归零编码10%调制,调制深度随天线设计变化,所以需要调整调制深度寄存器 */ /* GsNOnReg高位4位和低4位相差越大,调制深度越大(粗调)*/ /* CWGsPReg和ModGsPReg相差越大(主要是ModGsPReg的值越小),调制深度越大(细调) */ Write_Reg(GsNOnReg, 0x83); /* 天线开启时N驱动电导 */ Write_Reg(GsNOffReg, 0x38); /* 天线关闭时N驱动电导 */ Write_Reg(CWGsPReg, 0x30); /* 无调制时P驱动的电导 */ Write_Reg(ModGsPReg, 0x20); /* 调制时P驱动的电导 */ } return true; } /********************************************************************************************************* ** Function name: FM175X_SoftReset ** Descriptions: FM175xx软件复位 ** input parameters: N/A ** output parameters: N/A ** Returned value: true:操作成功 ERROR:操作失败 *********************************************************************************************************/ void FM175X_SoftReset(void) { Write_Reg(CommandReg, SoftReset); Delay_Ms(1); /* FM175XX芯片复位需要1ms */ Set_BitMask(ControlReg, 0x10); /* FM175xx作为NFC通讯协议的发起端 */ } /********************************************* 函数名: FM175X_SoftPowerdown 功能: 软件低功耗操作 输入参数: 返回值: true,进入低功耗模式; false,退出低功耗模式; ********************************************/ bool FM175X_SoftPowerdown(void) { if(Read_Reg(CommandReg) & 0x10) { Clear_BitMask(CommandReg,0x10);//退出低功耗模式 return false; } else{ Set_BitMask(CommandReg,0x10);//进入低功耗模式 return true; } } /********************************************************************************************************* ** Function name: FM175XX_Initial ** Descriptions: FM175XX 初始化 ** input parameters: N/A ** output parameters: N/A ** Returned value: NONE *********************************************************************************************************/ void FM175XX_Initial(void) { uint8_t regdata,res; regdata = 0x20; //WaterLevel,收到一半数据时候,起中断 SetReg(WaterLevelReg, regdata); } /****************************************************************************** * EOF (not truncated) ******************************************************************************/