Microbit的Python API主要基于micro:bit库,该库提供了丰富的硬件接口和功能。为了更加全面的学习,我们以官方Python Editor作为参考。

核心API学习
显示模块 (display)
Micro:bit 的显示模块是其最核心的功能之一,它控制着板载的 5×5 LED 矩阵。这个模块提供了丰富的功能,从简单的文本显示到复杂的动画效果。
基本显示功能
文本显示
from microbit import *
# 滚动显示文本(默认从右向左)
display.scroll("Hello Micro:bit!")
# 带参数的滚动显示
display.scroll("Python", delay=100, wait=False, loop=True, monospace=False)
- delay: 滚动速度(毫秒),值越小越快(默认150)
- wait: 是否阻塞程序(默认True,显示完才执行后续代码)
- loop: 是否循环显示(默认False)
- monospace: 是否使用等宽字体(默认False)
显示数字
# 直接显示整数
display.show(42)
# 显示浮点数(自动四舍五入)
display.show(3.14159) # 显示3
# 显示字符
display.show('A')
清除显示
display.clear() # 关闭所有LED
图像显示系统
内置图像
MicroPython 预置了数十种常用图像:
# 显示内置图像 display.show(Image.HEART) display.show(Image.HAPPY) display.show(Image.SAD) display.show(Image.ARROW_N) # 北箭头
其他内置图像:Images — BBC micro:bit MicroPython 1.1.1 documentation
自定义图像
您可以制作自己的图像。 每个 LED 的亮度由介于 0(关闭)和 9(最亮)之间的数字来表示:

smile = Image("00000:"
"09090:"
"00000:"
"90009:"
"09990")
display.show(smile)
备注:MicroBit v1.5的板子不能调整亮度,仅V2板子支持。
图像操作
# 图像反转(亮的变暗,暗的变亮) inverted = Image.HEART.invert() display.show(inverted) # 图像位移 shifted = Image.ARROW_E.shift_left(1) # 左移1像素 display.show(shifted)
像素级控制
设置单个像素
# 点亮(2,3)位置的LED(亮度9) display.set_pixel(2, 3, 9) # 关闭(1,1)位置的LED display.set_pixel(1, 1, 0)
- 坐标范围:x (0-4), y (0-4)
- 亮度范围:0 (关) 到 9 (最亮)
获取像素状态
brightness = display.get_pixel(0, 4) # 返回(0,4)的亮度值
动画效果
图像序列动画
# 创建动画帧
frames = [
Image("00000:00000:00900:00000:00000"),
Image("00000:09990:09090:09990:00000"),
Image("99999:90009:90009:90009:99999")
]
# 播放动画
display.show(frames, delay=200, loop=True, clear=True)
- delay: 帧间隔(毫秒)
- loop: 是否循环播放
- clear: 播放结束后是否清屏
动态生成动画
# 创建心跳动画
while True:
display.show(Image.HEART)
sleep(500)
display.show(Image.HEART_SMALL)
sleep(500)
实用技巧与示例
显示传感器数据
while True:
temp = temperature()
# 温度值显示在中间列
display.show(str(temp)[0:5]) # 最多显示5字符
sleep(1000)
创建简单游戏
# 简单的点灯游戏
x, y = 2, 2
display.set_pixel(x, y, 9)
while True:
if button_a.was_pressed():
display.set_pixel(x, y, 0)
x = (x + 1) % 5
display.set_pixel(x, y, 9)
if button_b.was_pressed():
display.set_pixel(x, y, 0)
y = (y + 1) % 5
display.set_pixel(x, y, 9)
调试技巧
串口输出:结合print()调试显示逻辑
print("Current temperature:",temperature())
按钮(button)
Micro:bit 正面有两个
按钮。 按钮 A 和按钮 B 可用作输入,以便在按下它们时在程序中进行一些操作。

button_a, button_b对象的方法:is_pressed(), was_pressed(), get_presses()。
button_a.get_presses()
- 统计型方法:返回整数,代表按压次数而不是布尔值
- 累加计数:自动记录自上次读取以来的完整按压
- 自动重置:每次调用后自动清零计数器
- 完整按压要求:只统计”按下并释放”的完整按压序列
button_a.is_pressed() vs button_a.was_pressed() 全面解析
在 MicroPython 的 Micro:bit 编程中,这两种方法都是用于检测按钮状态的,但它们的用途和内部机制有显著区别。理解这些差异对于开发响应式的用户交互程序至关重要。
核心区别对比表
| 特性 | button_a.is_pressed() | button_a.was_pressed() |
| 检测内容 | 按钮当前物理状态 | 自上次检查后的按钮状态变化 |
| 返回值时间窗口 | 当前瞬间状态 | 从上一次调用到当前的变化 |
| 返回类型 | 布尔值 (True/False) | 布尔值 (True/False) |
| 状态重置 | 无自动重置 | 检测后自动重置 |
| 典型用途 | 持续检测(如长按) | 单次动作检测(如点击) |
| 调用频率影响 | 无 | 高频率调用可能导致忽略事件 |
| 编程范式 | 状态检测 | 事件检测 |
button_a.is_pressed()
- 工作原理:直接检查按钮当前的物理状态
- 行为特点:
- 只要按钮被按住,始终返回True
- 松开后立即返回False
- 不记录历史状态变化
- 适用场景:
# 长按检测示例
from microbit import *
while True:
if button_a.is_pressed():
display.show(Image.ARROW_E) # 持续显示右箭头
else:
display.clear()
button_a.was_pressed()
- 工作原理:检测从上一次调用该方法到现在的按钮变化
- 行为特点:
- 仅在按钮按下并释放(完成一次完整点击)后返回True
- 返回True 后自动重置状态
- 如果调用间隔中未发生完整点击,返回False
- 最佳实践场景:
# 单次点击计数示例
from microbit import *
count = 0
while True:
if button_a.was_pressed():
count += 1
display.show(count)
sleep(200) # 防抖延时
常见误用场景与解决方案
误用1:高频调用导致事件丢失
# 错误示范
while True:
if button_a.was_pressed():
# 如果循环执行太快,可能错过快速点击
do_something()
# 解决方案:添加适当延时
while True:
if button_a.was_pressed():
do_something()
sleep(100) # 100ms间隔足以检测人类点击速度
误用2:误用is_pressed()检测单次点击
# 错误示范
while True:
if button_a.is_pressed():
# 会多次触发而不是仅一次
increment_counter()
# 正确方法:添加状态机
clicked = False
while True:
if button_a.is_pressed() and not clicked:
increment_counter()
clicked = True
elif not button_a.is_pressed():
clicked = False
高级使用技巧
组合使用实现双击检测
from microbit import *
import time
last_press = 0
double_click_threshold = 500 # 500ms间隔内算双击
while True:
if button_a.was_pressed():
current = time.ticks_ms()
if current - last_press < double_click_threshold:
display.show(Image.YES) # 检测到双击
last_press = current
创建长按/短按区别
from microbit import *
long_press_time = 1000 # 1秒算长按
while True:
if button_a.is_pressed():
start = time.ticks_ms()
while button_a.is_pressed():
elapsed = time.ticks_diff(time.ticks_ms(), start)
if elapsed > long_press_time:
display.scroll("Long press")
break
else:
display.scroll("Short press")
Microbit 按钮技术细节
内部状态机
- 每次调用was_pressed() 后,内部状态标志被清除
- 实际点击检测:按下 → 释放(才算一次完整点击)
- 硬件消抖:Microbit 有约 20ms 的硬件消抖滤波
内置传感器
Micro:bit 内置了多种传感器,让开发者无需额外硬件即可创建丰富的交互项目。V1.5 和 V2.0 版本在传感器方面有显著差异。
传感器概览对比表
| 传感器类型 | V1.5 | V2.0 | 主要区别 |
| 加速度计 | ✓ | ✓ | V2.0 灵敏度更高 |
| 磁力计 | ✓ | ✓ | V2.0 精度提升 |
| 温度传感器 | ✓ | ✓ | 相同实现 |
| 光线传感器 | ✗ | ✓ | V2.0 新增功能 |
| 麦克风 | ✗ | ✓ | V2.0 新增功能 |
| 触摸感应 | ✗ | ✓ | V2.0 新增功能 |
加速度计 (Accelerometer)
用途:检测运动、倾斜、震动和自由落体
from microbit import *
while True:
# 读取三轴加速度值(单位:毫g)
x = accelerometer.get_x()
y = accelerometer.get_y()
z = accelerometer.get_z()
# 检测特定动作
if accelerometer.is_gesture("shake"):
display.show(Image.SURPRISED)
# 检测倾斜方向
if accelerometer.current_gesture() == "face up":
display.show(Image.HAPPY)
sleep(100)
磁力计 (Compass)
用途:检测磁场强度、方向(电子罗盘)。

第一次使用罗盘时,您可能会被要求通过玩一个小游戏来校准它。 在显示屏上滚动显示 ‘TILT TO FILL SCREEN‘。 倾斜 micro:bit 直到每个 LED 灯都亮起,然后会出现一张快乐的脸。 该操作可确保罗盘能够提供准确的读数。
from microbit import *
# 必须先校准
compass.calibrate()
while True:
# 获取方向(0-360度)
heading = compass.heading()
# 获取磁场强度(微特斯拉)
x, y, z = compass.get_x(), compass.get_y(), compass.get_z()
# 显示方向箭头
if heading < 45 or heading > 315:
display.show(Image.ARROW_N) # 北
elif heading < 135:
display.show(Image.ARROW_E) # 东
sleep(500)
温度传感器
用途:测量处理器温度(非环境温度)
from microbit import *
while True:
temp = temperature() # 摄氏度
display.scroll(f"{temp}C")
sleep(5000)
注意:测量的是处理器温度,通常比环境温度高3-5°C
光线传感器 (仅V2.0)
用途:测量环境光强度
# 仅适用于V2.0
from microbit import *
while True:
# 获取光线强度 (0-255)
light_level = display.read_light_level()
print(light_level)
sleep(1000)
V2.0特性:
- 使用LED矩阵反向测量光线
- 适合检测光照变化而非绝对亮度
- 可用于创建光控开关
麦克风 (仅V2.0)
用途:检测声音级别和事件
# 仅适用于V2.0
from microbit import *
# 设置声音事件阈值
microphone.set_threshold(SoundEvent.LOUD, 128)
while True:
# 获取当前声音级别 (0-255)
level = microphone.sound_level()
print(level)
# 检测特定声音事件
if microphone.current_event() == SoundEvent.LOUD:
display.show(Image.SURPRISED)
elif microphone.was_event(SoundEvent.QUIET):
display.show(Image.ASLEEP)
sleep(100)
高级功能:
- get_events():获取所有待处理的声音事件
- set_analog_period(period):设置模拟信号周期
- 可用于拍手检测、声音激活项目
触摸感应 (仅V2.0)
用途:检测电容触摸
# 仅适用于V2.0
from microbit import *
while True:
# 检测引脚触摸
if pin0.is_touched():
display.show("0")
# 检测Logo区域触摸(金手指)
if pin_logo.is_touched():
display.show(Image.HEART)
sleep(200)
可用触摸点:
- 引脚:0, 1, 2, 3, 4, 5, 6, 7, 9, 10
- Logo区域:pin_logo
- 可用于创建触摸开关、交互式界面
扬声器 (仅V2.0)
用途:播放声音和音乐
# 仅适用于V2.0
from microbit import *
import music
import speech
import audio
# 您可以设置 micro:bit 播放音乐的节奏或速度: 节奏以 bpm 为单位,即每分钟节拍数。 数字低于 120 表示比正常节奏慢,高于 120 表示比正常节奏快。
music.set_tempo(bpm=120)
# 播放内置音乐
music.play(music.BIRTHDAY)
# 播放音符
music.play(['c', 'd', 'e', 'c'])
# 音调 micro:bit 可以播放由频率或音调定义的声音
music.pitch(440)
# 语音合成(完全听不清)
speech.say("Hello world", speed=120)
# 播放内置声音
audio.play(Sound.HELLO)
引脚操作指南
Micro:bit 的引脚系统是其最强大的功能之一,允许开发者连接各种外部设备和传感器。
引脚功能分类
| 引脚 | 数字I/O | 模拟输入 | 模拟输出(PWM) | 触摸感应(V2) | 特殊功能 |
| 0 | ✓ | ✓ | ✓ | ✓ | UART RX |
| 1 | ✓ | ✓ | ✓ | ✓ | UART TX |
| 2 | ✓ | ✓ | ✓ | ✓ | – |
| 3 | ✓ | ✓ | ✓ | ✓ | LED行1 |
| 4 | ✓ | ✓ | ✓ | ✓ | LED行2 |
| 5 | ✓ | ✓ | ✓ | ✓ | 按钮A |
| 6 | ✓ | ✓ | ✓ | ✓ | LED列1 |
| 7 | ✓ | ✓ | ✓ | ✓ | LED列2 |
| 8 | ✓ | ✓ | ✓ | ✓ | – |
| 9 | ✓ | ✓ | ✓ | ✓ | 按钮B |
| 10 | ✓ | ✓ | ✓ | ✓ | – |
| 11 | – | – | – | – | 保留 |
| 12 | – | – | – | – | 保留 |
| 13 | ✓ | – | – | – | SPI SCK |
| 14 | ✓ | – | – | – | SPI MISO |
| 15 | ✓ | – | – | – | SPI MOSI |
| 16 | ✓ | – | – | – | SPI CS |
| 19 | ✓ | – | – | – | I2C SCL |
| 20 | ✓ | – | – | – | I2C SDA |
| LOGO | – | – | – | ✓ | V2触摸区 |
基础引脚操作
数字输入/输出
from microbit import *
# 设置引脚为输出模式
pin0.write_digital(1) # 输出高电平 (3.3V)
pin0.write_digital(0) # 输出低电平 (0V)
# 读取数字输入
value = pin1.read_digital() # 返回0或1
if value == 1:
display.show(Image.YES)
模拟输入
# 读取模拟值 (0-1023) light_level = pin2.read_analog() # 光敏电阻示例 display.scroll(str(light_level)) # 电压计算 voltage = pin2.read_analog() * 3.3 / 1023
PWM输出
# 设置PWM占空比 (0-1023)
pin0.write_analog(512) # 50%占空比
# 控制舵机角度 (0-180度)
def set_servo_angle(pin, angle):
pulse_width = 500 + (angle * 2000 // 180) # 500-2500μs
duty_cycle = pulse_width * 1024 // 20000 # 20ms周期
pin.write_analog(duty_cycle)
set_servo_angle(pin0, 90) # 舵机转到90度
高级引脚功能
触摸感应 (V2专有)
if pin0.is_touched():
display.show(Image.HAPPY)
# 读取原始触摸值
touch_value = pin0.read_analog() # 0-1023
# Logo区域触摸
if pin_logo.is_touched():
display.show(Image.HEART)
中断处理
def on_pin_rise():
display.show("R")
# 设置中断处理
pin0.on_event(PinEvent.RISE, on_pin_rise) # 上升沿触发
pin1.on_event(PinEvent.FALL, lambda: display.show("F")) # 下降沿
pin2.on_event(PinEvent.TOUCH, lambda: display.show("T")) # V2触摸
脉冲测量
# 测量脉冲宽度 (微秒)
pulse_width = pin0.read_pulse_high() # 高电平时间
pulse_width = pin0.read_pulse_low() # 低电平时间
# 超声波测距示例
def measure_distance(trigger, echo):
# 发送10μs触发脉冲
trigger.write_digital(1)
sleep(10)
trigger.write_digital(0)
# 测量回波脉冲宽度
duration = echo.read_pulse_high()
# 计算距离 (声速340m/s)
distance = (duration * 0.034) / 2 # cm
return distance
dist = measure_distance(pin0, pin1)
通信协议支持
I2C通信
from microbit import i2c
# 扫描I2C设备
devices = []
for addr in range(0, 128):
try:
i2c.read(addr, 1)
devices.append(addr)
except:
pass
# 读取加速度计数据 (地址0x19)
i2c.write(0x19, b'\x28') # 设置寄存器
data = i2c.read(0x19, 6) # 读取6字节
x = (data[1] << 8) | data[0]
SPI通信
from microbit import spi
# 初始化SPI
spi.init(baudrate=1000000, bits=8, mode=0,
sclk=pin13, mosi=pin15, miso=pin14)
# 发送数据
spi.write(b'\x01\x02\x03')
# 同时发送和接收
received = spi.write_read(b'\xAA\x55')
UART串口通信
from microbit import uart
# 初始化UART
uart.init(baudrate=9600, bits=8, parity=None, stop=1, tx=pin0, rx=pin1)
# 发送数据
uart.write("Hello World\n")
# 接收数据
if uart.any():
data = uart.read()
display.scroll(data)
引脚配置选项
上拉/下拉电阻
# 设置内部上拉电阻 pin0.set_pull(pin0.PULL_UP) # 默认高电平 pin1.set_pull(pin1.PULL_DOWN) # 默认低电平 pin2.set_pull(pin2.NO_PULL) # 无上拉/下拉
省电技巧
# 关闭未使用引脚
def disable_unused_pins():
for pin in [pin8, pin11, pin12, pin13, pin14, pin15, pin16]:
pin.set_pull(pin.NO_PULL)
pin.write_digital(0)
引脚模式设置
# 设置引脚为模拟输入 pin0.set_analog_period(20) # 设置PWM周期(毫秒) # 设置触摸模式(V2) pin0.set_touch_mode(True) # 启用触摸检测
引脚状态检测
# 获取引脚模式 mode = pin0.get_mode() # 返回: digital_in, digital_out, analog, touch # 获取引脚编号 pin_num = pin0.get_id()
引脚冲突管理
引脚复用机制
Micro:bit 的物理引脚与内部功能复用关系:
P0:LED列1、ADC输入、GPIO P1:LED列2、ADC输入、GPIO P2:LED列3、ADC输入、GPIO P3:LED行1、GPIO P4:LED行2、GPIO P5:按钮A、GPIO P6:LED行3、GPIO P7:LED列4、GPIO P8:预留 P9:LED列5、GPIO P10:LED列6、GPIO P11:按钮B、GPIO P12:预留 P13:SPI时钟 P14:SPI数据输入 P15:SPI数据输出 P16:预留 P19:I2C数据 P20:I2C时钟
常见冲突场景
- LED矩阵与GPIO使用冲突
- 按钮引脚(P5/P11)与其他功能冲突
- I2C/SPI总线与自定义外设冲突
- 模拟输入与数字输出冲突
硬件层解决方案
禁用冲突功能
# 禁用LED矩阵以释放P3-P4,P6-P7,P9-P10
def safe_pin_write(pin, value):
if pin in [pin3, pin4, pin6, pin7, pin9, pin10]:
display.off()
pin.write_digital(value)
display.on()
else:
pin.write_digital(value)
引脚重映射
# I2C重映射到其他引脚 i2c.init(freq=100000, sda=pin1, scl=pin2) # SPI重映射 spi.init(baudrate=1000000, mosi=pin16, miso=pin17, sclk=pin18)
使用非冲突引脚
优先使用无复用功能的引脚:
- P0, P1, P2 (但注意LED列控制)
- P8, P12, P13-P16, P19-P20
软件层解决方案
分时复用技术
import microbit
def run_led_matrix():
display.on()
display.show(Image.HEART)
sleep(1000)
display.off()
def read_sensor():
# 在LED关闭时读取传感器
return pin1.read_analog()
while True:
run_led_matrix()
sensor_value = read_sensor()
# 处理传感器数据...
sleep(1000)
中断优先级管理
from microbit import *
# 高优先级中断
def critical_irq():
# 紧急处理代码
pass
# 低优先级任务
def normal_task():
# 非关键功能
pass
# 配置中断优先级
pin0.irq(trigger=Pin.IRQ_RISING, handler=critical_irq, priority=1)
引脚状态缓存
pin_state_cache = {}
def safe_pin_write(pin, value):
# 检查引脚状态
if pin in pin_state_cache and pin_state_cache[pin] != value:
# 解决冲突逻辑
resolve_conflict(pin)
pin.write_digital(value)
pin_state_cache[pin] = value
高级冲突解决方案
多路复用器扩展
使用CD74HC4067等芯片扩展引脚:
# 控制多路复用器选择通道
def select_mux_channel(channel):
pin8.write_digital(channel & 1)
pin12.write_digital((channel >> 1) & 1)
pin16.write_digital((channel >> 2) & 1)
# 读取16个模拟传感器
for ch in range(16):
select_mux_channel(ch)
value = pin2.read_analog()
I2C总线扩展
使用I2C GPIO扩展芯片(如PCF8574):
# 初始化I2C
i2c.init()
# PCF8574地址
PCF_ADDR = 0x20
# 设置扩展引脚输出
def set_expander_pins(value):
i2c.write(PCF_ADDR, bytes([value]))
# 读取扩展引脚
def read_expander_pins():
return i2c.read(PCF_ADDR, 1)[0]
虚拟引脚系统
class VirtualPin:
def __init__(self, physical_pin):
self.phys_pin = physical_pin
self.mode = None
def set_mode(self, mode):
if self.mode and self.mode != mode:
raise PinConflictError(f"Pin {self.phys_pin} mode conflict")
self.mode = mode
def write_digital(self, value):
self.set_mode('digital_out')
self.phys_pin.write_digital(value)
def read_analog(self):
self.set_mode('analog_in')
return self.phys_pin.read_analog()
# 使用虚拟引脚
vpin0 = VirtualPin(pin0)
特定冲突场景解决方案
LED矩阵与传感器冲突
# 自定义LED刷新函数避免冲突
def safe_display_show(image):
display.off()
# 快速刷新LED
for _ in range(5): # 刷新5次保证可见
display.show(image)
sleep(50)
display.off()
# 主循环
while True:
sensor_val = pin1.read_analog()
safe_display_show(Image.HEART)
sleep(1000)
按钮与GPIO冲突
# 使用中断代替轮询
def button_a_handler():
# 按钮A处理逻辑
pass
# 安全配置按钮中断
if not pin5.is_touched():
pin5.set_touch_mode(pin5.RESISTIVE)
pin5.irq(trigger=pin5.IRQ_TOUCH, handler=button_a_handler)
I2C总线设备冲突
# I2C设备分时复用
def read_i2c_device(address, register):
# 保存当前I2C状态
saved_sda = i2c.sda
saved_scl = i2c.scl
# 配置I2C
i2c.init(sda=pin1, scl=pin2)
# 读取设备
i2c.write(address, bytes([register]))
data = i2c.read(address, 1)
# 恢复I2C状态
i2c.init(sda=saved_sda, scl=saved_scl)
return data
调试与诊断工具
引脚状态监控
def print_pin_status():
pins = [pin0, pin1, pin2, pin3, pin4, pin5, pin6,
pin7, pin8, pin9, pin10, pin11, pin12,
pin13, pin14, pin15, pin16, pin19, pin20]
for i, p in enumerate(pins):
try:
mode = "IN" if p.get_mode() == 0 else "OUT"
value = p.read_digital() if mode == "IN" else "-"
print(f"P{i}: {mode} {value}")
except:
print(f"P{i}: Conflict!")
冲突检测算法
def detect_conflicts():
# 检查LED引脚
led_pins = [pin3, pin4, pin6, pin7, pin9, pin10]
for p in led_pins:
if p.read_digital() != 0 and display.is_on():
print(f"LED conflict on P{led_pins.index(p)+3}")
# 检查按钮引脚
if pin5.read_digital() == 0 and button_a.is_pressed():
print("Button A conflict")
# 检查I2C引脚
if pin19.read_digital() == 0 or pin20.read_digital() == 0:
print("I2C pins in use")
最佳实践指南
引脚使用优先级:
- 优先使用P0、P1、P2(模拟功能)
- 其次使用P8、P12、P13-P16
- 最后考虑复用引脚(P3-P4,P6-P7,P9-P11)
无线电通信(radio)
Micro:bit 的无线电模块是其最强大的功能之一,允许设备之间进行无线通信。这个功能基于蓝牙低功耗(BLE)技术,但提供了更简单的抽象接口。
硬件基础架构
Micro:bit 的无线电功能通过主控芯片内置的射频模块实现:
| 版本 | 主控芯片 | 射频模块 | 关键特性 |
| V1.5 | Nordic nRF51822 | 2.4GHz 射频收发器 | BLE 4.0,最大速率1Mbps |
| V2.0 | Nordic nRF52833 | 增强型2.4GHz收发器 | BLE 5.1,支持2Mbps高速模式 |
核心组件:
- 射频收发器:负责信号的调制/解调
- 频率合成器:生成4GHz工作频率
- 功率放大器:可配置发射功率(-20dBm至+4dBm)
- 基带处理器:处理数据包和协议栈
- 天线系统:PCB集成倒F天线(工作在4GHz)
无线电工作原理
发送过程

接收过程

核心技术特点
物理层深度解析
信号传播特性
- 衍射:绕过障碍物(但金属会完全阻挡)
- 反射:墙壁等表面反射引起多径干扰
- 衰减:遵循自由空间路径损耗公式:
损耗(dB) = 32.44 + 20*log10(f) + 20*log10(d)
- f=频率MHz
- d=距离km
例如:2.4GHz@10米 ≈ 60dB损耗
实际性能指标
| 指标 | V1.5 | V2.0 | 测试条件 |
| 理论带宽 | 1Mbps | 2Mbps | 无干扰环境 |
| 实测吞吐量 | 80Kbps | 210Kbps | 32字节包长 |
| 有效距离 | 30米 | 70米 | 开阔场地 |
| 延迟 | 2-5ms | 1-3ms | 设备对传 |
| 功耗 | 发送:15mA 接收:12mA |
发送:13mA 接收:10mA |
功率等级0 |
| 同时连接 | 6-8台 | 12-16台 | 星型网络 |
与标准无线技术对比
| 特性 | Micro:bit Radio | Bluetooth BLE | Wi-Fi | Zigbee |
| 拓扑结构 | 网状/星型 | 点对点/星型 | 星型 | 网状 |
| 连接建立 | 即时 | 需配对 | 需关联 | 需组网 |
| 适用距离 | <100米 | <100米 | <100米 | <100米 |
| 典型速率 | 200Kbps | 1Mbps | >1Mbps | 250Kbps |
| 功耗 | 极低 | 低 | 高 | 极低 |
| 抗干扰 | 中等 | 高 | 高 | 高 |
无线电模块基础
基本使用步骤
import radio # 导入模块
radio.on() # 启用无线电
radio.config(channel=7) # 设置频道(0-100)
# 发送消息
radio.send("Hello Micro:bit!")
# 接收消息
incoming = radio.receive()
if incoming:
display.scroll(incoming)
完整配置参数
radio.config(
length=32, # 消息长度(1-251字节)
queue=3, # 接收队列大小
channel=7, # 通信频道(0-100)
power=6, # 发射功率(0-7,7最强)
data_rate=radio.RATE_1MBIT, # 传输速率
address=0x756269, # 地址(类似MAC地址)
group=0, # 组号(0-255)
security=None # 安全设置(V2新增)
)
重要参数说明
| 参数 | 范围 | 默认值 | 说明 |
| channel | 0-100 | 7 | 避免WiFi常用频道(1,6,11) |
| power | 0-7 | 6 | 7=最大功率(+4dBm),0=最低功率(-30dBm) |
| data_rate | RATE_250KBIT RATE_1MBIT RATE_2MBIT |
RATE_1MBIT | V2支持所有速率,V1仅支持1MBIT |
| group | 0-255 | 0 | 逻辑分组,只接收同组消息 |
| length | 1-251 | 32 | 较大值增加吞吐量但降低可靠性 |
核心API详解
发送消息
# 发送字符串
radio.send("Temperature:25C")
# 发送字节数据
data = b'\x01\x02\x03\x04'
radio.send_bytes(data)
# 发送结构化数据(推荐)
import ustruct
packet = ustruct.pack('4sif', b"DATA", 42, 3.14)
radio.send_bytes(packet)
接收消息
# 接收字符串
msg = radio.receive()
if msg:
print("Received:", msg)
# 接收字节数据
data = radio.receive_bytes()
if data:
# 解析结构化数据
id, value, temp = ustruct.unpack('4sif', data)
高级接收(V2)
# 接收完整数据包(含元数据)
packet = radio.receive_full()
if packet:
payload, rssi, timestamp = packet
print(f"Payload: {payload}, RSSI: {rssi}dBm, Time: {timestamp}ms")
通信协议设计
简单文本协议
# 发送端
radio.send(f"TEMP:{temperature()},LIGHT:{light_level}")
# 接收端
msg = radio.receive()
if msg and msg.startswith("TEMP:"):
parts = msg.split(',')
temp = float(parts[0].split(':')[1])
light = int(parts[1].split(':')[1])
二进制协议
# 定义协议格式
# 字节0: 数据类型 (1=温度, 2=湿度...)
# 字节1-4: 浮点数值
# 字节5: 校验和
def create_packet(data_type, value):
data = bytearray(6)
data[0] = data_type
data[1:5] = ustruct.pack('f', value)
data[5] = sum(data[0:5]) & 0xFF # 简单校验
return data
# 解析数据
def parse_packet(data):
if len(data) != 6 or sum(data[0:5]) & 0xFF != data[5]:
return None # 校验失败
data_type = data[0]
value = ustruct.unpack('f', data[1:5])[0]
return (data_type, value)
安全通信(V2专有)
AES-128加密
from radio import security
import cryptolib
# 设置加密密钥(16字节)
key = b'MicrobitSecret!'
security.set_key(key)
# 启用加密
radio.config(security=security.AES)
# 发送加密数据(自动加密)
radio.send("Sensitive data")
# 接收时自动解密
msg = radio.receive() # 已解密
地址过滤
# 设置允许的地址列表 allowed_addresses = [0x123456, 0x789ABC] security.set_address_filter(allowed_addresses) # 只接收来自这些地址的消息
高级技巧与优化
省电策略
# 间歇性唤醒
while True:
radio.on()
# 发送/接收数据
radio.send("Ping")
sleep(100) # 等待响应
radio.off() # 关闭无线电省电
sleep(9000) # 休眠9秒
信号强度检测(RSSI)
# V2支持接收信号强度指示
packet = radio.receive_full()
if packet:
_, rssi, _ = packet
# RSSI是负值,值越大信号越好(如-50比-70好)
if rssi > -70: # 良好信号
display.show(Image.YES)
抗干扰技术
# 频道跳频
channels = [7, 23, 42, 56]
current_channel = 0
while True:
radio.config(channel=channels[current_channel])
# 通信...
# 定期切换频道
if button_a.was_pressed():
current_channel = (current_channel + 1) % len(channels)
数据压缩
import zlib # V2支持
# 发送压缩数据
data = "Long text message..." * 10
compressed = zlib.compress(data.encode())
radio.send_bytes(compressed)
# 接收端
compressed = radio.receive_bytes()
if compressed:
data = zlib.decompress(compressed).decode()
调试与故障排除
常见问题
- 无通信:检查频道、组号、无线电是否开启
- 数据丢失:减少数据长度、降低传输速率
- 干扰:避开WiFi频道(1,6,11)
- 距离短:增加发射功率(config(power=7))
调试工具
# 无线电状态监测
def radio_status():
print("Channel:", radio.config().get('channel', 'N/A'))
print("Queue size:", len(radio.receive_bytes()))
# V2特有
if hasattr(radio, 'rssi'):
print("RSSI:", radio.rssi())
性能测试
# 吞吐量测试
import time
radio.on()
radio.config(length=251, data_rate=radio.RATE_2MBIT)
start = time.ticks_ms()
count = 0
data = b'x' * 250 # 250字节数据
while time.ticks_diff(time.ticks_ms(), start) < 5000: # 5秒测试
radio.send_bytes(data)
count += 1
蓝牙功能
Micro:bit 的蓝牙功能是其最强大的特性之一,允许设备与其他蓝牙设备(如手机、电脑)进行无线通信。
蓝牙功能概述
硬件支持
- 5:支持蓝牙4.0(BLE)
- 0:支持蓝牙5.0(BLE),兼容蓝牙4.0,提供更快的速度和更远的距离
核心功能
- 与智能手机/平板配对通信
- 无线编程(无需USB线)
- 创建自定义蓝牙服务
- 与其他Micro:bit通信(通过蓝牙而非无线电)
- 低功耗模式(节省电池)
基础蓝牙操作
启用蓝牙
import bluetooth bluetooth.init() # 初始化蓝牙模块
设置设备名称
bluetooth.set_device_name("MyMicrobit")
开始广播
bluetooth.start_advertising(interval=200) # 广播间隔200ms
检测连接状态
if bluetooth.is_connected():
display.show(Image.HAPPY)
else:
display.show(Image.SAD)
蓝牙配对与连接
手机配对流程
- Micro:bit运行蓝牙程序
- 手机蓝牙设置中搜索”MyMicrobit”
- 配对连接(无需PIN码)
- 使用蓝牙调试App(如nRF Connect)查看服务
连接管理
# 获取连接句柄 conn_handle = bluetooth.connection() # 断开连接 bluetooth.disconnect()
创建蓝牙服务
定义服务UUID
from bluetooth import UUID # 自定义服务UUID SERVICE_UUID = UUID(0x180F) CHAR_UUID = UUID(0x2A19)
创建特征
battery_char = bluetooth.Characteristic(
CHAR_UUID,
bluetooth.FLAG_READ, # 只读特征
value="50%", # 初始值
max_len=5 # 最大长度
)
创建服务
battery_service = bluetooth.Service(
SERVICE_UUID,
[battery_char], # 包含的特征列表
nbr_chars=1 # 特征数量
)
注册服务
bluetooth.add_service(battery_service)
数据通信
读取数据
# 更新特征值 bluetooth.update_char_value(battery_char, "75%") # 在手机端读取将得到"75%"
写入数据
# 创建可写特征
led_char = bluetooth.Characteristic(
UUID(0xFFE1),
bluetooth.FLAG_WRITE,
max_len=1
)
# 写入回调函数
def on_write(conn_handle, char_handle, value):
if value == b'\x01':
display.show(Image.YES)
elif value == b'\x00':
display.clear()
bluetooth.set_write_callback(on_write)
通知功能
# 创建支持通知的特征
temp_char = bluetooth.Characteristic(
UUID(0x2A6E),
bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY
)
# 启用通知
bluetooth.char_notify_enable(temp_char)
# 更新值并通知
while True:
temp = temperature()
bluetooth.update_char_value(temp_char, f"{temp}C")
sleep(5000)
无线编程(蓝牙DFU)
启用无线编程模式
# 在main.py中添加 import bluetooth bluetooth.enable_irq(handler=None) bluetooth.set_advertising(interval=200, name="MicrobitDFU")
手机端操作
- 安装”Micro:bit”官方App
- 搜索并连接Micro:bit
- 选择hex文件上传
- 等待编程完成(LED闪烁)
蓝牙与无线电协同
蓝牙网关
import bluetooth
import radio
radio.on()
bluetooth.init()
def on_bluetooth_data(data):
# 将蓝牙数据转发到无线电
radio.send(data)
def on_radio_data():
# 将无线电数据转发到蓝牙
data = radio.receive()
bluetooth.send(data)
# 主循环
while True:
if bluetooth.is_connected():
data = bluetooth.receive()
if data:
on_bluetooth_data(data)
if radio.any():
on_radio_data()
sleep(100)
高级功能
低功耗模式
# 配置低功耗参数
bluetooth.config(
power=0, # 最低发射功率
interval=1000, # 广播间隔1秒
timeout=30 # 30秒无连接停止广播
)
# 深度睡眠
if not bluetooth.is_connected():
bluetooth.stop_advertising()
microbit.sleep(10000) # 休眠10秒
安全配对
# V2支持安全配对
bluetooth.set_security(
level=bluetooth.SECURITY_MEDIUM,
bond=True, # 绑定设备
mitm=True # 中间人保护
)
# 设置配对密码
bluetooth.set_passkey("123456")
多连接
# V2支持最多3个连接
if bluetooth.can_accept_connection():
bluetooth.accept_connection()
调试与问题解决
常见问题
- 无法连接:重启Micro:bit和手机蓝牙
- 服务不可见:确认UUID设置正确
- 数据丢失:减少数据包大小
- 功耗过高:增加广播间隔
调试工具
# 打印蓝牙状态
def print_ble_status():
print("Connected:", bluetooth.is_connected())
print("Address:", bluetooth.address())
print("RSSI:", bluetooth.rssi())
print("Services:", bluetooth.list_services())
LED状态指示
- 慢闪:广播中
- 快闪:连接建立中
- 常亮:已连接
- 熄灭:未启用蓝牙
文件系统
Micro:bit 的文件系统是其重要功能之一,特别是在 V2 版本中得到了显著增强。以下是对 Micro:bit 文件系统的详细介绍:
文件系统基础
硬件支持
- 5:
- 无专用文件系统存储
- 可通过特殊技巧模拟文件操作(有限)
- 0:
- 512KB Flash 存储器
- 其中 256KB 专用于文件系统
- FAT 格式兼容文件系统
文件系统特性
| 特性 | V1.5 | V2.0 |
| 存储空间 | 无专用空间 | 256KB |
| 文件数量限制 | 无 | 最多约100个文件 |
| 文件大小限制 | 无 | 最大64KB |
| 持久存储 | 重启后丢失 | 断电保持 |
| USB访问 | 不支持 | 支持(MAINTENANCE模式) |
文件系统访问方式
USB 访问模式
- 按住复位按钮
- 连接USB线
- 释放复位按钮
- 电脑显示为”MAINTENANCE”驱动器
- 可直接拖放文件操作
Python API 访问
import os
# 列出文件
files = os.listdir()
print(files)
# 创建文件
with open('data.txt', 'w') as f:
f.write("Hello Microbit!")
# 读取文件
with open('data.txt', 'r') as f:
content = f.read()
print(content)
# 删除文件
os.remove('old.txt')
文件系统管理技巧
空间优化
# 定期清理旧文件
MAX_FILES = 10
MAX_SIZE = 100 * 1024 # 100KB
def cleanup_files():
files = sorted(os.listdir(), key=os.size, reverse=True)
total_size = sum(os.size(f) for f in files)
# 删除最旧的文件直到满足限制
while len(files) > MAX_FILES or total_size > MAX_SIZE:
oldest = min(files, key=os.stat)
size = os.size(oldest)
os.remove(oldest)
files.remove(oldest)
total_size -= size
# 每周清理一次
if running_time() % (7 * 24 * 3600 * 1000) < 1000:
cleanup_files()
错误处理
def safe_file_op(func, *args):
try:
return func(*args)
except OSError as e:
if e.args[0] == 28: # ENOSPC
display.show(Image.SAD)
return "存储空间不足"
elif e.args[0] == 2: # ENOENT
return "文件不存在"
else:
return f"错误: {e}"
# 安全写入
result = safe_file_op(lambda: open('data.txt', 'w').write("test"))
文件系统检查
def check_fs_integrity():
files = os.listdir()
for f in files:
try:
with open(f, 'r') as test_file:
test_file.read(1)
except OSError:
print(f"损坏文件: {f}")
os.remove(f)
# 检查剩余空间
usage = os.statvfs('/')
if usage[3] < 10: # 少于10个块
display.show(Image.SKULL)
V1.5 文件系统模拟
EEPROM 模拟
# V1.5使用Flash模拟EEPROM
import microbit
# 写入数据
microbit.storage.store("key", "value")
# 读取数据
value = microbit.storage.load("key")
# 删除数据
microbit.storage.remove("key")
文件系统模拟
# 简单的键值存储模拟文件系统
FILE_SYSTEM = {}
def v1_write_file(name, content):
FILE_SYSTEM[name] = content
def v1_read_file(name):
return FILE_SYSTEM.get(name, None)
def v1_list_files():
return list(FILE_SYSTEM.keys())
注意事项与最佳实践
- 写寿命管理:
- Flash芯片有约10万次擦写寿命
- 避免高频写入同一位置
- 使用追加模式而非覆盖
- 电源安全:
- 写入时避免断电
- 使用sync()确保数据写入
with open('important.dat', 'w') as f:
f.write(data)
os.sync() # 强制写入物理存储
- 文件命名规范:
- 使用3格式(主名8字符,扩展名3字符)
- 避免特殊字符
- 使用小写字母
- 性能优化:
- 批量写入减少文件操作
- 使用二进制格式提高效率
- 避免频繁打开/关闭文件
- 安全考虑:
- 敏感数据加密存储
- 验证文件完整性
- 限制文件访问权限
参考链接:BBC micro:bit MicroPython documentation — BBC micro:bit MicroPython 1.1.1 documentation



