2024 年寒假练 - 基于RP2040 的多功能嵌入式编程学习、硬件调试平台实现的PWM发生器
该项目使用了RP2040 的多功能嵌入式编程学习、硬件调试平台,实现了PWM发生器的设计,它的主要功能为:120Hz ~ 12Mh 任意频率PWM发生器,最大可调精度在1/1000。。
标签
嵌入式系统
RP2040
2024 年寒假练
调试设备
sll
更新2024-04-01
244

项目需求

作业题目及要求

    • 可编程 PWM 发生器
    • 使用 RP2040 的 PIO 编程,生成 3 路最高重复频率为 12MHz 的 PWM 信号,每一路的重复频率和占空比都可独立调节;
    • 重复频率越高,占空比分辨率降低,占空比的调节精度最高设定为 1/1000;
    • 使用按键和拨轮组合调节输出输出频率、占空比,并由按键控制每一路 PWM 信号的输出;
    • 能在 LCD 上显示基础信息如当前使用引脚示意、引脚相应的 PWM 参数;

需求分析

    • 硬件需求:
      1. RP2040 开发板:可以选择 Raspberry Pi Pico 等基于 RP2040 芯片的开发板,确保具备足够的 GPIO 引脚用于生成 PWM 信号和控制 LCD 显示屏。
      2. LCD 显示屏:选择兼容 RP2040 开发板的 LCD 显示屏,常见的选择包括 1602A 型字符型液晶显示器或者 0.96 寸 OLED 显示屏。另外,需要考虑显示屏的驱动芯片和通信接口,确保与 RP2040 开发板兼容。
      3. 按键和拨轮:选择带有数字编码器(用于拨轮)和按键的模块,例如带旋转编码器和按钮的旋转编码器模块,确保兼容 RP2040 开发板的输入电平和通信协议。
      4. 电路连接器和线缆:根据实际需求选择合适的连接器和线缆,确保连接可靠且布线整洁。
    • 软件需求:
      1. PIO 编程环境:使用 RP2040 官方提供的 PIO SDK,或者第三方成熟的 PIO 开发环境,用于编写和调试生成 PWM 信号的 PIO 代码。
      2. 控制程序语言:选择适合的编程语言,如 MicroPython 或 C++,用于编写控制程序。
      3. 开发工具:选择适合的集成开发环境(IDE)或文本编辑器,如 Thonny 或 Visual Studio Code,用于编写和调试控制程序。
      4. RP2040 开发板驱动程序:根据具体的开发板型号下载并安装对应的 USB 驱动程序和固件烧录工具,确保 RP2040 开发板能够正常连接和通信。
      5. LCD 驱动库:选择适合的 LCD 驱动库,如 RPi.GPIO 或 Adafruit CircuitPython 库,用于控制 LCD 显示屏的输出。
      6. 输入处理库:选择适合的输入处理库,如 RPi.GPIO 或 Adafruit CircuitPython 库,用于处理按键和拨轮的输入。

项目介绍

开发环境

  • 使用官方提供的Micropython固件开发
  • IDE: Thonnty
  • 开发语言:Python
  • 需求库:
    • 第三方St7789屏幕驱动库
    • PIO 支持库rp2、官方驱动库

【Thonng图】

【Thonng屏幕驱动图】

使用教程

  • 不设置频率,不输出!
  • 开机
    • 上电自动开机,显示Logo后,进入用户界面
    • 用户界面介绍
      • 左侧为三个可选IO
      • 右侧为IO状态
        • 黑色:GND
        • 红色:正在工作
        • 闪烁:正在设置IO输出
        • 浅蓝色:IO未使用

logo:

image.png

用户界面

image.png

  • 选择IO
    1. 使用设备顶部的左右摇杆操作三个IO的选择;
    2. 左右波动可以上下选择;
    3. 中键按键表示选中,即进入操作IO模式

【操作界面图】

image.png

  • 设置频率
    • 在设置界面,向左波动摇杆,即进入频率设置界面
    • 在频率设置界面,Freq和对应的IO闪烁
    • 向左波动摇杆控制频率增加。
    • 向右波动摇杆频率降低。
    • 中间按下,保存设置,PWM开始输出。
  • 设置占空比
    • 在设置界面,向右波动摇杆,即进入占空比设置界面
    • 在占空比设置界面,Duty和对应的IO闪烁
    • 向左波动摇杆控制占空比减小。
    • 向右波动摇杆占空比增加。
    • 中间按下,保存设置,返回设置界面。
  • 设置界面返回
    • 长按S键(详见原理图)返回用户界面。

【设置占空比】

image.png

【设置频率】

image.png

【设置完成,并返回】

image.png



实现的方式及框图

软件设计思路及实现

  • 软件设计:
    1. 初始化 LCD 显示屏:在控制程序中使用 LCD 驱动库初始化 LCD 显示屏,并设置显示所需的参数(如行数、列数等)。
    2. 监听按键和拨轮输入:使用输入处理库监听按键和拨轮模块的输入,并根据输入值进行相应的操作。
    3. 控制 PWM 生成器:使用 PIO 编程环境编写代码,通过 RP2040 开发板的 GPIO 输出引脚生成 PWM 信号,并根据拨轮调整输出频率和按键调整占空比。
    4. 更新 LCD 显示:根据当前的 PWM 参数和用户输入,在 LCD 显示屏上实时更新输出频率和占空比等信息。
  • 用户界面设计:
    1. 在 LCD 显示屏上显示基本信息:设计一个用户界面,在 LCD 显示屏上显示当前的 PWM 参数(如频率、占空比)和操作指南(如使用拨轮调整频率,按键调整占空比)。
    2. 响应用户输入:根据用户按键和拨轮的输入,即时更新 LCD 显示屏上的 PWM 参数,并反馈给用户当前的操作状态。


软件框图


代码说明

PIO程序

  • 按照PWM生成原理编写的PIO程序
  • 重装载值(计数最大值)被存出来isr寄存器,由软件pash到状态机。
  • x寄存器中存储比较值(cmp),用于控制占空比
  • y寄存器用于递减,并与x寄存器值比较。
# 装饰器定义引脚
@rp2.asm_pio(sideset_init=PIO.OUT_LOW)
def pwm_prog():

mov(y, isr) .side(0) # 重装载

label("loop")
jmp(x_not_y, "skip") # 比较
nop() .side(1)

label("skip")
jmp(y_dec, "loop")


锯齿波比较生成PWM示意图


PWM设置程序

  • 由按键控制PWM频率及占空比改变
            sleep(0.05)
self.IOShow.SetIO(self.IONum, self.IOColor16)

self.IOColor16 += 100
if self.IOColor16 >= (65535 - 100):
self.IOColor16 = 0

if 0 == self.btn.OK.value():
self.IOShow.SetIO(self.IONum, st7789.RED)
self.display.text(font3, "Duty: ", 5, 71)
break


if 0 == self.btn.L.value():
if self.CountMax >= 0 and self.CountMax < 1000:
self.Duty -= 1
if self.CountMax >= 1000 :
self.Duty = int(self.Duty - float(self.CountMax/1000))
if self.Duty <= 0 :
self.Duty = 0


if 0 == self.btn.R.value():

if self.CountMax >= 0 and self.CountMax < 1000:
self.Duty += 1
if self.CountMax >= 1000 :
self.Duty = int(float(self.CountMax/1000) + self.Duty )

if self.Duty >= self.CountMax :
self.Duty = self.CountMax

self.PWM.set(self.Duty)

self.display.text(font3,"Duty: ",5,71, self.IOColor16)
i = (self.Duty+1) / (self.CountMax+2) * 100
if i < 10:
i_formatted = '0{:.3f}'.format(i)
else:
i_formatted = '{:.3f}'.format(i)
i_rounded = str(i_formatted) + Str_Index
self.display.text(font3,i_rounded,5,89)
print("DutyMax:", self.CountMax)
print("Duty:", self.Duty)
  • 配合PIO库相关函数,将占空比信息推送带状态机
  • 这里对官方历程做了优化,在程序里做了mov(x, osr)这一步,那么PIO程序内就减少一个操作。
    def set(self, value):
# Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse
value = max(value, -1)
value = min(value, self._max_count)
self._sm.put(value)
self._sm.exec("pull(noblock)")
self._sm.exec("mov(x, osr)") # 这里放 PhWM 比较值
  • 由于分辨率要求,改变频率需重新初始化状态机
class PIOPWM:
def __init__(self, sm_id, pin, max_count, count_freq):
self._sm = StateMachine(sm_id, pwm_prog, freq=count_freq*2, sideset_base=Pin(pin))
self._sm.active(1)
self._sm.put(max_count)
self._sm.exec("pull()")
self._sm.exec("mov(isr, osr)")
self._max_count = max_count
self.set(int(max_count/10))

总结

  • 这块小板子可以实现很多方便的调试(传感器应用调试、调试设备等)
  • PIO灵活性很高,但需要学习成本,国内PIO相关的应用太少了,希望能看到PIO推屏幕、CAN、LIN等总线或屏幕显示接口的应用。
附件下载
RP2040作业程序.7z
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号