电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
[树莓派系列] 入门WiringPi库的PWM接口(C和Python)
分 享
扫描二维码分享
[树莓派系列] 入门WiringPi库的PWM接口(C和Python)
树莓派
树莓派PWM
wybliw
关注
发布时间: 2020-10-09
丨
阅读: 5528
[TOC] --- --- **难度:** ★★ **读者:** 适合有`C语言`或`Python`编程基础的读者。 --- 上期文章: 《 [树莓派4B-WiringPi库的安装和使用](https://www.icxbk.com/article/preview?astatus=1&aid=1707) 》介绍了如何在树莓派上搭建WiringPi库(C和Python版),并实现简单的点亮LED灯教程。本文及后续文章都将使用WiringPi库来编写程序示例,若读者还没有搭建WiringPi库,可以先阅读上期文章,搭建好WiringPi库环境。 本篇将介绍WiringPi库中的PWM接口的使用,通过树莓派控制呼吸灯实例来展示。 **准备工作:** * 树莓派 * 一个LED灯 * 面包板和若干导线 --- ## 树莓派PWM简介 ### PWM简介 **脉冲宽度调制**(**Pulse-width modulation**,**PWM**),简称**脉宽调制**,对**模拟信号**电平进行**数字编码**的方法。 **PWM周期:** `周期(T) = 1 / 频率(f)`,比如:频率50Hz,其周期为20ms。 **占空比:**`duty ratio = Ton/(Ton + Toff)`,就是指在一个周期T内,信号处于高电平的时间Ton占据整个信号周期T的百分比,例如方波的占空比就是50%。 **分辨率:**就是占空比最小能达到多少,如8位的PWM,理论的分辨率就是1 - 255,10位PWM就是:1 - 1023。假如规定:当t=0时,称占空比为0%,t=T时称占空比为100%,那么8位即为把100%的占空比分为256(2的8次方)个档位,10位即为将其分为1024个档位,档位越多,分辨率就越高。 下图中前一周期,占空比20%,后一周期占空比50%。 ![](https://cf02.ickimg.com/bbsimages/202010/f7f0b67a2185cc289c3ef573f60e79b0.png) ### 树莓派PWM 树莓派4B上有有2个PWM通道,对应4个GPIO口,即有4个硬件PWM口,如下: | WiringPi Pin | Phy Pin | PWM0、PWM1 | | ------------ | ------- | ---------- | | GPIO1 | Pin 12 | PWM0 | | GPIO26 | Pin 32 | PWM0 | | GPIO23 | Pin 33 | PWM1 | | GPIO24 | Pin 35 | PWM1 | 下图是引脚详细信息,这里借用Pi3的GPIO图(和Pi4一致),图中虚线框中的就是4个硬件PWM口。 ![](https://cf02.ickimg.com/bbsimages/202010/1c0acdc1850bca9ad61d2ed9c74c3700.png) ### WiringPi库-硬件PWM接口介绍 使用硬件PWM接口需要包含头文件:`#include
` #### **pwmSetClock (int divisor)** 参数: * divisor:设置PWM时钟的分频。范围:2 ~ 4095。 **注:** PWM基础时钟19.2MHz,WiringPi库在初始化时,默认divisor值是32,因此默认PWM时钟就为PWMfreq = 19.2 x 1000 x 1000 / 32 = 600KHz。 #### **pwmSetMode (int mode)** 参数: * mode:PWM发生器能在2中模式下工作,`Balanced` 和 `Mark:Space` 模式(占空比模式),对应的设置参数: **PWM_MODE_BAL** 与 **PWM_MODE_MS** 。 `Mark:Space` 是传统PWM模式,树莓派默认PWM工作在 `Balanced` 模式。需要重新设置占空比,就要设置为`Mark:Space` 模式。 #### **pwmSetRange (int range)** 参数: * range:用来设置PWM的周期,默认值是1024。计算方式:比如600KHz的PWM时钟, `range = (600 x 1000Hz) / PWMfreq` 。 #### pwmWrite (int pin, int value) 参数: * pin:硬件PWM引脚编号(在WiringPi中的编号),将在该引脚上产生PWM波。 * value:设置占空比,value取值范围:0 ~ range,默认范围:0-1023。因为一个周期分为range等份,因此占空范围0~range。 ### WiringPi库-软件PWM接口介绍 使用软件PWM接口需要包含头文件:`#include
` #### **softPwmCreate (int pin, int value, int range)** 用来创建软件控制PWM,能在任意GPIO口生成PWM波。 参数: * pin:要产生PWM波的GPIO引脚编号。 * value:指定在PWM range 之间的任何一个初始值。 * range:PWM的频率范围。设置range为100,则PWM频率为100Hz,value取值范围从0到100。这些值对产生不同占空比的PWM是有用的。 **注:**`PWMfreq = 1 x 10^6 / (100 x range)`,单位Hz,其中100是源码固定参数。 #### void softPwmWrite (int pin, int value) 参数: * pin:要控制的GPIO口,即在softPwmCreate函数中设置过的GPIO口。 * value:占空比值,范围:0~range。 #### void softPwmStop (int pin) 参数: * pin:要关闭的GPIO口。 --- ## PWM编程实战 ### 呼吸灯(C语言版) #### 使用硬件PWM实现 代码很简单,如下: ```c #include
#include
#include
// 设置GPIO1为LED灯的控制引脚 #define PWM_PIN 1 int main(void) { int bright ; printf("wiringPi-C PWM test program\n") ; // 配置gpio wiringPiSetup(); // 配置GPIO1为PWM模式 pinMode(PWM_PIN, PWM_OUTPUT); while(1) { for(bright = 0 ; bright < 1000; bright++) { // bright为 0 ~ 1000,最大是1023 pwmWrite(PWM_PIN, bright); delay(1) ; } for(bright = 1000; bright >= 0; bright--) { pwmWrite(PWM_PIN, bright); delay(1) ; } } return 0 ; } ``` 将代码保存到`led_pwm.c`文件,然后执行编译命令: ```bash gcc led_pwm.c -o led_pwm -lwiringPi ``` 运行程序: ```bash sudo ./led_pwm ``` 效果图: ![](https://cf02.ickimg.com/bbsimages/202010/ecc189c7aa21b2103abe9e89ecd6380e.gif) #### 使用软件PWM实现 代码如下: ```c #include
#include
#include
// 定义控制LED灯的GPIO引脚,使用GPIO0 #define PWM_PIN 0 int main(void) { int bright ; printf("wiringPi-C Software PWM test program\n") ; // 初始化 wiringPiSetup(); pinMode(PWM_PIN, OUTPUT); softPwmCreate(PWM_PIN, 0, 100); while(1) { for(bright = 0; bright < 100; bright++) { softPwmWrite(PWM_PIN, bright); delay(10); } for(bright = 100; bright >= 0; bright--) { softPwmWrite(PWM_PIN, bright); delay(10); } } return 0 ; } ``` 保存,编译,运行(可不加sudo),和硬件PWM操作类似,注意连接LED灯的GPIO脚已经变成GPIO0,接线要对。 ### 呼吸灯(Python版) #### 使用硬件PWM实现 代码如下: ```python #!/usr/bin/env python # coding=utf-8 import wiringpi INPUT = 0 OUTPUT = 1 PWM_OUTPUT = 2 GPIO_CLOCK = 3 SOFT_PWM_OUTPUT = 4 SOFT_TONE_OUTPUT= 5 PWM_TONE_OUTPUT = 6 LOW = 0 HIGH = 1 PWM_PIN = 1 // 初始化 wiringpi.wiringPiSetup() wiringpi.pinMode(PWM_PIN, PWM_OUTPUT) while 1: for bright in range(0, 1000): wiringpi.pwmWrite(PWM_PIN, bright) wiringpi.delay(1) for bright in range(1000, 0, -1): wiringpi.pwmWrite(PWM_PIN, bright) wiringpi.delay(1) ``` 运行程序: ```bash sudo python pwm.py ``` 实验效果和C语言一样,图见上面C语言部分。 #### 使用软件PWM实现 代码如下: ```python #!/usr/bin/env python # coding=utf-8 INPUT = 0 OUTPUT = 1 PWM_OUTPUT = 2 GPIO_CLOCK = 3 SOFT_PWM_OUTPUT = 4 SOFT_TONE_OUTPUT= 5 PWM_TONE_OUTPUT = 6 LOW = 0 HIGH = 1 import wiringpi // 设置LED控制引脚,GPIO0 PWM_PIN = 0 // 初始化 wiringpi.wiringPiSetup() wiringpi.pinMode(PWM_PIN, OUTPUT) wiringpi.softPwmCreate(PWM_PIN, 0, 100) while 1: for bright in range(0, 100): wiringpi.softPwmWrite(PWM_PIN, bright) wiringpi.delay(10) for bright in range(100, 0, -1): wiringpi.softPwmWrite(PWM_PIN, bright) wiringpi.delay(10) ``` 代码运行可以不加sudo,注意GPIO引脚已经改变为GPIO0,实验效果和C语言一样,图见上面C语言部分。 --- ## 参考文献 * [WiringPi官方 Raspberry Pi Specifics](http://wiringpi.com/reference/raspberry-pi-specifics/) * [wiringPi库的pwm配置及使用说明](https://www.cnblogs.com/miaoxiong/p/10556072.html) == end ==
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
wybliw
关注
评论
(1)
登录后可评论,请
登录
或
注册
7943603
118
天前...
不错,很详细
0
回复
发布
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交