[i=s] 本帖最后由 sujingliang 于 2025-4-1 21:14 编辑 [/i]
一、RGB灯控制APP
找了一个app可以通过BLE控制RGB灯
其BLE控制RGB命令格式如下:
0x4e |
0x4f |
0x30 |
0x4 |
0xc5 |
0x0 |
0xff |
0xff |
0xf1 |
固定格式 |
固定格式 |
固定格式 |
固定格式 |
RED |
GREEN |
BLUE |
ALPHA |
未知 |
命令共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
#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实现函数
#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中修改如下
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;
}
其中增加了:
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改为和配置一致

进入界面后,可以操作了。
操作后串口输出:
