John Doe
树莓派pico入门指南

树莓派pico入门指南

一.pico引脚图

1

二.怎样使用pico

首先需要安装thonny,我们在这个软件上为pico编写程序

下面视频中用到的uf2文件和软件都在这里,无需再去下载视频里的文件了
链接:https://pan.baidu.com/s/1LLKOPCaXz0YnRgKDdawKnQ?pwd=uyxt

下面链接中的视频提供了软件安装方法

三.pico点灯(测试用代码)

1
2
3
4
5
6
7
from machine import Pin #从一个称为machine的库中导入了Pin这个功能,用来控制硬件设备上的引脚。
import time #导入time库,包含了与时间相关的函数和方法。

led = Pin(25, Pin.OUT) #创建了一个名为led的对象,代表引脚号为25的GPIO(查看引脚图,led所在即引脚就是GP25)
while True: #这是一个无限循环的语句,意味着下面缩进的代码会一直重复执行,为了让程序一直运行,这是一种常见操作
led.toggle() #用于切换LED灯的状态
time.sleep(1) #延时1秒

若看到pico上的灯以一秒间隔闪烁一次,则成功

四.oled屏幕

oled相关资料链接:https://pan.baidu.com/s/1nQGsRBe6f7FK12ftu00h7w?pwd=a3b0

向pico导入链接里main.py和ssd1306.py两个文件,在main.py文件里运行即可。可更改main文件,得到不同的输出内容。
使用的是像素点为128x32的oled屏幕,而一个字符是8x8大小的,就是说最多一行输入16个字符,最多有4行,共64个字符

注意:要编写字库后,才能识别汉字和图片

接线方式(方向为pico–oled):

  1. 3v3–VCC
  2. GND–GND
  3. GP6–SDA
  4. GP7–SCK

输出字符

1
2
3
4
5
6
7
8
9
10
from ssd1306 import SSD1306_I2C        #导入自己的ssd1306库
from machine import Pin, I2C #导入官方PIN(引脚),iic通讯总线的库
from time import sleep #导入用于延时的库

i2c = I2C(1, scl=Pin(7), sda=Pin(6), freq=200000)#配置引脚(scl时钟线,sda数据线)和频率
oled = SSD1306_I2C(128, 32, i2c) #配置oled规格和通讯协议
while True: #主程序
oled.fill(0) #清空屏幕,将屏幕上所有像素点的颜色都设置成黑色(0表示黑色,1表示蓝色)
oled.text("Hello,World!",0,0) #写入文字内容和起始像素点位置
oled.show() #oled.show()将屏幕上的内容展示出来。

输出数字

1
2
3
4
5
6
7
8
9
10
11
12
13
from ssd1306 import SSD1306_I2C
from machine import Pin, I2C
from time import sleep

i2c = I2C(1, scl=Pin(7), sda=Pin(6), freq=200000)
oled = SSD1306_I2C(128, 32, i2c)
a=0
while True:
a+=1
oled.fill(0)#一定要清空屏幕,否则输出内容就糊在一起了
oled.text(str(a),0,0)
oled.show()
#sleep(1) #觉得加的太快,每次给1秒延时

输出图形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from ssd1306 import SSD1306_I2C
from machine import Pin, I2C
from time import sleep

i2c = I2C(1, scl=Pin(7), sda=Pin(6), freq=200000)
oled = SSD1306_I2C(128, 32, i2c)

while True:
oled.fill(0)
oled.pixel(20,31,1) #画点 参数(点横坐标,纵坐标,颜色)
oled.line(30, 0, 60, 30, 1) #画线 参数(起点横坐标,纵坐标,终点横坐标,纵坐标,颜色)
oled.rect(0,0,10,10,1) #画矩形 参数(起点横坐标,纵坐标,长,宽,颜色)

oled.show()

其他小技巧

1
2
3
4
5
oled.poweroff():关闭显示屏。
oled.poweron(): 打开显示屏。
oled.contrast(x): 设置显示屏的对比度,参数x范围0-100,数字越大屏幕越亮
oled.invert(x): 设置显示屏的颜色反转。参数x范围0-1,0代表黑色,1代表蓝色
oled.scroll(x,y): 用于移动屏幕显示内容,其中x和y分别表示x轴和y轴移动的像素数量

中文点阵生成网站: https://www.zhetao.com/fontarray.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from ssd1306 import SSD1306_I2C
from machine import Pin, I2C
from time import sleep
import framebuf #导入汉字图片需要的库

i2c = I2C(1, scl=Pin(7), sda=Pin(6), freq=200000)
oled = SSD1306_I2C(128, 32, i2c)
#汉字二进制列表
a=[ 0x08, 0x80, 0x10, 0x00, 0x08, 0x80, 0x10, 0xfc, 0x08, 0x80, 0x10, 0x04, 0x11, 0xfe, 0x10, 0x08, 0x11, 0x02, 0xfc, 0x10, 0x32, 0x04, 0x24, 0x20, 0x34, 0x20, 0x24, 0x20, 0x50, 0x20, 0x25, 0xfe, 0x91, 0x28, 0x24, 0x20, 0x11, 0x24, 0x48, 0x20, 0x12, 0x24, 0x28, 0x20, 0x12, 0x22, 0x10, 0x20, 0x14, 0x22, 0x28, 0x20, 0x10, 0x20, 0x44, 0x20, 0x10, 0xa0, 0x84, 0xa0, 0x10, 0x40, 0x00, 0x40]
#图片二进制列表
b=[ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x07, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x7f, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x17, 0xe0, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0xe4, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x07, 0x00, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x01, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x20, 0x00, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x20, 0x7c, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x10, 0x38, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]

while True:
oled.fill(0)
#使用时根据点阵大小更改参数
hanzi = framebuf.FrameBuffer(bytearray(a),32,16,framebuf.MONO_HLSB)
oled.blit(hanzi,0,0)
picture = framebuf.FrameBuffer(bytearray(b),80,32,framebuf.MONO_HLSB)
oled.blit(picture,32,0)

oled.show()

五.摇杆模块(ADC)

1

摇杆的x轴和y轴相当于两个独立的滑动变阻器

  1. 在静止时,摇杆位于滑动变阻器中间位置,此时阻值大约为总阻值的一半。
  2. 当摇杆移动到一侧时,例如x轴向右移动或y轴向上移动,对应的滑动变阻器的阻值会逐渐减小,最终接近于0欧姆。
  3. 而当摇杆移动到另一侧时,例如x轴向左移动或y轴向下移动,对应的滑动变阻器的阻值会逐渐增大,最终达到阻值的最大值。
    这种阻值的变化导致了模拟信号的分压情况也不同,通过将摇杆输出信号连接到模数转换器(ADC)输入引脚上,单片机可以将模拟信号转换为数字信号进行处理。
    因此,在程序设计中,我们可以根据ADC转换后的数字信号值来判断摇杆的具体位置,进而实现相应的功能。

接线方式
摇杆 —– pico

  1. GND —– GND
  2. 5v —– GP10
  3. VRX —– GP26
  4. VRY —– GP27
  5. SW —– GP28

注:5v接在GP10上,是因为直接接单片机VBUS(5v),摇杆adc读出来的值不对,你们可以试一下,我也不知道为什么,我测试过3.3v供电,数据才符合,而板子上3.3v用了一个了,这里用gpio输出高电平,也就是3.3v了
但是要先这样声明一下,gpio才会输出高电平

1
2
handle = Pin(10,Pin.OUT) #handle只是变量名,可以根据设备名称更改
handle.value(1) #设置引脚为GP10,输出模式,输出高电平

adc读取摇杆的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from machine import Pin,ADC  #导入PIN,ADC库
from time import sleep

handle = Pin(10,Pin.OUT)
handle.value(1) #设置引脚为GP10,输出模式,输出高电平

x = ADC(Pin(26,Pin.OUT)) #分配引脚
y = ADC(Pin(27,Pin.OUT))
z = Pin(28,Pin.IN,Pin.PULL_UP)
while True:
x_value = x.read_u16()
y_value = y.read_u16()
z_value = z.value()

print("X = {0:d} \t\t Y = {1:d}\t\t".format(x_value,y_value),end=f"z:{z_value}")
print()
sleep(1)

判断摇杆的方向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from machine import ADC,Pin
from time import sleep

handle = Pin(10,Pin.OUT)
handle.value(1) #设置引脚为GP10,输出模式,输出高电平

X = ADC(Pin(26,Pin.OUT))
Y = ADC(Pin(27,Pin.OUT))
Z = Pin(28,Pin.IN,Pin.PULL_UP)
while True:
X_value = X.read_u16()
Y_value = Y.read_u16()
Z_value = Z.value()

if X_value <= 600:
print("X: "+" Left ",end=" ")
elif X_value >=60000:
print("X: "+" Right ",end=" ")
elif 600<X_value<60000:
print("X: "+" Middle ",end=" ")

if Y_value <= 600:
print("Y: "+" Up ",end=" ")
elif Y_value >= 60000:
print("Y: "+" Down ",end=" ")
elif 600<Y_value<60000:
print("Y: "+" Middle ",end=" ")

if Z_value == 0:
print("Z: "+" low ",end=" ")
else:
print("Z: "+" high ",end=" ")
print()
sleep(1)

六.蜂鸣器

理论基础请看下面的视频11-1节


接线方式
蜂鸣器 —– pico

  1. “-” —– GND
  2. “+” —– GP20

演奏音乐示例代码
若只简单应用,只需修改歌曲内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import machine
import urandom
import utime
# 初始化蜂鸣器对象,设置引脚为20号引脚,输出模式
buzzer = machine.PWM(machine.Pin(20, machine.Pin.OUT))

#各音调对应频率
tones = {
"B0": 31,
"C1": 33, "CS1": 35, "D1": 37, "DS1": 39, "E1": 41, "F1": 44,
"FS1": 46, "G1": 49, "GS1": 52, "A1": 55, "AS1": 58, "B1": 62,
"C2": 65, "CS2": 69, "D2": 73, "DS2": 78, "E2": 82, "F2": 87,
"FS2": 93, "G2": 98, "GS2": 104, "A2": 110, "AS2": 117, "B2": 123,
"C3": 131, "CS3": 139, "D3": 147, "DS3": 156, "E3": 165, "F3": 175,
"FS3": 185, "G3": 196, "GS3": 208, "A3": 220, "AS3": 233, "B3": 247,
"C4": 262, "CS4": 277, "D4": 294, "DS4": 311, "E4": 330, "F4": 349,
"FS4": 370, "G4": 392, "GS4": 415, "A4": 440, "AS4": 466, "B4": 494,
"C5": 523, "CS5": 554, "D5": 587, "DS5": 622, "E5": 659, "F5": 698,
"FS5": 740, "G5": 784, "GS5": 831, "A5": 880, "AS5": 932, "B5": 988,
"C6": 1047, "CS6": 1109, "D6": 1175, "DS6": 1245, "E6": 1319, "F6": 1397,
"FS6": 1480, "G6": 1568, "GS6": 1661, "A6": 1760, "AS6": 1865, "B6": 1976,
"C7": 2093, "CS7": 2217, "D7": 2349, "DS7": 2489, "E7": 2637, "F7": 2794,
"FS7": 2960, "G7": 3136, "GS7": 3322, "A7": 3520, "AS7": 3729, "B7": 3951,
"C8": 4186, "CS8": 4435, "D8": 4699, "DS8": 4978
}

def playtone(frequency): # 播放特定频率的音调
buzzer.duty_u16(1000) # 设置脉宽调制的占空比
buzzer.freq(frequency) # 设置频率

def bequiet(): # 停止播放
buzzer.duty_u16(0)

def playsong(mysong): # 播放音乐
for s in mysong:
if (s == "P"): # 如果是“P”,表示休止符
bequiet() # 停止播放
else:
playtone(tones[s]) # 播放对应频率的音调
utime.sleep(0.25) # 播放间隔

#我还想她——林俊杰(#根据音谱修改,创作歌曲吧)
song = [
"B5","B5","A5","A5","A5","D6","C6","B5","B5","A5","A5","A5","D6","C6",
"B5","B5","C6","C6","D6","E6","E6","E6","E6","E6","E6","E6","E6",
"B5","B5","C6","C6","C6","E6","D6","B5","B5","C6","C6","C6","E6","D6",
"B5","B5","C6","D6",
"C6","C6","C6","C6","C6","C6","C6","C6","C6","D6","E6","F6","E6","E6","D6","D6","D6",
"G6","F6","E6","E6","D6","E6","E6","F6","F6",
"G6","E6","E6","G6","G6","A6","C6","C6","C6","C6","C6","C6",
"B5","C6","C6","D6","D6","D6","E6","D6","C6","C6","C6","B5","B5","D6","D6",
"C6","C6","C6","C6","C6","C6","C6","C6","E6","F6","F6","F6","E6","G6",
"G6","G6","E6","F6","F6","F6","E6","G6","G6","G6","C6","D6","D6","D6","C6","E6",
"E6","E6","C6","D6","D6","D6","C6","E6","E6","E6","C6","D6","D6","C6","A5",
"A5","A5","A6","A6","A6","A6","G6","G6","G6","C6","D6","D6","E6","E6",
"F6","F6","A5","E6","E6","E6","C6","D6","D6","D6","E6","F6","F6","F6","E6","G6",
"G6","G6","E6","F6","F6","F6","E6","A6","G6","G6","E6","F6","F6","E6","E6",
"D6","D6","D6","B6","B6","A6","E6","E6","E6","E6","C6",
"A5","A5","A6","A6","A6","A6","G6","G6","G6","G6","C6","D6","D6","E6","E6","F6",
"F6","F6","F6","F6","C6","C6","C6","A5","E6","E6","E6","B5","D6","C6","C6","C6","C6",
"E6","A6","G6","G6","E6","A6","G6","G6","E6","A6","G6"
]
playsong(song) # 播放音乐
bequiet() # 停止播放

七.PWM

  1. 呼吸灯

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import time
    from machine import Pin, PWM

    pwm = PWM(Pin(25)) #把板载led灯的GPIO配置为PWM模式(可以更改为其他引脚,将自己的led灯接在设置的引脚上)
    pwm.freq(10000) # 设置PWM频率为10kHz
    duty = 0 # 初始化PWM值和方向
    direction = 1

    while True:
    # 根据方向增减值
    duty += direction
    # 如果值大于65535,则将值设置为最大值,并改变方向为递减
    if duty > 65535:
    duty = 65535
    direction = -1
    # 如果值小于0,则将值设置为0,并改变方向为递增
    elif duty < 0:
    duty = 0
    direction = 1
    # 设置PWM的值
    pwm.duty_u16(duty)
  2. PWM舵机
    接线方式:舵机——pico
    红色线 3.3v
    棕色线 GND
    橙色线 GP5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import time
from machine import Pin, PWM

pwm = PWM(Pin(5))
pwm.freq(10000) # 设置PWM频率为10kHz
duty = 0 # 初始化值和方向
direction = 1

while True:
# 根据方向增减值
duty += direction
# 如果值大于65535,则将值设置为最大值,并改变方向为递减
if duty > 65535:
duty = 65535
direction = -1
# 如果值小于0,则将值设置为0,并改变方向为递增
elif duty < 0:
duty = 0
direction = 1
# 设置PWM的值
pwm.duty_u16(duty)

八.中断

接线方式:
led灯长脚接GP11 ,短脚接GND
摇杆按键SW接GP12,5v接3.3v,GND接GND

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import machine
import utime

led = machine.Pin(11, machine.Pin.OUT)
led.value(0)
button = machine.Pin(12, machine.Pin.IN, machine.Pin.PULL_UP)

#中断函数
def int_handler(pin):
button.irq(handler=None) #暂时禁用中断处理函数,防止重复触发
print("Interrupt Detected!")
led.value(1)
utime.sleep(2)
button.irq(handler=int_handler)#恢复中断处理函数,以便下一次中断触发时继续执行处理函数

button.irq(trigger=machine.Pin.IRQ_RISING, handler=int_handler) #handler后接入中断函数
#trigger 配置可以触发中断的事件。可能的值是:
#Pin.IRQ_FALLING 下降沿中断
#Pin.IRQ_RISING 上升沿中断
#Pin.IRQ_RISING_FALLING 上升沿或下降沿中断
#Pin.IRQ_LOW_LEVEL 低电平中断
#Pin.IRQ_HIGH_LEVEL 高电平中断

while True:
led.toggle()
utime.sleep(2)

九.定时器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from machine import Pin, Timer
import utime
led_pin = Pin(25, Pin.OUT)

# 定义定时器回调函数,用于切换LED状态
def toggle_led(timer):
led_pin.toggle()

# 创建定时器对象
timer = Timer()
# 初始化定时器,设置频率为5Hz(每秒5次),模式为周期性触发,并指定回调函数
timer.init(freq=5, mode=Timer.PERIODIC, callback=toggle_led)

while True:
pass #跳过,什么也不做

十.串口通信

先从以下链接中下载串口软件
链接:https://pan.baidu.com/s/1VXN6w_Nuc2TFNZ1zu3zozA?pwd=8t1v
接线方式: 串口模块 —— pico
5v——VBUS
GND——GND
TX——GP1(通信双方都是TX和RX交叉连接哦)
RX——GP0

打开串口软件,选择对应串口和波特率,点击开启串口的选项。
在下面输入框按照通信协议输入,点击发送,即可完成电脑向单片机通信。

1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from machine import Pin, UART
import time

# 初始化串口,设置波特率和引脚
uart = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
led = machine.Pin(25, machine.Pin.OUT)

uart.write("UART TEST\r\n") # 单片机通过串口向电脑发送测试信息
# 在电脑串口工具输入1则打开LED,0关闭LED

while True:
if uart.any() != False: # 如果串口接收到正常数据
buf = uart.read(1) # 读取一个字节的数据(参数代表读取字节个数)
if buf == b'1': #b 表示字节串的前缀
led.on()
uart.write("LED ON \r\n") # 发送串口信息,表示LED已打开 \r\n" 表示回车符和换行符
elif buf == b'0':
led.off()
uart.write("LED OFF \r\n") # 发送串口信息,表示LED已关闭

十一.PIO

介绍一个PIO点灯的程序,效率比普通的点灯程序高很多,通过使用单片机上硬件资源,减轻单片机CPU的负荷。
除此之外,PIO可以模拟IIC或VGA等很多单片机上可能没有的通信协议端口,给了开发者非常高的开发自由度,请根据PICO数据手册自行学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from rp2 import PIO, StateMachine, asm_pio
from machine import Pin
import time

@asm_pio(set_init=PIO.OUT_LOW)#@为描述符,它告诉MicroPython将代码视为PIO程序
def led_quarter_brightness():
set(pins, 0) [31]#一条指令占一个周期,[a]表示延时a个周期
set(pins, 1)
sm1 = StateMachine(1, led_quarter_brightness, freq=10000, set_base=Pin(25))#配置状态机

while(True):
sm1.active(1)#启动状态机
time.sleep(1)
sm1.active(0)#关闭状态机

十二.自学教程推荐

https://blog.csdn.net/slofslb/category_11328828.html?spm=1001.2014.3001.5482