1.自我介绍:本人从事电子工程师多年,一直是以硬件为主工作,最两年才从事一些与软件有关的设计工作,基础不是特别的牢,软件水平不是特别流畅,所以才申请RP2040学习。
2.芯片介绍:
RP2040芯片参数:
- 双核 Arm Cortex-M0 + @ 133MHz
- 芯片内置 264KB SRAM 和 2MB 的板载闪存
- 通过专用 QSPI 总线支持最高 16MB 的片外闪存
- DMA 控制器 30 个 GPIO 引脚,其中 4 个可用作模拟输入
- 2 个 UART、2 个 SPI 控制器和 2 个 I2C 控制器 16 个 PWM 通道
- USB 1.1 主机和设备支持 8 个树莓派可编程 I/O(PIO)状态机,用于自定义外围设备支持 支持 UF2 的 USB 大容量存储启动模式,用于拖放式编程 。
3.芯片设计体验思路(含开发思路、扩展硬件、搜集素材的思路等)
1、芯片设计思路主要是根据PCIO核心板相似,参照核心板的部分相关布局,包括相关BOOT、存储芯片、晶振布局都有一些类似。
2、主要扩展硬件有GPIO8控制的WS2812显示时钟RGB灯,GPIO14脚控制蜂鸣器,SW1,SW2调节时间,有计划OLED显示等功能。
3、素材主要是想引用核心板,小巧简单,排针随时可以插拔,方便。另一方面是想做一个只有自己看的懂的实时时钟,也是引用了网友的设计布局,主要原因是这个看的时候容易好理解,从上之下的可以很明理。
4、画原理图、PCB制板过程中遇到的问题,以及解决方法
1、画原理图:
画原理图时,找了好多相关的资料,不知道做哪一个功能的好,最后看到好多人都比较喜欢RGB最终才选择WS2812去实现一个时钟的功能,最终以RP2040官方原理图开始绘画原理图设计,在画官方原理图和WS2812灯这个过程中,想到时钟都有一个带整点报时,于时就增加了一个蜂鸣器。
2、画PCB:
在进行PCB时,一直都把PCIO核心板进行对比,核心板是四层,我画的时候尽量用双面去搞定,然后器件在一面就出现难题了,放不下,思来想去,决定把器件放到板子的另一面,最终还是完成了了PCB的工作。
以下是整个PCB背面布局。
项目整体设计流程图:
5、展示用RP2040芯片设计功能板与板功能介绍
图中1:主要是MCU RP2040的核心电路部分的供电电容器件,这些电容分别 有3.3V和1.9V电路,还包括R104,R107的5.1K电阻,是在TYPE C的CC1,CC2上的。
图中2:是用的WS2812,作为时钟的时显示。
图中3:是用来显示时间的分显示。
6、核心代码:
peak = 255
music_on = False
mymusic = None
led = neopixel_rp2040.neopixel(LEDS=pin_cfg.LED_COUNT, PIN=pin_cfg.ws2812)
# led = neopixel_rp2040.neopixel(LEDS=28, PIN=8)
# 将WS2812 LED灯根据时间指示分成三个数组
hour_leds = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
ten_min_leds = [13, 14, 15, 16, 17, 18]
one_min_leds = [19, 20, 21, 22, 23, 24, 25, 26, 27, 28]
class OledTime():
def __init__(self, oled):
self.oled = oled
self.oled.fill(0)
self.wri = Writer(oled, freesans20)
def show_tim(self, hour, minite, second):
self.h=hour
self.mi=minite
self.s=second
def draw1(self):
self.wri.set_textpos(oled, 30, 20)
self.wri.printstring(str(self.h))
self.wri.set_textpos(oled, 30, 60)
self.wri.printstring(str(self.mi))
self.wri.set_textpos(oled, 30, 100)
self.wri.printstring(str(self.s))
def show_date(self, year, month, day):
self.y = year
self.m = month
self.d = day
def draw2(self):
self.wri.set_textpos(oled, 10, 10)
self.wri.printstring(str(self.y))
self.wri.set_textpos(oled, 10, 70)
self.wri.printstring(str(self.m))
self.wri.set_textpos(oled, 10, 100)
self.wri.printstring(str(self.d))
oled_time = OledTime(oled)
def Ws2812Time(hour,minite,second):
h_tmp = hour
m_tmp = minite
s_tmp = second
tw_h = h_tmp % 12 or 12
minute_tens = (m_tmp // 10) % 10
minute_ones = m_tmp % 10
led.set(COLOR=led.BLACK, BRIGHTNESS=0.03)
led.set(LED_NUMBER=hour_leds[tw_h]-2, COLOR=led.MAGENTA, BRIGHTNESS=0.03)
led.set(LED_NUMBER=ten_min_leds[minute_tens]-1, COLOR=led.CYAN, BRIGHTNESS=0.03)
led.set(LED_NUMBER=one_min_leds[minute_ones]-1, COLOR=led.RED, BRIGHTNESS=0.03)
def music_toggle(on):
global music_on, mymusic
if music_on and not on:
mymusic.stop()
music_on = False
elif not music_on and on:
mymusic = music(song, tempo = 1)
gc.collect()
mymusic.beat = 200
music_on = True
class AlarmTime:
def __init__(self, oled):
self.oled = oled
self.s = 5
self.ss = 0 # alarm absolute time
self.on = False
self.wri = Writer(oled, freesans20)
def render(self):
if self.on and mymusic is not None:
mymusic.tick()
def update(self, s):
if (s - 10 - self.ss) % 60 == 10:
self.on = False
if self.on and self.ss < s:
music_toggle(True)
elif not self.on:
music_toggle(False)
def draw(self):
self.oled.fill(0)
self.wri.set_textpos(oled, 10, 50)
self.wri.printstring(str(self.s))
self.wri.set_textpos(oled, 10, 70)
self.wri.printstring(str('s'))
self.wri.set_textpos(oled, 40, 10)
self.wri.printstring(str('k2:Increase '))
self.wri.set_textpos(oled, 25, 10)
self.wri.printstring(str('k1:Confirm '))
alarm_time = AlarmTime(oled)
class StateMachine():
SettingAlarmTime = 0
ShowCurrentTime = 1
def __init__(self, alarmTime):
self.state = StateMachine.ShowCurrentTime
self.old_state = self.state
self.alarmTime = alarmTime
def update(self, k1, k2, s):
self.old_state = self.state
if self.state == StateMachine.ShowCurrentTime:
self.showCurrentTime(k1)
elif self.state == StateMachine.SettingAlarmTime:
self.settingAlarmTime(k1, k2, s)
def showCurrentTime(self, k1):#未按k1显示时间
if k1 == False:
pass
elif k1 == True:
self.alarmTime.on = False
self.state = StateMachine.SettingAlarmTime
def settingAlarmTime(self, k1, k2, s):#按k1显示倒计时的时间
if k1 == False:
if k2:
self.alarmTime.s = (self.alarmTime.s + 5) % 60
pass
if k1 == True:
self.alarmTime.ss = (s + self.alarmTime.s + 1) % 60
self.alarmTime.on = True
self.state = StateMachine.ShowCurrentTime
fsm = StateMachine(alarm_time)
tick = 0
led.reset()
# led.set(BRIGHTNESS=0.01)
while True:
oled.fill(0)
dt_tuple = rtc.datetime()
print(dt_tuple)
year = dt_tuple[0]
month = dt_tuple[1]
day =dt_tuple[2]
hour = dt_tuple[4]
minite = dt_tuple[5]
second = dt_tuple[6]
oled_time.show_date(year, month, day)
oled_time.show_tim(hour, minite, second)
# ws2812_time.show_time(hour, minite, second)
alarm_time.update(second)
k1_value = k1.value()
k2_value = k2.value()
fsm.update(k1_value, k2_value, second)
if fsm.state == StateMachine.ShowCurrentTime:
oled_time.draw2()
oled_time.draw1()
if fsm.state == StateMachine.SettingAlarmTime:
alarm_time.draw()
Ws2812Time(hour, minite, second)
# rendering
oled.show()
alarm_time.render()
tick = (tick + 1) % 65536
sleep(0.04) # fps = 25
总结:
1.首先说一下RP2040的性能,个人感觉还是非常强大的,资源很丰富。
2.开发使用可选用Python或C/C++进行开发,方便快速开发,灵活易用。