CC1101 Cap
Cap CC1101 是一款扩展 Cap,集成了 CC1101 Sub-GHz 射频收发器和 ST25R3916 NFC 读卡器。
MicroPython API 按功能拆分:
CC1101Cap用于 Sub-GHz 发送和接收。NFCCap用于 NFC 卡片检测和读写操作。
支持以下产品:
频率范围
CC1101Cap 支持以下实测频率范围:
范围 |
频段 |
|---|---|
|
315MHz 频段 |
|
433MHz 频段 |
|
868MHz 频段 |
当 freq_khz 改变时,会自动更新 RF switch。
UiFlow2 应用示例
CC1101 RF 发送
在 UiFlow2 中打开 cc1101_cap_rf_tx_example.m5f2 项目。
此示例在 868MHz 下每秒发送一次 payload,并显示 SEQ、OK 和 FAIL 计数。
UiFlow2 代码块:
示例输出:
无
CC1101 RF 接收
在 UiFlow2 中打开 cc1101_cap_rf_rx_example.m5f2 项目。
此示例在 868MHz 下接收数据包,并显示 payload、RSSI、LQI 和 CRC 状态。
UiFlow2 代码块:
示例输出:
无
NFC 卡片检测
在 UiFlow2 中打开 cc1101_cap_nfc_read_id_example.m5f2 项目。
此示例扫描 ISO14443A 卡片,并显示 UID、卡片类型和用户区容量。
UiFlow2 代码块:
示例输出:
无
MicroPython 应用示例
CC1101 RF 发送
此示例在 868MHz 下每秒发送一次 payload,并显示发送计数。
MicroPython 代码块:
1# SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD 2# 3# SPDX-License-Identifier: MIT 4 5import os, sys, io 6import M5 7from M5 import * 8from cap import CC1101Cap 9import time 10 11 12label_title = None 13label_status = None 14label_seq = None 15label_ok = None 16label_fail = None 17label_payload = None 18cap_cc1101 = None 19 20 21seq = None 22last_tx_ms = None 23ok_count = None 24payload = None 25fail_count = None 26tx_ok = None 27 28 29def setup(): 30 global \ 31 label_title, \ 32 label_status, \ 33 label_seq, \ 34 label_ok, \ 35 label_fail, \ 36 label_payload, \ 37 cap_cc1101, \ 38 seq, \ 39 last_tx_ms, \ 40 ok_count, \ 41 payload, \ 42 fail_count, \ 43 tx_ok 44 45 M5.begin() 46 Widgets.fillScreen(0x101418) 47 label_title = Widgets.Label( 48 "CC1101 TX", 76, 3, 1.0, 0x22D3A6, 0x101418, Widgets.FONTS.Montserrat18 49 ) 50 label_status = Widgets.Label( 51 "Auto TX every 1s", 5, 28, 1.0, 0x22D3A6, 0x101418, Widgets.FONTS.Montserrat16 52 ) 53 label_seq = Widgets.Label("SEQ: 0", 5, 50, 1.0, 0xEAF2F8, 0x101418, Widgets.FONTS.Montserrat16) 54 label_ok = Widgets.Label("OK: 0", 5, 72, 1.0, 0x22D3A6, 0x101418, Widgets.FONTS.Montserrat16) 55 label_fail = Widgets.Label( 56 "FAIL: 0", 120, 72, 1.0, 0xFF5C5C, 0x101418, Widgets.FONTS.Montserrat16 57 ) 58 label_payload = Widgets.Label( 59 "TX:", 5, 100, 1.0, 0xEAF2F8, 0x101418, Widgets.FONTS.Montserrat18 60 ) 61 62 cap_cc1101 = CC1101Cap(868000, 2.4, 25.4, 58, 10, 64, 0x12, 0xAD) 63 seq = 0 64 ok_count = 0 65 fail_count = 0 66 last_tx_ms = 0 67 Speaker.begin() 68 Speaker.setVolumePercentage(0.5) 69 label_status.setText(str("Auto TX every 1s")) 70 label_seq.setText(str("SEQ: 0")) 71 label_ok.setText(str("OK: 0")) 72 label_fail.setText(str("FAIL: 0")) 73 label_payload.setText(str("TX: ")) 74 Speaker.tone(3600, 40) 75 time.sleep_ms(35) 76 Speaker.tone(4800, 45) 77 78 79def loop(): 80 global \ 81 label_title, \ 82 label_status, \ 83 label_seq, \ 84 label_ok, \ 85 label_fail, \ 86 label_payload, \ 87 cap_cc1101, \ 88 seq, \ 89 last_tx_ms, \ 90 ok_count, \ 91 payload, \ 92 fail_count, \ 93 tx_ok 94 M5.update() 95 if (time.ticks_diff((time.ticks_ms()), last_tx_ms)) >= 1000: 96 last_tx_ms = time.ticks_ms() 97 payload = str((str("CC1101, SEQ=") + str(seq))) + str(", Hello") 98 tx_ok = cap_cc1101.send(payload) 99 if tx_ok: 100 ok_count = (ok_count if isinstance(ok_count, (int, float)) else 0) + 1 101 label_status.setText(str("TX OK")) 102 Speaker.tone(3600, 25) 103 else: 104 fail_count = (fail_count if isinstance(fail_count, (int, float)) else 0) + 1 105 label_status.setText(str("TX failed")) 106 Speaker.tone(900, 100) 107 label_payload.setText(str((str("TX: ") + str(payload)))) 108 seq = (seq if isinstance(seq, (int, float)) else 0) + 1 109 label_seq.setText(str((str("SEQ: ") + str(seq)))) 110 label_ok.setText(str((str("OK: ") + str(ok_count)))) 111 label_fail.setText(str((str("FAIL: ") + str(fail_count)))) 112 113 114if __name__ == "__main__": 115 try: 116 setup() 117 while True: 118 loop() 119 except (Exception, KeyboardInterrupt) as e: 120 try: 121 from utility import print_error_msg 122 123 print_error_msg(e) 124 except ImportError: 125 print("please update to latest firmware")
示例输出:
无
CC1101 RF 接收
此示例在 868MHz 下接收数据包,并显示 payload、RSSI、LQI 和 CRC 状态。
MicroPython 代码块:
1# SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD 2# 3# SPDX-License-Identifier: MIT 4 5import os, sys, io 6import M5 7from M5 import * 8from cap import CC1101Cap 9import time 10 11 12label_title = None 13label_status = None 14label_counts = None 15label_rssi = None 16label_lqi = None 17label_payload = None 18cap_cc1101 = None 19 20 21cc1101_data = None 22rx_count = None 23crc_count = None 24last_rx_ms = None 25last_anim_ms = None 26 27 28def setup(): 29 global \ 30 label_title, \ 31 label_status, \ 32 label_counts, \ 33 label_rssi, \ 34 label_lqi, \ 35 label_payload, \ 36 cap_cc1101, \ 37 cc1101_data, \ 38 rx_count, \ 39 crc_count, \ 40 last_rx_ms, \ 41 last_anim_ms 42 43 M5.begin() 44 Widgets.fillScreen(0x101418) 45 label_title = Widgets.Label( 46 "CC1101 RX", 75, 3, 1.0, 0x22D3A6, 0x101418, Widgets.FONTS.Montserrat18 47 ) 48 label_status = Widgets.Label( 49 "Listening...", 5, 28, 1.0, 0x22D3A6, 0x101418, Widgets.FONTS.Montserrat16 50 ) 51 label_counts = Widgets.Label( 52 "RX:0 CRC:0", 5, 50, 1.0, 0xEAF2F8, 0x101418, Widgets.FONTS.Montserrat16 53 ) 54 label_rssi = Widgets.Label( 55 "RSSI: -", 5, 72, 1.0, 0xEAF2F8, 0x101418, Widgets.FONTS.Montserrat16 56 ) 57 label_lqi = Widgets.Label( 58 "LQI: -", 136, 72, 1.0, 0xEAF2F8, 0x101418, Widgets.FONTS.Montserrat16 59 ) 60 label_payload = Widgets.Label( 61 "RX:", 5, 100, 1.0, 0x22D3A6, 0x101418, Widgets.FONTS.Montserrat18 62 ) 63 64 cap_cc1101 = CC1101Cap(868000, 2.4, 25.4, 58, 10, 64, 0x12, 0xAD) 65 cap_cc1101.start_recv() 66 rx_count = 0 67 crc_count = 0 68 last_rx_ms = time.ticks_ms() 69 last_anim_ms = time.ticks_ms() 70 Speaker.begin() 71 Speaker.setVolumePercentage(0.5) 72 label_status.setText(str("Listening...")) 73 label_counts.setText(str("RX:0 CRC:0")) 74 label_rssi.setText(str("RSSI: -")) 75 label_lqi.setText(str("LQI: -")) 76 label_payload.setText(str("RX: ")) 77 Speaker.tone(3600, 40) 78 time.sleep_ms(35) 79 Speaker.tone(4800, 45) 80 81 82def loop(): 83 global \ 84 label_title, \ 85 label_status, \ 86 label_counts, \ 87 label_rssi, \ 88 label_lqi, \ 89 label_payload, \ 90 cap_cc1101, \ 91 cc1101_data, \ 92 rx_count, \ 93 crc_count, \ 94 last_rx_ms, \ 95 last_anim_ms 96 M5.update() 97 cc1101_data = cap_cc1101.recv(timeout_ms=0) 98 if cc1101_data: 99 if cc1101_data.crc_ok: 100 last_rx_ms = time.ticks_ms() 101 rx_count = (rx_count if isinstance(rx_count, (int, float)) else 0) + 1 102 label_status.setText(str("Packet received")) 103 label_counts.setText( 104 str((str((str("RX:") + str(rx_count))) + str((str(" CRC:") + str(crc_count))))) 105 ) 106 label_rssi.setText(str((str((str("RSSI: ") + str((cc1101_data.rssi)))) + str(" dBm")))) 107 label_lqi.setText(str((str("LQI: ") + str((cc1101_data.lqi))))) 108 label_payload.setText(str((str("RX:") + str(((cc1101_data.data).decode()))))) 109 Speaker.tone(5200, 35) 110 cap_cc1101.start_recv() 111 else: 112 crc_count = (crc_count if isinstance(crc_count, (int, float)) else 0) + 1 113 label_status.setText(str("CRC error")) 114 label_counts.setText( 115 str((str((str("RX:") + str(rx_count))) + str((str(" CRC:") + str(crc_count))))) 116 ) 117 Speaker.tone(900, 100) 118 cap_cc1101.start_recv() 119 else: 120 if (time.ticks_diff((time.ticks_ms()), last_anim_ms)) >= 1000: 121 last_anim_ms = time.ticks_ms() 122 label_status.setText(str("Listening...")) 123 124 125if __name__ == "__main__": 126 try: 127 setup() 128 while True: 129 loop() 130 except (Exception, KeyboardInterrupt) as e: 131 try: 132 from utility import print_error_msg 133 134 print_error_msg(e) 135 except ImportError: 136 print("please update to latest firmware")
示例输出:
无
NFC 卡片检测
此示例扫描 ISO14443A 卡片,并显示 UID、卡片类型和用户区容量。
MicroPython 代码块:
1# SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD 2# 3# SPDX-License-Identifier: MIT 4 5import os, sys, io 6import M5 7from M5 import * 8from cap import NFCCap 9import time 10 11 12label_title = None 13label_status = None 14label_uid = None 15label_type = None 16label_mem = None 17cap_nfc = None 18last_scan_ms = None 19card_0 = None 20last_uid = None 21card_uid = None 22card_type = None 23card_size = None 24 25 26def setup(): 27 global \ 28 label_title, \ 29 label_status, \ 30 label_uid, \ 31 label_type, \ 32 label_mem, \ 33 cap_nfc, \ 34 last_scan_ms, \ 35 card_0, \ 36 last_uid, \ 37 card_uid, \ 38 card_type, \ 39 card_size 40 41 M5.begin() 42 Widgets.fillScreen(0x101418) 43 label_title = Widgets.Label( 44 "NFC card detect", 44, 3, 1.0, 0x22D3A6, 0x101418, Widgets.FONTS.Montserrat18 45 ) 46 label_status = Widgets.Label( 47 "Scanning...", 5, 28, 1.0, 0x22D3A6, 0x101418, Widgets.FONTS.Montserrat14 48 ) 49 label_uid = Widgets.Label("UID: -", 5, 50, 1.0, 0xEAF2F8, 0x101418, Widgets.FONTS.Montserrat14) 50 label_type = Widgets.Label( 51 "Type: -", 5, 72, 1.0, 0xEAF2F8, 0x101418, Widgets.FONTS.Montserrat14 52 ) 53 label_mem = Widgets.Label( 54 "Memory: -", 5, 94, 1.0, 0xEAF2F8, 0x101418, Widgets.FONTS.Montserrat14 55 ) 56 57 Speaker.begin() 58 Speaker.setVolumePercentage(0.6) 59 cap_nfc = NFCCap() 60 last_uid = "" 61 last_scan_ms = time.ticks_ms() 62 label_status.setText(str("Scanning...")) 63 label_uid.setText(str("UID: -")) 64 label_type.setText(str("Type: -")) 65 label_mem.setText(str("Memory: -")) 66 Speaker.tone(3600, 40) 67 time.sleep_ms(35) 68 Speaker.tone(4800, 45) 69 70 71def loop(): 72 global \ 73 label_title, \ 74 label_status, \ 75 label_uid, \ 76 label_type, \ 77 label_mem, \ 78 cap_nfc, \ 79 last_scan_ms, \ 80 card_0, \ 81 last_uid, \ 82 card_uid, \ 83 card_type, \ 84 card_size 85 M5.update() 86 if (time.ticks_diff((time.ticks_ms()), last_scan_ms)) >= 180: 87 last_scan_ms = time.ticks_ms() 88 card_0 = cap_nfc.detect() 89 if card_0: 90 card_uid = card_0.uid_str 91 if card_uid != last_uid: 92 last_uid = card_uid 93 card_type = card_0.type_name 94 card_size = card_0.user_memory 95 label_status.setText(str("Card detected")) 96 label_uid.setText(str((str("UID: ") + str(card_uid)))) 97 label_type.setText(str((str("Type: ") + str(card_type)))) 98 label_mem.setText(str((str((str("Memory: ") + str(card_size))) + str(" bytes")))) 99 Speaker.tone(4200, 45) 100 time.sleep_ms(35) 101 Speaker.tone(5600, 55) 102 cap_nfc.halt() 103 else: 104 last_uid = "" 105 label_status.setText(str("Scanning...")) 106 label_uid.setText(str("UID: -")) 107 label_type.setText(str("Type: -")) 108 label_mem.setText(str("Memory: -")) 109 110 111if __name__ == "__main__": 112 try: 113 setup() 114 while True: 115 loop() 116 except (Exception, KeyboardInterrupt) as e: 117 try: 118 from utility import print_error_msg 119 120 print_error_msg(e) 121 except ImportError: 122 print("please update to latest firmware")
示例输出:
无
API参考
class CC1101Cap
- class cap.cc1101.CC1101Cap(freq_khz=868000, bitrate_kbps=2.4, freq_dev_khz=25.4, rx_bw_khz=58.0, output_power=10, preamble_length=16, sync_word_h=0x12, sync_word_l=0xAD)
创建用于 Sub-GHz 射频通信的 CC1101Cap 对象。
- 参数:
freq_khz (int) – CC1101 射频频率,单位 kHz。有效范围:
315000~348000 kHz、415000~464000 kHz、830000~928000 kHz。bitrate_kbps (float) – 数据速率,单位 kbps,范围 0.6 到 6.0 kbps。
freq_dev_khz (float) – 频偏,单位 kHz,范围 1.6 到 380 kHz。
rx_bw_khz (float) – 接收带宽,单位 kHz,范围 58 到 812 kHz。
output_power (int) – 输出功率,单位 dBm,范围 -30 到 10 dBm。
preamble_length (int) – 前导码长度,单位 bit,可选值:16、24、32、48、64、96、128、192。
sync_word_h (int) – 同步字高字节(0x00 到 0xFF)。
sync_word_l (int) – 同步字低字节(0x00 到 0xFF)。
UiFlow2 代码块:

MicroPython 代码块:
from cap import CC1101Cap cap_cc1101 = CC1101Cap(868000, 2.4, 25.4, 58.0, 10, 64, 0x12, 0xAD)
- set_freq(freq_khz)
设置频率,单位 kHz,并自动更新 Cap RF switch。
- 参数:
freq_khz (int) – 频率,单位 kHz。有效范围:
315000~348000 kHz、415000~464000 kHz、830000~928000 kHz。
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.set_freq(868000)
- set_bitrate(bitrate_kbps)
设置数据速率,单位 kbps。
- 参数:
bitrate_kbps (float) – 数据速率,单位 kbps,范围 0.6 到 6.0。
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.set_bitrate(2.4)
- set_freq_dev(freq_dev_khz)
设置频偏,单位 kHz。
- 参数:
freq_dev_khz (float) – 频偏,单位 kHz,范围 1.6 到 380。
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.set_freq_dev(25.4)
- set_rx_bw(rx_bw_khz)
设置接收带宽,单位 kHz。
- 参数:
rx_bw_khz (float) – 接收带宽,单位 kHz,范围 58 到 812。
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.set_rx_bw(58.0)
- set_output_power(output_power)
设置输出功率,单位 dBm。
- 参数:
output_power (int) – 输出功率,单位 dBm,范围 -30 到 10。
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.set_output_power(10)
- set_preamble_length(preamble_length)
设置前导码长度,单位 bit。
- 参数:
preamble_length (int) – 前导码长度,单位 bit。必须是 16、24、32、48、64、96、128、192 之一。
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.set_preamble_length(64)
- set_sync_word(sync_word_h, sync_word_l)
设置 2 字节同步字。
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.set_sync_word(0x12, 0xAD)
- send(packet)
发送数据。
- 参数:
packet (str | list | tuple | int | bytearray | bytes) – 要发送的数据。
- 返回:
数据包发送成功返回
True,否则返回False。- 返回类型:
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.send("Hello World")
- recv(timeout_ms=None)
接收数据。
- 参数:
timeout_ms (int) – 超时时间,单位 ms。
None表示非阻塞轮询。- 返回:
接收到的数据包实例,或
None。- 返回类型:
CC1101Packet | None
UiFlow2 代码块:

MicroPython 代码块:
packet = cap_cc1101.recv() if packet and packet.crc_ok: print(packet.decode(), packet.rssi, packet.lqi)
- start_recv()
启动接收模式。
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.start_recv()
- set_rx_irq_callback(callback)
设置接收中断回调。
- 参数:
callback – 收到数据包时调用该回调,参数为
CC1101Packet。
UiFlow2 代码块:

MicroPython 代码块:
def on_rx(packet): print(packet.decode()) cap_cc1101.set_rx_irq_callback(on_rx)
- set_tx_irq_callback(callback)
设置发送回调。
- 参数:
callback – 发送完成后调用该回调。在 CC1101Cap 上,GDO2 用于 RF switch 控制,因此该 API 主要用于兼容。
UiFlow2 代码块:

MicroPython 代码块:
def on_tx(_): print("TX done") cap_cc1101.set_tx_irq_callback(on_tx)
- standby()
使 CC1101 进入 standby 模式。
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.standby()
- rx_irq_triggered()
检查 RX IRQ 是否已触发。
- 返回:
RX IRQ 已触发返回
True,否则返回False。- 返回类型:
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.rx_irq_triggered()
- tx_irq_triggered()
检查 TX IRQ 是否已触发。
- 返回:
TX IRQ 已触发返回
True,否则返回False。- 返回类型:
UiFlow2 代码块:

MicroPython 代码块:
cap_cc1101.tx_irq_triggered()
class CC1101Packet
- class driver.cc1101.CC1101Packet
CC1101Cap.recv()和 RX 回调返回的数据包对象。- data
原始数据包数据。
- rssi
接收信号强度,单位 dBm。
- lqi
链路质量指示。
- crc_ok
CRC 结果。
True表示数据包通过 CRC 校验。
- decode()
将数据包数据按 UTF-8 解码为字符串。
- 返回:
解码后的字符串。
- 返回类型:
class NFCCap
- class cap.cc1101.NFCCap
创建用于 Cap CC1101 硬件上 ST25R3916 NFC 读卡器的 NFCCap 对象。
NFCCap 内部以 SPI 模式使用 ST25R3916,应用层不需要传入 I2C 总线或 SPI 对象。
UiFlow2 代码块:

MicroPython 代码块:
from cap import NFCCap nfc = NFCCap()
- detect()
轮询检测 ISO14443A 卡片。
- 返回:
检测到卡片时返回
Card对象,否则返回None。
UiFlow2 代码块:

MicroPython 代码块:
card = nfc.detect() if card: print(card.uid_str, card.type_name, card.user_memory)
- read(card, index, key=FACTORY_KEY)
从检测到的卡片读取一个地址单元。
MIFARE Classic:
index为全局块号,返回值为 16 字节或None。Type 2 / Ultralight / NTAG:
index为页号,返回值为 4 字节或None。
- 参数:
- 返回:
bytes或None。
UiFlow2 代码块:

MicroPython 代码块:
data = nfc.read(card, 4)
- write(card, index, data, key=FACTORY_KEY)
向检测到的卡片写入一个地址单元。
MIFARE Classic:
data必须为 16 字节,index为全局块号。Type 2 / Ultralight / NTAG:
data必须为 4 字节,index为页号。
仅使用可写测试卡。不要写入 UID 页、锁定位、扇区尾块、访问控制块、支付卡、门禁卡或身份卡。
- 参数:
- 返回:
成功返回
True,否则返回False。- 返回类型:
UiFlow2 代码块:

MicroPython 代码块:
ok = nfc.write(card, 4, bytes(16))
- halt()
发送 HLTA,使 Type A 卡片进入 HALT 状态。
UiFlow2 代码块:

MicroPython 代码块:
nfc.halt()
- rf_off()
关闭 NFC RF 场。
UiFlow2 代码块:

MicroPython 代码块:
nfc.rf_off()
- rf_on()
开启 NFC RF 场。
UiFlow2 代码块:

MicroPython 代码块:
nfc.rf_on()
Card 对象
NFCCap.detect() 返回的 Card 对象包含检测到的卡片信息。
UiFlow2 代码块:
属性 / 方法 |
说明 |
|---|---|
|
原始 UID 字节。 |
|
UID 长度。 |
|
大写十六进制 UID 字符串。 |
|
ISO14443A ATQA 值。 |
|
ISO14443A SAK 值。 |
|
卡片类型 ID。 |
|
卡片类型名称。 |
|
检测到的用户区容量,单位 byte。 |
|
MIFARE Classic 系列卡片返回 |
|
Type 2 / Ultralight / NTAG 系列卡片返回 |
UiFlow2 代码块:





