Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
AB32VG1
RT-Thread
学习笔记
《玩转中科蓝讯(AB32VG1)开发板》第2章 全彩LED实现魔幻色彩
发布于 2021-03-14 16:38:31 浏览:1187
订阅该版
[tocm] **开发环境:** RT-Thread版本:4.0.3 操作系统:Windows 10 RT-Thread Studio版本:2.0.0 开发板MCU:AB5301A ## 2.1全彩LED简介 大家常的LED都是单色的,控制一端的高低电平即可控制LED的亮灭。全彩LED就是可以通过RGB三种基本LED组合多种色彩的LED,当然还有一种RGBW 四基色的全彩LED。全彩LED分为**共阳极和共阴极**两种。蓝讯AB32VG1的板子是共阳的。 ![60BoGt.png](https://oss-club.rt-thread.org/uploads/20220714/c19cf0660ae1dec97f3880f3a9252309c1c543de.png) 全彩LED的控制有两种方式:**一种是直接通过三个引脚直接控制,另外一种是通过SM16703、WS2811、TM1829等驱动芯片进行控制**。本文采用直接控制的方式,但要想获得更多颜色,就需要通过PWM来控制。 ## 2.2简单实现七彩色 ### 2.2.1实验分析 先来看看电路图。 ![60BLqg.png](https://oss-club.rt-thread.org/uploads/20220714/5c41bc15586e35b984f9a847c14837aeff94fd65.png) 这些 LED 灯的阴极都是连接到 AB5301A的 GPIO 引脚,只要我们控制 GPIO 引脚的电平输出状态,即可控制 LED 灯的亮灭。 ### 2.2.2代码实现 关于工程创建,这里就不说了,不懂的上上一章吧。 [开发环境搭与使用 ( RT-Thread Studio)](https://bruceou.blog.csdn.net/article/details/114727331) 七色很简单,就通过控制三个引脚亮灭来组合其中颜色。直接看代码。 ```c /**Includes*********************************************************************/ #include
#include "board.h" /**define***********************************************************************/ #define LED_R "PE.1" #define LED_G "PE.4" #define LED_B "PA.2" /** the macro definition to the led on or off * 1 - off *0 - on */ #define ON PIN_LOW #define OFF PIN_HIGH /** * @brief main * @param None * @retval None */ int main(void) { uint32_t cnt = 0; uint8_t pin_r = rt_pin_get(LED_R); uint8_t pin_g = rt_pin_get(LED_G); uint8_t pin_b = rt_pin_get(LED_B); rt_pin_mode(pin_r, PIN_MODE_OUTPUT); rt_pin_mode(pin_g, PIN_MODE_OUTPUT); rt_pin_mode(pin_b, PIN_MODE_OUTPUT); while (1) { //红 rt_pin_write(pin_r, ON); rt_pin_write(pin_g, OFF); rt_pin_write(pin_b, OFF); rt_thread_mdelay(1000); //绿 rt_pin_write(pin_r, OFF); rt_pin_write(pin_g, ON); rt_pin_write(pin_b, OFF); rt_thread_mdelay(1000); //蓝 rt_pin_write(pin_r, OFF); rt_pin_write(pin_g, OFF); rt_pin_write(pin_b, ON); rt_thread_mdelay(1000); //黄(红+绿) rt_pin_write(pin_r, ON); rt_pin_write(pin_g, ON); rt_pin_write(pin_b, OFF); rt_thread_mdelay(1000); //紫(红+蓝) rt_pin_write(pin_r, ON); rt_pin_write(pin_g, OFF); rt_pin_write(pin_b, ON); rt_thread_mdelay(1000); //青(绿+蓝) rt_pin_write(pin_r, OFF); rt_pin_write(pin_g, ON); rt_pin_write(pin_b, ON); rt_thread_mdelay(1000); //白(红+绿+蓝) rt_pin_write(pin_r, ON); rt_pin_write(pin_g, ON); rt_pin_write(pin_b, ON); rt_thread_mdelay(1000); //黑(全部关闭) rt_pin_write(pin_r, OFF); rt_pin_write(pin_g, OFF); rt_pin_write(pin_b, OFF); rt_thread_mdelay(1000); cnt++; } return 0; } ``` 代码很简单,主要是通过`rt_pin_write()`函数来控制不同LED。 ### 2.2.3实验现象 编译完成后,通过`Downloader`下载程序,即可看到不同七色光依次出现。 ## 2.3 PWM 控制全彩LED ### 2.3.1实验分析 在正式讲解之前,先来说说什么是PWM。**PWM(Pulse Width Modulation , 脉冲宽度调制) 是一种对模拟信号电平进行数字编码的方法,通过不同频率的脉冲使用方波的占空比用来对一个具体模拟信号的电平进行编码,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替所需要波形的设备**。 ![60Bjaj.png](https://oss-club.rt-thread.org/uploads/20220714/9752d29b1b333441661b53f48245fcc1a71d6045.png) 如上图所示,就是PWM 原理示意图,假定定时器工作模式为向上计数,当计数值小于阈值时,则输出一种电平状态,比如高电平,当计数值大于阈值时则输出相反的电平状态,比如低电平。当计数值达到最大值是,计数器从0开始重新计数,又回到最初的电平状态。高电平持续时间(脉冲宽度)和周期时间的比值就是占空比,范围为0~100%。上图高电平的持续时间刚好是周期时间的一半,所以占空比为50%。 上一节讲了控制三基色的亮灭实现了七色,这一节通过使用 PWM对R、G、B三个灯进行颜色控制,通过改变三个通道的占空比,三个灯进行颜色的组合,就可以混合成多种不同的颜色。 那么要怎么做呢?其实很简单,也就通过改变电平的占空比使RGB分别显示出不同的色值,然后通过组合显示出想要的颜色。通过PWM和直接控制三基色有啥区别呢,其实没区别,通过PWM控制的颗粒度更细,因此能得到更多的色彩。 值得注意的是,这里要调整LED_R的GPIO,将LED_R接到PA1上,便于后面的控制。 |Name| Type |Function| |--|--|--| |PE4(LED_G) |I/O |SPI0DI-G2
SPI1DI-G6
LPWM0-G1
IISMCLK-G2PE4| |PA1(LED_R) |I/O |SPDIF1
SPI1CLK-G1
TX0-G5
HSTRX-G5
LPWM1-G3
IISDO-G1
PA1| |PA2(LED_B) |I/O |SPI1DI-G1
LPWM2-G3
IISSCLK-G1
PA2| ### 2.2.3代码实现 首先我们需要配置PWM驱动,双击RT-Thread Settings文件,打开 RT-Thread 项目配置界面,勾选PWM驱动,然后保存即可。 ![6rGBrj.png](https://oss-club.rt-thread.org/uploads/20220714/a733344f52537d2a46f3d062904610987828d7b5.png) 接下来需要使能3个LED的PWM。 [![6rGhM4.png](https://oss-club.rt-thread.org/uploads/20220714/c5ceb5f6e27186ad4d17624b32f1fcf1fd0db7d1.png)](https://imgtu.com/i/6rGhM4) 还可以通过env工具来配置。 ![60DPMT.png](https://oss-club.rt-thread.org/uploads/20220714/c763c6163364159b8bd4c0ccfe754ce5c58cd083.png) 也可直接在`rtconfig.h`中直接添加以下宏定义即可。 ![60DFLF.png](https://oss-club.rt-thread.org/uploads/20220714/bf0f0784991cb68d97ad90b567cc2d91fc05b649.png) 如果以上添加成功,编译烧写到开发板,查看设别,可以看到控制3个LED的PWM设备。 ![60DAZ4.png](https://oss-club.rt-thread.org/uploads/20220714/fc012e7824da1f486521415e55a2ae20365a3179.png) 接下来就是下应用代码,在`applications`文件夹下新建文件,添加一个线程任务,然后在任务中操作3个LED。代码如下: ```c /** ****************************************************************************** * @file task.c * @author BruceOu * @version V1.0 * @date 2021-03-12 * @blog https://blog.bruceou.cn/ * @Official Accounts 嵌入式实验楼 * @brief RTT任务 ****************************************************************************** */ /*Includes**********************************************************************/ #include "task.h" #define THREAD_PRIORITY 7 #define THREAD_STACK_SIZE 512 #define THREAD_TIMESLICE 3 #define PWM_DEV_NAME_R "lpwm1" /* PWM设备名称 */ #define PWM_DEV_CHANNEL_R 3 /* PWM通道 */ #define PWM_DEV_NAME_G "lpwm0" /* PWM设备名称 */ #define PWM_DEV_CHANNEL_G 1 /* PWM通道 */ #define PWM_DEV_NAME_B "lpwm2" /* PWM设备名称 */ #define PWM_DEV_CHANNEL_B 3 /* PWM通道 */ struct rt_device_pwm *pwm_dev_r; /* PWM设备句柄 */ struct rt_device_pwm *pwm_dev_g; /* PWM设备句柄 */ struct rt_device_pwm *pwm_dev_b; /* PWM设备句柄 */ static rt_thread_t pwm_led_tid = RT_NULL; /* 线程 pwm_led_thread_entry 的入口函数 */ /** * @brief pwm_led_thread_entry * @param parameter * @retval None */ static void pwm_led_thread_entry(void *parameter) { rt_uint32_t period, pulse_r,pulse_g,pulse_b, dir_r,dir_g,dir_b; period = 655360; /* 周期为0.5ms,单位为纳秒ns */ dir_r = 1; /* PWM脉冲宽度值的增减方向 */ dir_g = 1; dir_b = 1; pulse_r = 0; /* PWM脉冲宽度值,单位为纳秒ns */ pulse_g = 0; pulse_b = 0; rt_uint16_t r,g,b; /* 查找设备 */ pwm_dev_r = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME_R); if (pwm_dev_r == RT_NULL) { rt_kprintf("pwm led r run failed! can't find %s device!\n", PWM_DEV_NAME_G); } pwm_dev_g = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME_G); if (pwm_dev_g == RT_NULL) { rt_kprintf("pwm led g run failed! can't find %s device!\n", PWM_DEV_NAME_G); } pwm_dev_b = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME_B); if (pwm_dev_b == RT_NULL) { rt_kprintf("pwm led b run failed! can't find %s device!\n", PWM_DEV_NAME_B); } /* 设置PWM周期和脉冲宽度默认值 */ rt_pwm_set(pwm_dev_r, PWM_DEV_CHANNEL_R, period, pulse_r); rt_pwm_set(pwm_dev_g, PWM_DEV_CHANNEL_G, period, pulse_g); rt_pwm_set(pwm_dev_b, PWM_DEV_CHANNEL_B, period, pulse_b); /* 使能设备 */ rt_pwm_enable(pwm_dev_r, PWM_DEV_CHANNEL_R); rt_pwm_enable(pwm_dev_g, PWM_DEV_CHANNEL_G); rt_pwm_enable(pwm_dev_b, PWM_DEV_CHANNEL_B); while (1) { for (r =0 ; r < 8; r++) { if (dir_r) { pulse_r += 81920; /* 从0值开始每次增加81920ns */ } else { pulse_r -= 81920; /* 从最大值开始每次减少81920ns */ } if ((pulse_r) >= period) { dir_r = 0; } if (81920 > pulse_r) { dir_r = 1; } /* 设置PWM周期和脉冲宽度 */ rt_pwm_set(pwm_dev_r, PWM_DEV_CHANNEL_R, period, pulse_r); for(g = 0; g < 8; g++) { if (dir_g) { pulse_g += 81920; /* 从0值开始每次增加81920ns */ } else { pulse_g -= 81920; /* 从最大值开始每次减少81920ns */ } if ((pulse_g) >= period) { dir_g = 0; } if (81920 > pulse_g) { dir_g = 1; } rt_pwm_set(pwm_dev_g, PWM_DEV_CHANNEL_G, period, pulse_g); for(b = 0; b < 8; b++) { rt_thread_mdelay(10); if (dir_b) { pulse_b += 81920; /* 从0值开始每次增加81920ns */ } else { pulse_b -= 81920; /* 从最大值开始每次减少81920ns */ } if ((pulse_b) >= period) { dir_b = 0; } if (81920 > pulse_b) { dir_b = 1; } rt_pwm_set(pwm_dev_b, PWM_DEV_CHANNEL_B, period, pulse_b); } } } } } /* 线程初始化*/ int thread_init(void) { /* 创建线程,名称是 pwm_led_thread,入口是 pwm_led_thread*/ pwm_led_tid = rt_thread_create("pwm_led_thread", pwm_led_thread_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); /* 如果获得线程控制块,启动这个线程 */ if (pwm_led_tid != RT_NULL) rt_thread_startup(pwm_led_tid); return 0; } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(thread_init, thread init); ``` 当然啦以上代码还可以优化,有兴趣自行去修改吧。控制PWM主要用到了以下三个函数: ```c rt_device_find() //根据 PWM 设备名称查找设备获取设备句柄 rt_pwm_set() //设置 PWM 周期和脉冲宽度 rt_pwm_enable() //使能 PWM 设备 ``` 代码也很简单,就是通过PWM来控制三个LED的脉宽,从而得到不同的颜色。 [PWM参考地址](https://www.rt-thread.org/document/site/programming-manual/device/pwm/pwm/) ### 2.3.3实验现象 烧写成功后复位,在终端输 `thread_init`。 ![60rZnS.png](https://oss-club.rt-thread.org/uploads/20220714/db98758953efa740963ed9bb1b4c3d76eca0ff02.png) 即可看到LED闪烁出不同的颜色。 ![在这里插入图片描述](https://oss-club.rt-thread.org/uploads/20220714/b97f29640bef3f5f82628ff4bceb30e7260de0a7.gif#pic_center) 当然啦,由于拍摄原因,呈现的效果不是很好。 ------------ ### 欢迎访问我的网站 [BruceOu的哔哩哔哩](https://space.bilibili.com/338944611) [BruceOu的主页](https://www.bruceou.cn/) [BruceOu的博客](https://blog.bruceou.cn/) [BruceOu的CSDN博客](https://blog.csdn.net/bruceoxl) [BruceOu的gitee](https://gitee.com/ouxiaolong/)
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
BruceOu
这家伙很懒,什么也没写!
文章
27
回答
0
被采纳
0
关注TA
发私信
相关文章
1
RT-THREAD在STM32H747平台上移植lwip
2
正点原子miniSTM32开发板读写sdcard
3
反馈rtt串口驱动对低功耗串口lpuart1不兼容的问题
4
Keil MDK 移植 RT-Thread Nano
5
RT1061/1052 带 RTT + LWIP和LPSPI,有什么坑要注意吗?
6
RT thread HID 如何收发数据
7
求一份基于RTT系统封装好的STM32F1系列的FLASH操作程序
8
RT-Thread修改项目名称之后不能下载
9
rt-studio编译c++
10
有木有移植rt-thread(nano)到riscv 32位MCU上
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
812
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部