NFC_Card小卡片


Logo

简介

自己的小项目,最初的灵感是稚晖君的CyberCard卡片,然后自己想加上一些传感器之类的东西。
于是做出了这么个小东西。也算是第一次开发一个功能比较完整的项目。其中使用到了STM32L051作为主控,外设有SPI屏幕,tp4056锂电池充电芯片,ch340串口芯片,BME680多合一传感器,NFC芯片ST25DV。
能够在屏幕上显示温度、湿度、气压、空气质量指数。还可以把一些数据写入NFC芯片,供有NFC的手机读取。
可以使用锂电池供电,整个板子比较小巧,方便携带。

MCU

芯片外观

由于是用锂电池供电的,还有一定的携带和续航要求,所以要稍微考虑一下低功耗。
板子的主控用的是STM32L051,属于ST的低功耗产品线,主频最大32MHz,有串口,I2C,SPI等外设,管脚数量48pin,LQFP封装,有内置振荡器和时钟源,是一款很不错的入门级产品。
价格大概再8元左右。在小项目中用一下很合适,烧了也不心疼。
除此之外,入门产品线还有G0系列的,如G070,也很适合这种小项目。
ST官方简介

屏幕

用的是中景园的TFT屏幕,SPI协议,驱动芯片ST7735,2.4寸,分辨率240X240。屏幕素质还是不错的。有排线版本和排针版本,理论上排线版本更美观,但是我图方便和好替换,用的是排针版本,直接插到板子上的排母上就好了。价格大概25元左右,我就不放链接了,淘宝上一搜就有。
商品介绍页

BME680多合一传感器

博世公司出的一款能够能够监测温度、湿度、气压、空气质量的多合一传感器芯片。
可以通过SPI或者I2C与单片机进行通信,QFN封装,非常小巧。缺点是价格略贵,淘宝50元出头。若是为了追求降低成本,可以换成分立器件AHT10+SGP30之类的。
传感器的图片

NFC芯片ST25DV

ST公司的一款射频NFC芯片,能够模拟M1卡片,用手机就能完成对芯片的写入,还能用单片机的I2C与之进行通信,完成卡片内容的读写。
ST25DV简介
这里要注意的一点是芯片的板载天线设计,PCB布局的时候要留足足够的空间用来走矩形天线来满足谐振频率的阻抗要求,并且天线的区域不能铺铜,后面会详细提到

tp4056锂电池充电模块

tp4056是一款常用的单节锂电池充电芯片,充电电流可通过一个电阻来设定,最高可达1000ma。外围电路无需MOSFET、检测电阻器或隔离二极管。采用SOP8封装。

八款tp4056锂电池充电电路详解

充电电流与编程电阻之间的关系
20220204011418

适合需要充电状态指示,不需要电池温度监测功能的应用电路
20220204011026

串口芯片CH340N

CH340是一款国产USB总线的转接芯片,实现USB差分信号转TTL串口。
可以加到USB的差分信号口上,这样既一根USB线既能供电又能实现串口通信。

应用电路
CH340N应用电路参考

typeC接口

简介:typeC接口大势所趋,typeC支持的协议多,接口引脚多达24pin(最高支持USB3.0),有些厂家为了降低成本,减少了引脚的个数,所以有16pin(支持USB2.0协议),6pin(仅供电)的阉割版。还有各手机厂家的魔改版本。一般电子产品目前用的最多的还是16pin的。

TYPEC引脚定义图

引脚含义
其中CC引脚是用于typeC双公头电流大小的控制,若是双公头供电,需要接一个5.1K下拉电阻倒地。否则收电端会没有电。

开发过程

绘制原理图

整体原理图

绘制PCB

这块PCB的主要设计难点就在于PCB板载天线的问题,查阅数据手册可以知道,这个NFC芯片天线所需要的电感量是4.6uH,不能超过太多,也不能太少,否则就会导致谐振频率偏移13.56Mhz,导致手机读不出数据。

这个PCB我绘制了两板,第一版由于禁止铺铜区域只放置了顶层没有放置底层(画PCB的时候猪脑过载忘记了),所以导致铺铜的时候板载天线处铺上了底层铜,由于铜层会吸收电磁波的能量,而且第一版的天线电感量经过再次计算也只有2uH左右的水平,达不到设计标准。到手测试后果然无法检测到芯片(╯▔皿▔)╯,第一版的NFC功能无法使用。但是经过测试其他功能还是正常的,于是我打算保留第一版,NFC芯片再打板单独测试一下,如果可以的话再考虑出个完整版。

第一版的PCB

于是我为了验证NFC芯片和天线的可行性,又画了一版,这一次我查阅了ST官方NFC天线的设计手册
NFC设计指南地址
又使用了ST的的电感量计算工具。
网页工具
网页工具截图

设计出了第二块验证板,这一次我就没加上其他的电路,只是为了验证NFC芯片和板载天线是否可行,左侧的是ESP32的封装和屏幕的封装,是我为了验证其他项目里一些东西设计的,画在了一块板子上。
验证板

打样

发给厂家打样,这里推荐一下嘉立创,每个月右2次免费的打样机会,交期也蛮快。
20220809155855

焊接

使用风枪和新买的铁板烧,哐哐哐就焊好了,开测!
20220809163633

代码编写

串口收发测试

老规矩,printf重定向到串口,循环打印提示消息”System Start!”。
然后用电脑打开串口,可以看到一直有数据过来。说明串口芯片工作正常。

NFC芯片测试

将有NFC写入功能的手机靠近线圈,有嗡的一声提示音,手机默认的NFC软件被唤起,说明芯片被成功读取到。

屏幕驱动

移植一下淘宝店家的例程,主要是管脚定义的修改和初始化,以及一些delay函数的处理.
这是我自己整理好的驱动 lcd_driver_st7735下载地址
把.h文件全部加入Inc,把.c文件全部加入Src
在main.c调用这两条就可以了。
LCD_Init();//LCD初始化 LCD_Fill(0,0,LCD_W,LCD_H,WHITE);

精简后的发送SPI

由于店家的驱动是用IO管脚模拟的SPI,速率可能不会太快,所以我把驱动改成了使用硬件SPI的方式,但是一测试,发现竟然比模拟的SPI还要更慢一点。
20220809161353
经过查阅资料,发现是因为HAL库在发送之前要经过很多检查动作,拖慢了速度,这些检查在屏幕驱动等行为上可以被认为是多余的,所以我们可以自己稍微精简一下SPI,能大大提高速度。

/* 把HAL库中的检查精简了的快速发送*/
void SPI_FAST_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData)  
{
  hspi->State       = HAL_SPI_STATE_BUSY_TX;
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pTxBuffPtr  = (uint8_t *)pData;
  hspi->TxXferSize  = 1;
  hspi->TxXferCount = 1;

  SPI_1LINE_TX(hspi);
  __HAL_SPI_ENABLE(hspi);

  *((__IO uint8_t *)&hspi->Instance->DR) = (*hspi->pTxBuffPtr);
  hspi->pTxBuffPtr += sizeof(uint8_t);
  hspi->TxXferCount--;

  hspi->State = HAL_SPI_STATE_READY;
}

/******************************************************************************
      函数说明:LCD串行数据写入函数
      入口数据:dat  要写入的串行数据
      返回值:  无
******************************************************************************/


void LCD_Writ_Bus(u8 dat) 
{ 
 #ifdef SoftSPI
 u8 i;
 LCD_CS_Clr();
 for(i=0;i<8;i++)      // 软件模拟SPI
 {     
  LCD_SCLK_Clr();
  if(dat&0x80)
  {
     LCD_MOSI_Set();
  }
  else
  {
     LCD_MOSI_Clr();
  }
  LCD_SCLK_Set();
  dat<<=1;
 } 
  LCD_CS_Set(); 

 #else
 LCD_CS_Clr();
// HAL_SPI_Transmit(&hspi1, &dat, 1, 0x1);   // 硬件SPI发送
 SPI_FAST_Transmit(&hspi1, &dat);       // 硬件SPI快速发送
 LCD_CS_Set();

 #endif
}

传感器驱动

官方驱动Github地址
按照官方教程移植就好,但是在重定向官方给的I2C驱动接口时,要注意把地址左移一位(这是由于STM32的硬件I2C地址是8位的,而一般的器件的地址线都是7位)。
这让我不禁想起了移植RDA5820驱动的时候,软件模拟I2C的多字节读取,要在非最后一个字节的时候发ACK信号,在最后一个字节的时候发NACK信号。当年差点被这个坑了,总的来说,I2C协议还是有其麻烦之处的,虽然它支持多主多从,带来的代价就是需要上拉电阻和比较麻烦的设备地址和寄存器地址的设计。以及一些恶劣信号环境下时序波形的劣化导致的无法正常通信。

void user_delay_ms(uint32_t period)
{
  HAL_Delay(period);
}

int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
    int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
  rslt = HAL_I2C_Mem_Read(&hi2c1, dev_id << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, reg_data, len, 0xff);
    return rslt;
}

int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
    int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
  rslt = HAL_I2C_Mem_Write(&hi2c1, dev_id << 1 , reg_addr, I2C_MEMADD_SIZE_8BIT, reg_data, len, 0xff);
    return rslt;
}

NFC驱动

参考这个网站 IOT小分队
比较麻烦的一点是,要自己写一个安卓APP,来完成对ST25DV芯片的写入,因为市面上一般的NFC软件是不支持ST芯片的,只支持普通的M1卡。而我的安卓开发知识基本忘完了,需要一段时间重新捡起来。
不过也有例外,我找到了一款软件,能完成对ST25DV芯片的简单写入,于是我用安卓手机将网页信息写入了芯片,用另一部手机靠近,弹出了网页信息。
测试NFC标签

实物图

用STLink下载调试
调试

加上锂电池
电池粘在了背面

侧视图
蓝色的是供电按钮


文章作者: Allen Hong
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Allen Hong !
  目录