返回列表 发新帖我要提问本帖赏金: 100.00元(功能说明)

[蓝牙芯片] 【CH585M测评】NFC阅读器初体验

[复制链接]
3183|0
 楼主| yangjiaxu 发表于 2025-1-14 23:41 | 显示全部楼层 |阅读模式
最近收到了沁恒的CH585M开发板,其实我对这个开发板是非常期待的,本身我就是做射频方面的应用,看到沁恒有这款MCU+NFC的方案我是非常愿意尝试一下的,这不就心随人愿,有幸的申请到了开发板嘛,接下来我们就来看看这个开发板。
01eb9c3354718b6767bf5495b16ba694
图1 CH585M开发板
通过图1可以看出,开发板确实十分的简洁,板载一个MCU,该MCU支持蓝牙与NFC,所以有2个天线,但是布局很有考究,两个天线方向和距离都很远,所以干扰的情况会大大降低;接下来是板载两个USB接口,用的是Type-c接口,这两个分别是HS和FS,FS是可以做USB烧录口来使用;接下来是板载两个按键,一个是复位按键一个是boot按键,也就是烧录时候会用到,下来就是一些必备的阻容件和晶振等等元件了。其实可以看出,沁恒很为客户来考虑,就非常少的元器件就可以实现一个核心板的功能,这样不仅仅可以降低成本,也可以减少电路设计时容易出现的错误。
接下来就来玩耍一下NFC吧,其实CH585M是支持NFC模拟卡和读卡器两种功能的,也就是说该芯片十分的强大,本次就来体验一下读卡器的功能吧,利用程序实现读卡功能,利用串口1实现数据的输出,并且添加了一点串**互,利用串口发送命令实现对卡的读取等等;
首先去官网下载好开发资料,然后找到对应的工程,本次利用MifareClassic的工程为模板,来学习读卡器功能。

c9ad7289eb403090b023e257e7b5071a
图2 工程示例
打开工程之后找到主函数,一般阅读程序都是要从主函数来阅读的。根据程序可以看出,驱动NFC功能非常简单,主要是配置一下nfca_pcd_init();具体代码如下:
  1. void nfca_pcd_init(void)
  2. {
  3.     nfca_pcd_config_t cfg;

  4.     /* NFC引脚初始化为模拟输入模式 */
  5.     GPIOB_ModeCfg(GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_16 | GPIO_Pin_17, GPIO_ModeIN_Floating);

  6.     /* 关闭GPIO数字输入功能 */
  7.     R32_PIN_IN_DIS |= ((GPIO_Pin_8 | GPIO_Pin_9) << 16);        /* 关闭GPIOB中GPIO_Pin_8和GPIO_Pin_9的数字输入功能 */
  8.     R16_PIN_CONFIG |= ((GPIO_Pin_16 | GPIO_Pin_17) >> 8);       /* 关闭GPIOB中GPIO_Pin_16和GPIO_Pin_17的数字输入功能 */

  9.     /* CH584F和CH585F内部PA9和PB9短接,需要将PA9也设置为模拟输入并关闭数字功能,M封装注释下面的两句代码,F封装取消注释 */
  10. //    GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeIN_Floating);
  11. //    R32_PIN_IN_DIS |= GPIO_Pin_9;

  12.     cfg.data_buf = gs_nfca_pcd_data_buf;
  13.     cfg.data_buf_size = NFCA_PCD_DATA_BUF_SIZE;

  14.     cfg.send_buf = g_nfca_pcd_send_buf;
  15.     cfg.send_buf_size = NFCA_PCD_MAX_SEND_NUM;

  16.     cfg.recv_buf = g_nfca_pcd_recv_buf;
  17.     cfg.recv_buf_size = NFCA_PCD_MAX_RECV_NUM;

  18.     cfg.parity_buf = g_nfca_pcd_parity_buf;
  19.     cfg.parity_buf_size = NFCA_PCD_MAX_PARITY_NUM;

  20.     /* 将数据区指针传入给NFC库内BUFFER指针 */
  21.     nfca_pcd_lib_init(&cfg);

  22. #if NFCA_PCD_USE_NFC_CTR_PIN
  23.     nfca_pcd_ctr_init();
  24. #endif

  25. }

接下来就是针对天线的低功耗检卡ADC值校准,虽然不知道干啥的,但是照做就对了,至此,NFC部分就初始化成功了,接下来初始化串口,串口的话官方都有提供完整的例子,我就不提了,再接下来就是设想IC读卡器的功能,本来是想用USB和蓝牙实现的,奈何沁恒的蓝牙部分我还不熟悉,所以就先拿串口来模拟实现吧,主要是有数据交互,也就是串口接收到指令,会实现对卡的一些操作,比如读卡的UID,指定卡扇区,读卡里内容,或者增加卡密钥等等,本次就先做个简单的发送指令读取UID吧,代码如下:
  1. int main(void)
  2. {
  3.     UINT16 x;
  4.     uint8_t len;
  5.     uint8_t res;
  6.     char buf[100] = {'\0'};
  7.     PWR_DCDCCfg(ENABLE);
  8.     SetSysClock(CLK_SOURCE_HSE_PLL_62_4MHz);

  9. #ifdef DEBUG
  10.     GPIOA_SetBits(GPIO_Pin_14);
  11.     GPIOPinRemap(ENABLE, RB_PIN_UART0);
  12.     GPIOA_ModeCfg(GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
  13.     UART0_DefInit();
  14. #endif
  15.     /* 配置串口1:先配置IO口模式,再配置串口 */
  16.     GPIOA_SetBits(GPIO_Pin_9);
  17.     GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);      // RXD-配置上拉输入
  18.     GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); // TXD-配置推挽输出,注意先让IO口输出高电平
  19.     UART1_DefInit();

  20.     PRINT("NFCA PCD START\n");

  21.     nfca_pcd_init();

  22.     nfca_pcd_lpcd_calibration();    /* 低功耗检卡ADC值校准,和天线等相关,可在生产时进行检测。 */

  23. //    nfca_pcd_test();

  24. #if 1 // 测试串口发送字符串
  25.     UART1_SendString(TxBuff, sizeof(TxBuff));

  26. #endif

  27.     while(1)
  28.     {
  29.         len = UART1_RecvString(RxBuff);
  30.         if(len)
  31.         {
  32.             switch (RxBuff[0])
  33.             {
  34.             case 1:
  35.                 nfca_pcd_start();
  36.                 mDelaymS(1);   /* 手机等模拟卡设备需要长时间的连续波唤醒其卡功能,普通实体卡 1 ms 即可 */

  37.                 #if NFCA_PCD_USE_NFC_CTR_PIN
  38.                         nfca_pcd_ctr_handle();  /* 对天线信号进行检测,使用NFC CTR引脚控制幅度 */
  39.                 #endif

  40.                         res = PcdRequest(PICC_REQALL);
  41.                         if(res == 0x0004)
  42.                         {
  43.                             res = PcdAnticoll(PICC_ANTICOLL1);
  44.                             if (res == PCD_NO_ERROR)
  45.                             {
  46.                                 picc_uid[0] = g_nfca_pcd_recv_buf[0];
  47.                                 picc_uid[1] = g_nfca_pcd_recv_buf[1];
  48.                                 picc_uid[2] = g_nfca_pcd_recv_buf[2];
  49.                                 picc_uid[3] = g_nfca_pcd_recv_buf[3];
  50.                                 PRINTF("uid: %02x %02x %02x %02x\n", picc_uid[0], picc_uid[1], picc_uid[2], picc_uid[3]);
  51.                                 sprintf(buf,"uid: %02x %02x %02x %02x\n", picc_uid[0], picc_uid[1], picc_uid[2], picc_uid[3]);
  52.                                 UART1_SendString(buf, strlen(buf));
  53. //                                res = PcdSelect(PICC_ANTICOLL1, picc_uid);
  54. //                                if (res == PCD_NO_ERROR)
  55. //                                {
  56. //                                    PRINTF("\nselect OK, SAK:%02x\n", g_nfca_pcd_recv_buf[0]);
  57. //                                }
  58.                             }
  59.                         }
  60.                 break;
  61.             case 2:
  62.                 UART1_SendString(RxBuff, len);
  63.                 break;

  64.             }
  65.         }
  66.     }

  67. //    while(1);
  68. }
代码较为简单,就是给MCU发送个01,然后读取卡的UID,并且返回给串口,直接给大家看效果吧。
36796caa3615067023bd0722e3a5c916
图3 测试结果
b2a60ef42f64be56432d779b065fc0d2
图4 用手机读取到的卡的UID与串口返回的一致
可以看出uid是一致的,说明读取的是正确的,总的来说还是比较简单的,主要是一些具体的功能我还没来得及添加,后续会完善的,点评一下CH585M就是这个芯片确实讨喜,这么小的封装,有这这么高端的功能,而且芯片价格还不贵,不过在体验的时候发现射频读卡距离还是有优化的空间的,一般是可以通过调整RF的增益来实现,不知道沁恒是否支持这种功能,还是只能通过优化硬件电路来实现呢,留个悬念吧,不过感觉做IC阅读器确实是个不错的选择,后续再完善完善,随时与大家分享,敬请期待吧~

打赏榜单

21ic小管家 打赏了 100.00 元 2025-05-16
理由:优质评测

您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:嵌入式技术专家
简介:擅长电路设计、物联网产品开发、射频产品开发,喜欢打篮球,技术交流,欢迎各位来聊~

805

主题

3383

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部