尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用ZigBee CC253X构建无线考勤机:硬件、协议栈与固件设计详解

用ZigBee CC253X构建无线考勤机:硬件、协议栈与固件设计详解 简介基于ZStack协议栈的ZigBee CC2530/CC2531无线IC卡考勤机完整项目资料适合嵌入式开发者和物联网学习者开展实战训练。资料覆盖CC253X系列单片机包含从硬件接口、ZStack网络配置到RFID刷卡逻辑、安全传输与低功耗管理的完整实现思路。压缩包共313个文件以C语言源码和头文件为主含148个h、122个c文件另有库文件、链接脚本、工程配置及调试脚本整体大小6.51MB便于直接导入IAR工程进行编译与烧录。目前已有160人学习下载。项目中涉及ZStack协议栈的ZDO设备对象、ZCL通用集群、OTA升级、密钥建立等关键模块结合示例可用于理解ZigBee设备入网、数据上报和远程维护机制对希望掌握无线传感网络产品开发、快速搭建考勤或门禁原型的工程师是一份结构清晰、可参考性强的实际工程样例。1. 用 ZigBee CC253X 做无线考勤机先想清楚链路再谈刷卡把 CC2530 或 CC2531 做成无线 IC 卡考勤机卡位很多但不是刷卡难。刷卡只是 13.56MHz 读卡模块把 UID 吐到串口真正的工程量在 ZigBee 那一侧节点怎么上报、协调器怎么收、掉线怎么重连。这套方案基于 TI 的 ZStack跑的是 IEEE 802.15.4 协议2.4GHz 频段和 WiFi、蓝牙挤在一起现场干扰和丢帧才是考勤数据对不上的根源。标题里写的 CC253X 是整条产品线CC2530 当考勤节点CC2531 多了 USB 控制器适合当协调器或抓包器。下文按做这类设备最常见的路径走先定硬件最小系统和读卡接口再在 ZStack 工程里跑通第一帧给出一套带 ACK 重传的固件状态机最后专门讲仿真器驱动安装和抓包验证。新手能照着把工程立起来熟手重点看状态机设计和现场排错那两节。2. 硬件从新大陆 zigbee 模块原理图起步CC2530 最小系统与读卡接口很多人第一步就踩坑CC2530 焊在洞洞板上读卡模块也通了串口能打印卡号但 ZigBee 帧就是发不出去。原因基本都在射频前端和供电上。CC2530 是 8051 内核加上片内 2.4GHz 收发器模拟链路对电源和天线匹配都很敏感最小系统缺一个元件都可能让发射功率掉到没法用的程度。2.1 CC253X 选型CC2530 当节点CC2531 当协调器CC2530 和 CC2531 的射频内核、协议栈支持完全一致区别只在 USB 外设。做考勤机时我一般按下面的分工选芯片内核Flash/RAM特色外设考勤机里的角色CC2530F2568051256KB / 8KB双 USART、8 路 ADC考勤节点接读卡模块CC2531F2568051256KB / 8KBUSB 2.0 全速控制器协调器USB 直连上位机CC2530F32805132KB / 8KB同上Flash 小只跑简单应用时的低成本节点同理CC2531 刷上 TI 的抓包固件就是协议分析器现场排查 ZigBee 丢帧特别方便这一点最后一章细说。注意 CC2531 的引脚复用比 CC2530 紧张如果协调器还要同时接读卡模块和显示优先考虑 CC2530 加 USB 转串口芯片的方案不要硬上 CC2531。提示:ZStack 工程里 CoordinatorEB、RouterEB、EndDeviceEB 三个 workspace 的源码是同一套烧录器和协调器用的是不同编译配置选型时只要确定 Flash 容量不低于 256KB。2.2 参考公共原理图搭最小系统晶振、复位、RF 前端三者缺一不可公开渠道能查到的“新大陆 zigbee 模块原理图”这类资料主线基本都是 TI 官方 CC2530 参考设计32MHz 主晶振加 32.768kHz 睡眠晶振、AVDD 和 DVDD 分开供电滤波、RF_P/RF_N 差分对经过 balun 转成单端接天线。抄这类原理图时不要只抄芯片外围注意三处第一32MHz 晶振的负载电容必须按晶体手册选常见取 27pF 到 33pF焊错容值会导致 ZigBee 协议栈起振失败。第二睡眠晶振不能省ZStack 的 OSAL 定时器和网络定时依赖它只留 32MHz 的话休眠唤醒后时钟会漂考勤时间戳就对不上。第三RF 前端 balun 的元件值和布局严格按参考设计来陶瓷天线下方要避开铺铜和走线。我见过把 balun 电路 0402 电容换成 0603 后发射距离从 80 米掉到 10 米的例子。供电上读卡模块瞬间电流能到上百毫安射频发送时也有 29mA 左右的脉冲电流两者最好分两路 LDO 供电输出端并 1uF 加 10nF 陶瓷电容避免刷卡瞬间把 VDD 拉低导致 802.15.4 帧 CRC 错误。2.3 读卡接口选 UART 直出 UID 的 13.56MHz 模块最省事IC 卡考勤机用的是 13.56MHz 的 ISO14443A 协议常见做法有两种一种直接用 RC522 这类读卡芯片自己发命令读卡另一种用一体式模块模块上电后就自动检测卡片卡号通过串口吐出来。做考勤机我首选后者省去在 CC2530 里写 RC522 时序的功夫只需要做好串口解析。模块接法很简单模块的 TX 接 CC2530 的 RX模块的 RX 接 CC2530 的 TX电平确认是 3.3V TTL共地不能少。CC2530 的串口初始化放在 ZStack 的 HAL 层代码是这样的halUARTCfg_t uartConfig; uartConfig.configured TRUE; uartConfig.baudRate HAL_UART_BR_9600; // 读卡模块常见 9600 uartConfig.flowControl FALSE; uartConfig.flowControlThreshold 8; uartConfig.rx.maxBufSize 64; // 接收缓冲卡号一帧足够 uartConfig.tx.maxBufSize 16; uartConfig.idleTimeout 6; // 空闲 6 个字符时间后回调 uartConfig.callBackFunc rfidUartRxCb; // 收到数据后进回调 HalUARTOpen(HAL_UART_PORT_0, uartConfig);这段配置里有几个参数值得注意。baudRate 一定先查模块手册很多 125kHz 模块是 960013.56MHz 模块有 9600 也有 19200。idleTimeout 设为 6意味着串口空闲超过 6 个字符时间就触发一次回调卡号的 ASCII 字符串是一气呵成发完的回调里就能按一帧处理。maxBufSize 给到 64 字节算上模块上线时主动上报的厂商信息也够用。最后串口回调里千万不要做耗时处理只把数据拷贝进自己的环形缓冲然后置一个 OSAL 事件解析放到任务循环里做。还有一部分读卡模块输出的不是串口而是 Wiegand 26/34 格式D0、D1 两根线各接一个带中断的 GPIO。Wiegand 协议里 D0 拉低表示 0D1 拉低表示 1每一位脉冲约 50 微秒需要用定时器做 25ms 无脉冲超时判断一帧结束。这个我一般放在第四章的固件里讲接口选择上只要记住能走 UART 就走 UARTWiegand 解码占用的中断资源和定时器在 ZStack 里跟协议栈定时器有冲突风险不是必须就别选。3. ZStack 工程里跑通第一帧端点、簇、AF_DataRequest 与回调ZStack 和裸机程序最大的区别不是多了一堆 API而是整个程序跑在 OSAL 任务调度器上。协议栈的 MAC、NWK、APS 各层都是一个个任务你的考勤应用也要注册成任务收到刷卡事件后通过 AF 层接口把数据交给协议栈剩下的路由、重发、组网都由 ZStack 接管。3.1 从工程目录看懂 ZStack 的分层和任务模型ZStack-CC2530 工程解压后Projects 目录下按芯片平台堆放进入后能看到 CoordinatorEB、RouterEB、EndDeviceEB 三个 IAR workspace打开哪个决定编译出来的固件角色。源码里 zstack 目录下 MAC、NWK、APS、ZDO 各层分得清清楚楚应用层在 App 目录硬件驱动在 HAL 目录。应用任务注册有固定套路在 OSAL 的 tasksArr 数组里加一个任务处理函数比如 attendance_event_loop它接收 task_id 和 event 两个参数用 switch 处理自己定义的事件位。OSAL 每轮循环把 tasksEvents 里置位的任务找出来调度所以刷卡、串口数据、定时器超时这些事件都要通过 osal_set_event 或 osal_start_timerEx 转成任务事件不能直接在中断里调用协议栈 API。注意:在串口中断回调里直接调 AF_DataRequest 发送数据是很多第一次用 ZStack 的人必踩的坑。协议栈不是中断安全的必须先置事件回到任务上下文再发。3.2 端点、簇和绑定ZigBee 协议里的三张连接表ZigBee 协议和应用层打交道靠的是端点和簇。一个端点是设备上的一个应用实例考勤机用一个端点比如 8协调器也用同一个端点号。簇 ID 表示这个端点提供什么服务我一般自定义两个簇0xCC01 用来上报考勤记录0xCC02 用来回 ACK。绑定解决的是“发给谁”的问题。协调器和考勤机都声明自己的 SimpleDescriptor协调器发起 Match_Desc_req 找到同簇的考勤机端点之后考勤机发送时用 afAddrNotPresent 地址模式协议栈自动查绑定表把帧发到绑定对象。绑定表维护在协调器侧考勤机多了以后每台机器只和协调器单向绑定现场不用手工填 16 位短地址这是最稳的工程做法。3.3 最小发送代码AF_DataRequest 的八个参数在 ZStack 里发一帧应用数据入口是 AF_DataRequest。下面这段是考勤机上报卡号的核心函数static uint8 cardSeq 0; static void attendanceSendReport(uint8 *payload, uint8 len) { afAddrType_t dstAddr; dstAddr.addrMode (afAddrMode_t)afAddrNotPresent; // 走绑定表不指定短地址 dstAddr.endPoint ATTEND_ENDPOINT; // 目标端点 8 afStatus_t st AF_DataRequest( dstAddr, // 目标地址结构体 attendanceEndPointDesc, // 本端点的 SimpleDescriptor ATTEND_CLUSTER_REPORT, // 簇 ID 0xCC01 len, // 载荷长度 payload, // 载荷指针帧头卡号序号 cardSeq, // 事务序号协议栈回填并随帧发出 AF_ACK_REQUEST, // 请求 MAC/APS 确认 AF_DEFAULT_RADIUS // 广播半径单播时用默认值 ); cardSeq; // 每次发送自增对端据此去重 if (st ! afStatus_SUCCESS) { // 失败原因一般是不在绑定表或网络未就绪 } }参数逐个说addrMode 用 afAddrNotPresent 而不是 afAddr16Bit是因为绑定表里存了协调器的短地址由协议栈解析端点和簇 ID 必须和协调器一致否则对端应用收不到抓包却能看到帧这是最常见的“发了没反应”原因。cardSeq 是事务序号随帧带过去协调器回 ACK 时把同样的序号送回考勤机配合第四章的 ACK 重传。AF_ACK_REQUEST 只是让协议栈做链路层确认不保证应用层处理成功所以还要自己做应用层 ACK。接收侧在任务处理函数里解析 afIncomingMSGPacket_tstatic void attendanceProcessIncoming(afIncomingMSGPacket_t *pkt) { if (pkt-clusterId ATTEND_CLUSTER_ACK) { uint8 *p pkt-cmd.Data; if (p[0] 0xA1 p[1] cardSeq) { osal_stop_timerEx(attendanceTaskId, EVT_ACK_TIMEOUT); attendanceState ST_IDLE; // ACK 序号对上刷卡流程结束 } } }回 ACK 的帧也要走同一条绑定链路这样考勤机不用维护协调器地址只要判断簇 ID 和载荷前两字节。注意 pkt-cmd.Data 的长度上限是 APS 层最大载荷超过 100 字节的考勤记录要分帧实际场景里一卡一帧足够不要在这里做批量上传。4. 考勤机固件状态机卡号解析、ACK 重传与掉线重连考勤机看着简单但刷卡是随机事件无线链路会丢帧协调器可能重启所以固件必须是一个能自恢复的有限状态机而不是“收到卡号就发”的顺序程序。下面这套状态机我沿用了好几个项目核心是用应用层 ACK 配合超时重传把丢帧率控制在千分之一以内。4.1 从串口到卡号环形缓冲与 Wiegand 解码两条路径串口回调收到的是字节流先放进环形缓冲再在任务循环里按帧解析。13.56MHz 一体模块通常输出 8 字节 ASCII 卡号加回车换行解析逻辑就是找起始符、凑满长度、校验回车。解析成功后置 EVT_CARD_READ 事件同时把卡号拷进全局缓冲区防止发送期间被下一次刷卡覆盖。如果用了 Wiegand 模块解码要在 GPIO 中断里做思路是按位收25ms 超时收尾__interrupt void P1_ISR(void) { if (P1IFG BV(0)) wiegandValue (wiegandValue 1) | 0; // D0 拉低 0 if (P1IFG BV(1)) wiegandValue (wiegandValue 1) | 1; // D1 拉低 1 wiegandBits; P1IFG 0; P1IF 0; osal_start_timerEx(wiegandTaskId, EVT_WIEGAND_TIMEOUT, 25); }Wiegand 一帧 26 位首尾是奇偶校验位中间 24 位才是卡号。收到EVT_WIEGAND_TIMEOUT事件后取出中间 24 位即为卡号但需要把 P1 中断优先级和 T1 的定时器正确配置避免和 ZStack 的 MAC 定时器抢占冲突。4.2 状态定义与转移从刷卡到 ACK 是一个完整事务一个完整的刷卡事务包含四态外加一个离线态状态进入条件主要动作超时去向ST_IDLE初始化或收到 ACK等待刷卡中断无ST_WAIT_ACK卡号就绪并已发送启动 300ms 定时器重发重发次数加 1ST_RETRYACK 超时且重发次数小于 3按 300/600/1200ms 退避重发3 次无 ACK 进 ST_OFFLINEST_OFFLINE重发耗尽停止发送继续判卡缓存记录收到心跳 ACK 后回 ST_IDLE状态机的事件有四个EVT_CARD_READ、EVT_ACK_OK、EVT_ACK_TIMEOUT、EVT_NET_LOST。核心循环这样写static uint8 attendanceTaskRun(uint8 event) { if (event EVT_CARD_READ) { if (attendanceState ST_IDLE || attendanceState ST_OFFLINE) { attendanceBuildFrame(cardNoBuf, sendBuf); attendanceSendReport(sendBuf, sendLen); attendanceState ST_WAIT_ACK; retryCount 0; osal_start_timerEx(taskId, EVT_ACK_TIMEOUT, 300); } } if (event EVT_ACK_OK) { osal_stop_timerEx(taskId, EVT_ACK_TIMEOUT); attendanceState ST_IDLE; // 事务成功回到待刷卡 } if (event EVT_ACK_TIMEOUT) { if (retryCount MAX_RETRY) { attendanceSendReport(sendBuf, sendLen); osal_start_timerEx(taskId, EVT_ACK_TIMEOUT, 300 retryCount); } else { attendanceState ST_OFFLINE; // 挽救失败进入离线缓存 } } return events; }退避时间用300 retryCount重发间隔 300/600/1200ms这是 802.15.4 信道冲突后一个比较平缓的节奏不会把协调器收帧队列打爆。每次重发前从 sendBuf 重新发注意 cardSeq 在重发时不能再自增否则对端去重逻辑就失效了。4.3 离线缓存与掉线自恢复考勤机最怕的是无线断了还傻等用户连续刷卡全丢。进 ST_OFFLINE 后不再发无线帧卡号按“时间戳卡号”拼成一条记录写进外部 SPI Flash 或 AT24C16 这类 EEPROM每台机器按最大 1000 条记录封顶满了覆盖最老的。CC2530 片内没有 EEPROM但 ZStack 的 osal_nv 可以用内部 Flash 页存小量参数存考勤记录不够用外挂存储是常见做法。掉线检测用应用层心跳比用协议栈状态更直观考勤机每 60 秒发一帧 0xF0 心跳协调器回 0xA1 帧号连续三次心跳无 ACK 就主动切 ST_OFFLINE。重新上线靠 ZStack 自身的重连机制网络恢复后绑定关系还在心跳 ACK 回来了就把状态拉回 ST_IDLE同时把缓存记录按序补传补传帧头部带缓存序号协调器按序落库。4.4 工程里必须锁死的一组参数参数推荐值说明信道 DZDEFAULT_CHANLIST0x00000800信道 11避开 WiFi 拥挤的 1/6/11 信道PAN ID ZDAPP_CONFIG_PAN_ID固定如 0x2233防止现场多个考勤系统串网串口波特率9600与读卡模块一致应用 ACK 超时300ms小于 ZigBee APS 重试窗口最大重发次数3超过即离线心跳周期60s协调器据此判断节点在线缓存容量1000 条按 16 字节每条约 16KB Flash信道选择这里单独提醒2.4GHz 的 ZigBee 信道 11 到 26现场如果有 WiFi 覆盖优先做一次信道扫描选和 WiFi AP 中心频点错开至少 20MHz 的信道。固定 PAN ID 的作用是隔离现场可能存在的中继器或调试节点烧录前在出厂配置里写死。5. zigbee 仿真器驱动安装、CC2531 抓包与现场三项验证ZStack 工程能编译只是第一步烧录和验证反而最卡人。这一章把 zigbee 仿真器驱动安装和 CC2531 抓包这两件必做的事讲透最后给一套现场验收的动作。5.1 zigbee 仿真器驱动安装Win10/11 下超六成问题出在签名CC Debugger 或 SmartRF04EB 插到 Windows 10/11 后设备管理器里经常出现带感叹号的未知设备这不是仿真器坏了是驱动没有成功加载。老烧录软件自带的驱动没有微软签名新系统默认拒绝安装。常见做法是先在设备管理器里手动更新驱动指向 SmartRF Flash Programmer 安装目录下的 Driver 文件夹如果系统仍然拒绝需要临时关闭驱动签名强制重启一次装完再恢复。安装完成后设备管理器里应出现 TI CC Debugger 或对应的仿真器节点SmartRF Flash Programmer 能识别到芯片型号才是真的通了。注意:烧录考勤机固件用 SmartRF Flash Programmer在线调试用 IAR EW8051两套工具不能混用。IAR 连不上仿真器时先确认仿真器固件版本用 SmartRF Flash Programmer 给仿真器本身升级一次。5.2 用 CC2531 把 ZigBee 无线帧变成可读日志CC2531 USB 板刷入 Packet Sniffer 固件后插电脑就能把空中抓到的 802.15.4 帧按协议栈解出来。打开 TI Packet Sniffer选择 CC2531 USB设置要监听的信道注意这个信道必须和考勤机编译进固件的信道一致否则一帧都抓不到。抓包界面上能看到三样关键信息关联请求和关联响应帧、APS Data 帧的载荷以及每一帧的 RSSI 和 LQI 值。现场排查时先让考勤机发一帧看抓包里载荷前两字节是不是 0xAA 帧头和卡号 ASCII。如果抓包有帧但协调器上位机没数据问题在协调器的串口或者上位机解析不在无线链路如果抓包都看不到帧问题在节点侧重点查绑定表是否丢失。5.3 现场验收三项验证一个技巧第一项单机自检烧录完考勤机先不组网串口接电脑刷 100 次卡片确认卡号解析无错码这一步把读卡链路和无线链路彻底隔离。第二项组网验证协调器上电后观察考勤机的短地址是否分配成功ZStack 里可以定时打印 mac 层的关联状态。第三项整链路测试连续刷 200 次卡协调器上位机比对收到的卡号和次数。压箱底的一个技巧是把应用层 ACK 设计成“回显请求帧的帧序号加 CRC8”抓包时用 Packet Sniffer 的过滤功能只保留 0xCC02 这个 ACK 簇然后直接数时序图上同一帧序号的请求和回显对。丢包率按“发出的帧序号数量减去 ACK 回显数量再除以发出数”计算连续测 100 次刷卡这个数低于 1‰ 再放行进场。本文还有配套的精品资源点击获取
返回列表