Skip to content

由 sujingliang 贡献,Ai-Thinker 进行整理

【Ai-WB2评测】BLE+PWM控制RGB灯

一、RGB灯控制APP 找了一个app可以通过BLE控制RGB灯

其BLE控制RGB命令格式如下:

0x4e0x4f0x300x40xc50x00xff0xff0xf1
固定格式固定格式固定格式固定格式REDGREENBLUEALPHA未知

命令共9个字节 头四字节固定为0x4e 0x4f 0x30 0x4 ,可以用来判断后面是控制RGB的指令 第5个字节为RED 第6个字节为GREEN 第7个字节为BLUE 第8个字节为ALPHA 第9个字节没弄明白是什么,没有使用

二、编写BLE从机程序 以applications/bluetooth/ble_slave为模板。

1、增加PWM控制RGB灯代码 pwmled.h

📜 点击展开完整代码
java
#ifndef __PWM_LED_H__
#define __PWM_LED_H__

// pwmled.h

#include <bl602.h>
#include <bl602_gpio.h>
#include <bl_pwm.h>

BL_Err_Type
PWM_Smart_Configure2
(PWM_CH_ID_Type ch, uint16_t clkDiv, uint16_t period,uint16_t threshold2)
;

void

pwm_led_init
(
void
)
;

void

pwm_led_set
(uint8_t red,uint8_t green,uint8_t blue)
;

void

rgb_control
(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
;
#endif

BL_Err_Type PWM_Smart_Configure2(PWM_CH_ID_Type ch, uint16_t clkDiv, uint16_t period,uint16_t threshold2); 配置PWM参数

void pwm_led_init(void); 初始化PWM

void pwm_led_set(uint8_t red,uint8_t green,uint8_t blue); 设置3个RGB LED

void rgb_control(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha); 加上alpha控制3个RGB LED

pwmled.c实现函数

📜 点击展开完整代码
java
#include <FreeRTOS.h>
#include <task.h>
#include <blog.h>
#include <bl602.h>
#include <bl602_gpio.h>
#include <bl602_glb.h>
#include <bl_pwm.h>
#include
"pwmled.h"

#define
PWM_Get_Channel_Reg
(ch)
  (PWM_BASE+PWM_CHANNEL_OFFSET+(ch)*
0x20
)
#define
PWM_STOP_TIMEOUT_COUNT

(
160
*
1000
)

GLB_GPIO_Cfg_Type cfg[
3
] = {
    {
        .drive =
0
,
        .smtCtrl =
1
,
        .gpioMode = GPIO_MODE_OUTPUT,
        .pullType = GPIO_PULL_DOWN,
        .gpioPin =
14
,
/// red

        .gpioFun =
8
,
    },
    {
        .drive =
0
,
        .smtCtrl =
1
,
        .gpioMode = GPIO_MODE_OUTPUT,
        .pullType = GPIO_PULL_DOWN,
        .gpioPin =
17
,
/// green

        .gpioFun =
8
,
    },
    {
        .drive =
0
,
        .smtCtrl =
1
,
        .gpioMode = GPIO_MODE_OUTPUT,
        .pullType = GPIO_PULL_DOWN,
        .gpioPin =
3
,
/// blue

        .gpioFun =
8
,
    },
};

/// @brief Copy from PWM_Smart_Configure. Use Bus Clock instead of External Crystal Clock for PWM Timer

/// @param ch PWM Channel

/// @param clkDiv PWM clock divider

/// @param period PWM period

/// @param threshold2

/// @return

BL_Err_Type
PWM_Smart_Configure2
(PWM_CH_ID_Type ch, uint16_t clkDiv, uint16_t period,uint16_t threshold2)

{
    uint32_t tmpVal;

uint32_t

timeoutCnt

=
 PWM_STOP_TIMEOUT_COUNT;

/* Get channel register */

uint32_t

PWMx

=
 PWM_Get_Channel_Reg(ch);

    tmpVal = BL_RD_REG(PWMx, PWM_CONFIG);

// if(BL_GET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL) != PWM_CLK_XCLK){

if
(BL_GET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL) != PWM_CLK_BCLK){
        BL_WR_REG(PWMx, PWM_CONFIG, BL_SET_REG_BIT(tmpVal, PWM_STOP_EN));

while
(!BL_IS_REG_BIT_SET(BL_RD_REG(PWMx, PWM_CONFIG), PWM_STS_TOP)){
            timeoutCnt--;

if
(timeoutCnt ==
0
){

return
 TIMEOUT;
            }
        }

// tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL, PWM_CLK_XCLK);

        tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL, PWM_CLK_BCLK);
    }
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_OUT_INV, PWM_POL_NORMAL);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_STOP_MODE, PWM_STOP_GRACEFUL);
    BL_WR_REG(PWMx, PWM_CONFIG, tmpVal);

/* Config pwm division */

    BL_WR_REG(PWMx, PWM_CLKDIV, clkDiv);

/* Config pwm period and duty */

    BL_WR_REG(PWMx, PWM_PERIOD, period);
    BL_WR_REG(PWMx, PWM_THRE1,
0
);
    BL_WR_REG(PWMx, PWM_THRE2, threshold2);

return
 SUCCESS;
}

void

pwm_led_init
(
void
)

{

for
 (
int

i

=

0
; i <
3
; i++) {
        GLB_GPIO_Init(cfg + i);

PWM_CH_ID_Type

ch

=
 cfg[i].gpioPin % PWM_CH_MAX;
        PWM_Channel_Disable(ch);
    }
}

void

pwm_led_set
(uint8_t red,uint8_t green,uint8_t blue)

{
    PWM_Smart_Configure2(
2
,
80
,
255
, green);
    PWM_Channel_Enable(
2
);

    PWM_Smart_Configure2(
3
,
80
,
255
, blue);
    PWM_Channel_Enable(
3
);

    PWM_Smart_Configure2(
4
,
80
,
255
, red);
    PWM_Channel_Enable(
4
);

}

void

rgb_control
(uint8_t red, uint8_t green, uint8_t blue,  uint8_t alpha)

{
    uint8_t t_red,t_green,t_blue;

// 应用透明度/亮度

    t_red = red*alpha/
255
;
    t_green = green*alpha/
255
;
    t_blue = blue*alpha/
255
;

    pwm_led_set(t_red,t_green,t_blue);
}

2、ble_interface.c中修改如下

📜 点击展开完整代码
java
static
 ssize_t
ble_uuid1_write_val
(struct bt_conn *conn, const struct bt_gatt_attr *attr,
                                   const
void
 *buf, u16_t len, u16_t offset,
                                   u8_t flags)

{
    uint8_t *recv_buffer;
    recv_buffer = pvPortMalloc(sizeof(uint8_t) * len);
    memcpy(recv_buffer, buf, len);
    printf(
"recv ble data len: %d\r\n"
, len);

if
(recv_buffer[
0
]==
0x4e
&&recv_buffer[
1
]==
0x4f
&&recv_buffer[
2
]==
0x30
&&recv_buffer[
3
]==
0x04
){

//pwm_led_set(recv_buffer[4],recv_buffer[5],recv_buffer[6]);

        rgb_control(recv_buffer[
4
],recv_buffer[
5
],recv_buffer[
6
],recv_buffer[
7
]);
        printf(
"pwm_led_set\r\n"
);
    }

for
 (
size_t

i

=

0
; i < len; i++)
    {
        printf(
"0x%x "
, recv_buffer[i]);
    }
    printf(
"\r\n"
);
    vPortFree(recv_buffer);

return
 len;
}

其中增加了:

📜 点击展开完整代码
java
if
(recv_buffer[
0
]==
0x4e
&&recv_buffer[
1
]==
0x4f
&&recv_buffer[
2
]==
0x30
&&recv_buffer[
3
]==
0x04
){

//pwm_led_set(recv_buffer[4],recv_buffer[5],recv_buffer[6]);

        rgb_control(recv_buffer[
4
],recv_buffer[
5
],recv_buffer[
6
],recv_buffer[
7
]);
        printf(
"pwm_led_set\r\n"
);
    }

即当UUID1收到写入值后,判断头4个字节是否为0x4e 0x4f 0x30 0x4, 如果是,调用rgb_control控制RGB灯改变颜色。

三、运行 手机上运行该APP

搜索到BLE,并连接

将uuid改为和配置一致

进入界面后,可以操作了。

操作后串口输出:

Released under the MIT License. Build Time 2026-09-11 14:52:23