803|1

253

帖子

3

TA的资源

纯净的硅(初级)

楼主
 

【ST NUCLEO-C031C6开发板测评】使用定时器PWM输出控制RGB LED [复制链接]

一、硬件了解

STM32C031C6的MCU系统架构中,提供了多个定时器:

 

 

这些定时器的具体异同点如下:

 

本篇分享使用定时器PWM输出控制RGB LED,选用了TIM3定时器来进行控制。

TIM3的具体介绍如下:

 

 

该定时器框图如下:

 

 

要单独控制RGB LED的R、G、B,需要3个通道。而TIM3有4个独立通道,所以用来控制没有问题。

 

 

二、RGB LED了解

我使用的RGB LED为5050灯珠的三色全彩LED:

 

 

注意这个上面的灯珠和WS2812B的灯珠看起来一样,但是实际使用不同。

WS2812B的自带IC,一个灯带上的每一颗都可以单独控制。而普通5050灯带需要统一行动。

 

三、zephyr对定时器的支持

从zephyr/../modules/hal/stm32/dts/st/c0/stm32c031c(4-6)tx-pinctrl.dtsi中,可以了解到tim3定时器关联的pinctrl信息:

 

因为PA5已经被 zephyr/boards/arm/nucleo_c031c6/nucleo_c031c6.dts 配置中默认的TIM1对应的PWM占用了,

 

 

所以我选择了TIM3中所对应的PA6、PA7、PB0通道来做为RGB的控制,对应开发板上的如下引脚:

 

 

 

不过,zephyr/boards/arm/nucleo_c031c6/nucleo_c031c6.dts中没有TIM3的配置,所以需要自己添加一个配置文件:nucleo_c031c6.overlay

/ {
	mypwmleds {
		compatible = "pwm-leds";

		my_red_pwm_led: my_led_pwm_0 {
			pwms = <&pwm3 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
			label = "Red PWM LED";
		};
		my_green_pwm_led: my_led_pwm_1 {
			pwms = <&pwm3 2 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
			label = "Green PWM LED";
		};
		my_blue_pwm_led: my_led_pwm_2 {
			pwms = <&pwm3 3 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
			label = "Blue PWM LED";
		};
	};

    aliases {
		my-pwm-led0 = &my_green_pwm_led;
		my-pwm-led1 = &my_blue_pwm_led;
		my-pwm-led2 = &my_red_pwm_led;
		my-green-pwm-led = &my_green_pwm_led;
		my-blue-pwm-led = &my_blue_pwm_led;
		my-red-pwm-led = &my_red_pwm_led;
    };

};

&timers3 {
	st,prescaler = <10000>;
	status = "okay";
	pwm3: pwm {
		pinctrl-0 = <&tim3_ch1_pa6 &tim3_ch2_pa7 &tim3_ch3_pb0>;
		pinctrl-names = "default";
		status = "okay";
	};
};

 

四、代码编写

在 zephyr/samples/basic/rgb_led,有单个RGB LED的控制代码:

/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * [url=home.php?mod=space&uid=1307177]@File[/url] Sample app to demonstrate PWM-based RGB LED control
 */

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/device.h>
#include <zephyr/drivers/pwm.h>

static const struct pwm_dt_spec red_pwm_led =
	PWM_DT_SPEC_GET(DT_ALIAS(red_pwm_led));
static const struct pwm_dt_spec green_pwm_led =
	PWM_DT_SPEC_GET(DT_ALIAS(green_pwm_led));
static const struct pwm_dt_spec blue_pwm_led =
	PWM_DT_SPEC_GET(DT_ALIAS(blue_pwm_led));

#define STEP_SIZE PWM_USEC(2000)

int main(void)
{
	uint32_t pulse_red, pulse_green, pulse_blue; /* pulse widths */
	int ret;

	printk("PWM-based RGB LED control\n");

	if (!pwm_is_ready_dt(&red_pwm_led) ||
	    !pwm_is_ready_dt(&green_pwm_led) ||
	    !pwm_is_ready_dt(&blue_pwm_led)) {
		printk("Error: one or more PWM devices not ready\n");
		return 0;
	}

	while (1) {
		for (pulse_red = 0U; pulse_red <= red_pwm_led.period;
		     pulse_red += STEP_SIZE) {
			ret = pwm_set_pulse_dt(&red_pwm_led, pulse_red);
			if (ret != 0) {
				printk("Error %d: red write failed\n", ret);
				return 0;
			}

			for (pulse_green = 0U;
			     pulse_green <= green_pwm_led.period;
			     pulse_green += STEP_SIZE) {
				ret = pwm_set_pulse_dt(&green_pwm_led,
						       pulse_green);
				if (ret != 0) {
					printk("Error %d: green write failed\n",
					       ret);
					return 0;
				}

				for (pulse_blue = 0U;
				     pulse_blue <= blue_pwm_led.period;
				     pulse_blue += STEP_SIZE) {
					ret = pwm_set_pulse_dt(&blue_pwm_led,
							       pulse_blue);
					if (ret != 0) {
						printk("Error %d: "
						       "blue write failed\n",
						       ret);
						return 0;
					}
					k_sleep(K_SECONDS(1));
				}
			}
		}
	}
	return 0;
}

 

参考上述代码,编写控制3个LED的代码:

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/device.h>
#include <zephyr/drivers/pwm.h>

static const struct pwm_dt_spec red_pwm_led =
	PWM_DT_SPEC_GET(DT_ALIAS(my_red_pwm_led));
static const struct pwm_dt_spec green_pwm_led =
	PWM_DT_SPEC_GET(DT_ALIAS(my_green_pwm_led));
static const struct pwm_dt_spec blue_pwm_led =
	PWM_DT_SPEC_GET(DT_ALIAS(my_blue_pwm_led));

// 延时时间
#define DELAY_TIME_MS 500U

// pulse基础值
#define PULSE_BASE 0x80000
// 亮度最大值
#define BRIGHTNESS_MAX 32

int main(void)
{
	uint32_t pulse_red, pulse_green, pulse_blue; /* pulse widths */
	int ret;

	printk("PWM-based RGB LED control\n");

	if (!pwm_is_ready_dt(&red_pwm_led) ||
	    !pwm_is_ready_dt(&green_pwm_led) ||
	    !pwm_is_ready_dt(&blue_pwm_led)) {
		printk("Error: one or more PWM devices not ready\n");
		return 0;
	}

	printk("period(r,g,b)=(%d,%d,%d)\n", red_pwm_led.period, green_pwm_led.period, blue_pwm_led.period);
	uint32_t color_pulse_list[8][3] = {
		{0, 0, 0},
		{1, 0, 0},
		{0, 1, 0},
		{0, 0, 1},
		{1, 1, 0},
		{0, 1, 1},
		{1, 0, 1},
		{1, 1, 1}
	};

	uint32_t i = 0;
	uint32_t brightness = 1;
	while (1) {
		pulse_red = color_pulse_list[i][0] * PULSE_BASE * brightness;
		pulse_green = color_pulse_list[i][1] * PULSE_BASE * brightness;
		pulse_blue = color_pulse_list[i][2] * PULSE_BASE * brightness;

		ret = pwm_set_pulse_dt(&red_pwm_led, pulse_red);
		if (ret != 0) {
			printk("Error %d: red write failed\n", ret);
			return 0;
		}

		ret = pwm_set_pulse_dt(&green_pwm_led,
					pulse_green);
		if (ret != 0) {
			printk("Error %d: green write failed\n",
					ret);
			return 0;
		}

		ret = pwm_set_pulse_dt(&blue_pwm_led,
						pulse_blue);
		if (ret != 0) {
			printk("Error %d: "
					"blue write failed\n",
					ret);
			return 0;
		}

		printk("pulse(r,g,b)=(%04X,%04X,%04X), brightness=%d\n", pulse_red, pulse_green, pulse_blue, brightness);
		k_sleep(K_MSEC(DELAY_TIME_MS));

		i++;
		if (i == 8) {
			i = 0;
			brightness++;
			if(brightness>BRIGHTNESS_MAX) {
				brightness = 1;
			}
		}
#endif
	}
	return 0;
}

上述代码中,使用 my_red_pwm_led、my_green_pwm_led、my_blue_pwm_led来对应dts定义的R、G、B控制设备。

然后定义了 color_pulse_list ,用于设置R、G、B的点亮情况:

	uint32_t color_pulse_list[8][3] = {
		{0, 0, 0},
		{1, 0, 0},
		{0, 1, 0},
		{0, 0, 1},
		{1, 1, 0},
		{0, 1, 1},
		{1, 0, 1},
		{1, 1, 1}
	};

然后在循环中,依次使用上述配置,点亮R、G、B中的1个或者多个,并使用brightness来控制亮度。

 

五、输出结果

将之前的nucleo_c031c6.overlay保存到 zephyr/samples/basic/rgb_led/boards/下,然后编译烧录到开发板,就能输出结果:

 

RGB LED也会随之跟着变换颜色:

4621_1708266556

 

六、参考资料

此帖出自stm32/stm8论坛

最新回复

注意这个上面的灯珠和WS2812B的灯珠看起来一样,但是实际使用不同,什么原因   详情 回复 发表于 2024-2-20 07:44
点赞 关注
 

回复
举报

2万

帖子

341

TA的资源

版主

沙发
 

注意这个上面的灯珠和WS2812B的灯珠看起来一样,但是实际使用不同,什么原因

此帖出自stm32/stm8论坛
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表