最近收到了沁恒的CH585M开发板,其实我对这个开发板是非常期待的,本身我就是做射频方面的应用,看到沁恒有这款MCU+NFC的方案我是非常愿意尝试一下的,这不就心随人愿,有幸的申请到了开发板嘛,接下来我们就来看看这个开发板。
图1 CH585M开发板 通过图1可以看出,开发板确实十分的简洁,板载一个MCU,该MCU支持蓝牙与NFC,所以有2个天线,但是布局很有考究,两个天线方向和距离都很远,所以干扰的情况会大大降低;接下来是板载两个USB接口,用的是Type-c接口,这两个分别是HS和FS,FS是可以做USB烧录口来使用;接下来是板载两个按键,一个是复位按键一个是boot按键,也就是烧录时候会用到,下来就是一些必备的阻容件和晶振等等元件了。其实可以看出,沁恒很为客户来考虑,就非常少的元器件就可以实现一个核心板的功能,这样不仅仅可以降低成本,也可以减少电路设计时容易出现的错误。
接下来就来玩耍一下NFC吧,其实CH585M是支持NFC模拟卡和读卡器两种功能的,也就是说该芯片十分的强大,本次就来体验一下读卡器的功能吧,利用程序实现读卡功能,利用串口1实现数据的输出,并且添加了一点串**互,利用串口发送命令实现对卡的读取等等;首先去官网下载好开发资料,然后找到对应的工程,本次利用MifareClassic的工程为模板,来学习读卡器功能。
图2 工程示例 打开工程之后找到主函数,一般阅读程序都是要从主函数来阅读的。根据程序可以看出,驱动NFC功能非常简单,主要是配置一下nfca_pcd_init();具体代码如下:
void nfca_pcd_init(void)
{
nfca_pcd_config_t cfg;
/* NFC引脚初始化为模拟输入模式 */
GPIOB_ModeCfg(GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_16 | GPIO_Pin_17, GPIO_ModeIN_Floating);
/* 关闭GPIO数字输入功能 */
R32_PIN_IN_DIS |= ((GPIO_Pin_8 | GPIO_Pin_9) << 16); /* 关闭GPIOB中GPIO_Pin_8和GPIO_Pin_9的数字输入功能 */
R16_PIN_CONFIG |= ((GPIO_Pin_16 | GPIO_Pin_17) >> 8); /* 关闭GPIOB中GPIO_Pin_16和GPIO_Pin_17的数字输入功能 */
/* CH584F和CH585F内部PA9和PB9短接,需要将PA9也设置为模拟输入并关闭数字功能,M封装注释下面的两句代码,F封装取消注释 */
// GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeIN_Floating);
// R32_PIN_IN_DIS |= GPIO_Pin_9;
cfg.data_buf = gs_nfca_pcd_data_buf;
cfg.data_buf_size = NFCA_PCD_DATA_BUF_SIZE;
cfg.send_buf = g_nfca_pcd_send_buf;
cfg.send_buf_size = NFCA_PCD_MAX_SEND_NUM;
cfg.recv_buf = g_nfca_pcd_recv_buf;
cfg.recv_buf_size = NFCA_PCD_MAX_RECV_NUM;
cfg.parity_buf = g_nfca_pcd_parity_buf;
cfg.parity_buf_size = NFCA_PCD_MAX_PARITY_NUM;
/* 将数据区指针传入给NFC库内BUFFER指针 */
nfca_pcd_lib_init(&cfg);
#if NFCA_PCD_USE_NFC_CTR_PIN
nfca_pcd_ctr_init();
#endif
}
接下来就是针对天线的低功耗检卡ADC值校准,虽然不知道干啥的,但是照做就对了,至此,NFC部分就初始化成功了,接下来初始化串口,串口的话官方都有提供完整的例子,我就不提了,再接下来就是设想IC读卡器的功能,本来是想用USB和蓝牙实现的,奈何沁恒的蓝牙部分我还不熟悉,所以就先拿串口来模拟实现吧,主要是有数据交互,也就是串口接收到指令,会实现对卡的一些操作,比如读卡的UID,指定卡扇区,读卡里内容,或者增加卡密钥等等,本次就先做个简单的发送指令读取UID吧,代码如下:
int main(void)
{
UINT16 x;
uint8_t len;
uint8_t res;
char buf[100] = {'\0'};
PWR_DCDCCfg(ENABLE);
SetSysClock(CLK_SOURCE_HSE_PLL_62_4MHz);
#ifdef DEBUG
GPIOA_SetBits(GPIO_Pin_14);
GPIOPinRemap(ENABLE, RB_PIN_UART0);
GPIOA_ModeCfg(GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
UART0_DefInit();
#endif
/* 配置串口1:先配置IO口模式,再配置串口 */
GPIOA_SetBits(GPIO_Pin_9);
GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU); // RXD-配置上拉输入
GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); // TXD-配置推挽输出,注意先让IO口输出高电平
UART1_DefInit();
PRINT("NFCA PCD START\n");
nfca_pcd_init();
nfca_pcd_lpcd_calibration(); /* 低功耗检卡ADC值校准,和天线等相关,可在生产时进行检测。 */
// nfca_pcd_test();
#if 1 // 测试串口发送字符串
UART1_SendString(TxBuff, sizeof(TxBuff));
#endif
while(1)
{
len = UART1_RecvString(RxBuff);
if(len)
{
switch (RxBuff[0])
{
case 1:
nfca_pcd_start();
mDelaymS(1); /* 手机等模拟卡设备需要长时间的连续波唤醒其卡功能,普通实体卡 1 ms 即可 */
#if NFCA_PCD_USE_NFC_CTR_PIN
nfca_pcd_ctr_handle(); /* 对天线信号进行检测,使用NFC CTR引脚控制幅度 */
#endif
res = PcdRequest(PICC_REQALL);
if(res == 0x0004)
{
res = PcdAnticoll(PICC_ANTICOLL1);
if (res == PCD_NO_ERROR)
{
picc_uid[0] = g_nfca_pcd_recv_buf[0];
picc_uid[1] = g_nfca_pcd_recv_buf[1];
picc_uid[2] = g_nfca_pcd_recv_buf[2];
picc_uid[3] = g_nfca_pcd_recv_buf[3];
PRINTF("uid: %02x %02x %02x %02x\n", picc_uid[0], picc_uid[1], picc_uid[2], picc_uid[3]);
sprintf(buf,"uid: %02x %02x %02x %02x\n", picc_uid[0], picc_uid[1], picc_uid[2], picc_uid[3]);
UART1_SendString(buf, strlen(buf));
// res = PcdSelect(PICC_ANTICOLL1, picc_uid);
// if (res == PCD_NO_ERROR)
// {
// PRINTF("\nselect OK, SAK:%02x\n", g_nfca_pcd_recv_buf[0]);
// }
}
}
break;
case 2:
UART1_SendString(RxBuff, len);
break;
}
}
}
// while(1);
}
代码较为简单,就是给MCU发送个01,然后读取卡的UID,并且返回给串口,直接给大家看效果吧。
图3 测试结果 图4 用手机读取到的卡的UID与串口返回的一致 可以看出uid是一致的,说明读取的是正确的,总的来说还是比较简单的,主要是一些具体的功能我还没来得及添加,后续会完善的,点评一下CH585M就是这个芯片确实讨喜,这么小的封装,有这这么高端的功能,而且芯片价格还不贵,不过在体验的时候发现射频读卡距离还是有优化的空间的,一般是可以通过调整RF的增益来实现,不知道沁恒是否支持这种功能,还是只能通过优化硬件电路来实现呢,留个悬念吧,不过感觉做IC阅读器确实是个不错的选择,后续再完善完善,随时与大家分享,敬请期待吧~
|