引脚编号 | 引脚名称 | 说明 |
---|
1 | DO | 控制数据信号输出端 | 2 | DI | 控制数据信号输入端 | 3 | VCC | 控制电路电源正极 | 4 | NC | 空脚 | 5 | VDD | LED电源正极 | 6 | VSS | 电源负极 |
数据时序图 0,1码的高低电平时间:
电平 | 描述 | 时间 |
---|
T0H | 0 码, 高电平时间 | 0.35us ±150ns | T0L | 0 码, 低电平时间 | 0.8us ±150ns | T1H | 1 码, 高电平时间 | 0.7us ±150ns | T1L | 1 码, 低电平时间 | 0.6us ±150ns | RES | 低电平时间 | 约 >50us |
TH+TL=1.25μs±600ns
[单片机框架] [onewire] 利用单线协议来点亮WS2812X 模拟IO 兼容带OS
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "app_led.h"
#include "onewire.h"
#include "os_api.h"
#include "rgb_hsv.h"
#include "business_gpio.h"
#include "business_function.h"
#define BYTE_0(n) ((uint8_t)((n) & (uint8_t)0xFF))
#define BYTE_1(n) ((uint8_t)(BYTE_0((n) >> (uint8_t)8)))
#define BYTE_2(n) ((uint8_t)(BYTE_0((n) >> (uint8_t)16)))
#define BYTE_3(n) ((uint8_t)(BYTE_0((n) >> (uint8_t)24)))
#if BS_APP_LED_WS2812_DRIVEN_MODE
#if BS_WS2812_CH0_EN
static void timer_ws2812_0_light_control(void const *arg);
#endif
#if BS_WS2812_CH1_EN
static void timer_ws2812_1_light_control(void const *arg);
#endif
#if BS_WS2812_CH2_EN
static void timer_ws2812_2_light_control(void const *arg);
#endif
#if BS_WS2812_CH3_EN
static void timer_ws2812_3_light_control(void const *arg);
#endif
#endif
static bool g_app_led_init = false;
typedef struct
{
app_led_id_t led_id;
app_led_type_t type;
bool level_logic;
char *timer_id;
uint32_t period_max;
uint16_t cycle_time;
uint32_t period;
uint8_t temp_dir;
uint16_t temp_times;
} app_led_t;
#if BS_APP_LED_WS2812_DRIVEN_MODE
#if BS_WS2812_CH0_EN
os_timer_def(ws2812_0, timer_ws2812_0_light_control);
app_led_t app_led_ws2812_0 = {APP_LED_ID_0, LED_TYPE_OFF, 0, NULL, BS_WS2812_CH0_NUM, 0, 0, 1, 0};
#endif
#if BS_WS2812_CH1_EN
os_timer_def(ws2812_1, timer_ws2812_1_light_control);
app_led_t app_led_ws2812_1 = {APP_LED_ID_1, LED_TYPE_OFF, 0, NULL, BS_WS2812_CH1_NUM, 0, 0, 1, 0};
#endif
#if BS_WS2812_CH2_EN
os_timer_def(ws2812_2, timer_ws2812_2_light_control);
app_led_t app_led_ws2812_2 = {APP_LED_ID_2, LED_TYPE_OFF, 0, NULL, BS_WS2812_CH2_NUM, 0, 0, 1, 0};
#endif
#if BS_WS2812_CH3_EN
os_timer_def(ws2812_3, timer_ws2812_3_light_control);
app_led_t app_led_ws2812_3 = {APP_LED_ID_3, LED_TYPE_OFF, 0, NULL, BS_WS2812_CH3_NUM, 0, 0, 1, 0};
#endif
#endif
static void led_type_off(app_led_t *app_led)
{
uint8_t temp[3] = {0, 0 ,0};
onewire_send_data(app_led->led_id, temp, 3);
}
static void led_type_light(app_led_t *app_led)
{
uint8_t temp[3] = {BYTE_1(app_led->period), BYTE_2(app_led->period), BYTE_0(app_led->period)};
onewire_send_data(app_led->led_id, temp, 3);
}
static void led_type_breath(app_led_t *app_led)
{
if (app_led->type != LED_TYPE_BREATH)
{
return;
}
uint16_t time = 0;
uint8_t temp[3];
float h, s, v;
if (app_led->temp_dir == 0)
{
app_led->temp_times++;
}
else if (app_led->temp_dir == 1)
{
app_led->temp_dir = 2;
time = 255;
goto end;
}
else if (app_led->temp_dir == 2)
{
app_led->temp_times--;
}
if (app_led->temp_times == 257)
{
app_led->temp_dir = 1;
}
else if (app_led->temp_times == 0)
{
app_led->temp_dir = 0;
time = 255;
goto end;
}
time = app_led->cycle_time;
end:
rgb2hsv(BYTE_2(app_led->period), BYTE_1(app_led->period), BYTE_0(app_led->period), &h, &s, &v);
v = (float)(app_led->temp_times) / 256;
hsv2rgb(h, s, v, &temp[1], &temp[0], &temp[2]);
onewire_send_data(app_led->led_id, temp, 3);
os_timer_start((os_timer_id)(app_led->timer_id), time);
}
static void led_type_twinkle(app_led_t *app_led)
{
if (app_led->type != LED_TYPE_TWINKLE)
{
return;
}
if (app_led->temp_dir == 0)
{
led_type_light(app_led);
app_led->temp_dir = 1;
}
else
{
led_type_off(app_led);
app_led->temp_dir = 0;
}
os_timer_start((os_timer_id)(app_led->timer_id), app_led->cycle_time);
}
static void led_type_sos(app_led_t *app_led)
{
if (app_led->type != LED_TYPE_SOS)
{
return;
}
uint16_t time = 0;
if (app_led->temp_dir == 0)
{
app_led->temp_dir = 1;
led_type_light(app_led);
time = 100;
goto end;
}
else if (app_led->temp_dir == 1)
{
app_led->temp_times++;
app_led->temp_dir = 0;
if (app_led->temp_times > 2)
{
app_led->temp_times = 0;
app_led->temp_dir = 2;
}
led_type_off(app_led);
time = 200;
goto end;
}
else if (app_led->temp_dir == 2)
{
app_led->temp_dir = 3;
led_type_light(app_led);
time = 800;
goto end;
}
else if (app_led->temp_dir == 3)
{
app_led->temp_times++;
app_led->temp_dir = 2;
if (app_led->temp_times > 2)
{
app_led->temp_times = 0;
app_led->temp_dir = 0;
}
led_type_off(app_led);
time = 200;
goto end;
}
else
{
app_led->temp_dir = 0;
}
end:
os_timer_start((os_timer_id)(app_led->timer_id), time);
}
static void led_type_red_blue_twinkle(app_led_t *app_led)
{
if (app_led->type != LED_TYPE_RED_BLUE_TWINKLE)
{
return;
}
uint16_t time = 0;
if (app_led->temp_dir == 0)
{
app_led->temp_dir = 1;
app_led->period = COLOR_RED;
led_type_light(app_led);
time = 150;
goto end;
}
else if (app_led->temp_dir == 1)
{
app_led->temp_times++;
app_led->temp_dir = 0;
if (app_led->temp_times > 2)
{
app_led->temp_times = 0;
app_led->temp_dir = 2;
}
app_led->period = COLOR_BLUE;
led_type_light(app_led);
time = 150;
goto end;
}
else if (app_led->temp_dir == 2)
{
app_led->temp_dir = 3;
app_led->period = COLOR_RED;
led_type_light(app_led);
time = 500;
goto end;
}
else if (app_led->temp_dir == 3)
{
app_led->temp_times++;
app_led->temp_dir = 2;
if (app_led->temp_times > 2)
{
app_led->temp_times = 0;
app_led->temp_dir = 0;
}
app_led->period = COLOR_BLUE;
led_type_light(app_led);
time = 500;
goto end;
}
else
{
time = 1000;
app_led->temp_dir = 0;
app_led->temp_times = 0;
led_type_off(app_led);
}
end:
os_timer_start((os_timer_id)(app_led->timer_id), time);
}
#if BS_APP_LED_WS2812_DRIVEN_MODE
#if BS_WS2812_CH0_EN
static void timer_ws2812_0_light_control(void const *arg)
{
if (app_led_ws2812_0.type == LED_TYPE_OFF)
{
led_type_light(&app_led_ws2812_0);
}
else if (app_led_ws2812_0.type == LED_TYPE_LIGHT)
{
led_type_light(&app_led_ws2812_0);
}
else if (app_led_ws2812_0.type == LED_TYPE_BREATH)
{
led_type_breath(&app_led_ws2812_0);
}
else if (app_led_ws2812_0.type == LED_TYPE_TWINKLE)
{
led_type_twinkle(&app_led_ws2812_0);
}
else if (app_led_ws2812_0.type == LED_TYPE_SOS)
{
led_type_sos(&app_led_ws2812_0);
}
else if (app_led_ws2812_0.type == LED_TYPE_RED_BLUE_TWINKLE)
{
led_type_red_blue_twinkle(&app_led_ws2812_0);
}
}
#endif
#if BS_WS2812_CH1_EN
static void timer_ws2812_1_light_control(void const *arg)
{
if (app_led_ws2812_1.type == LED_TYPE_OFF)
{
led_type_light(&app_led_ws2812_1);
}
else if (app_led_ws2812_1.type == LED_TYPE_LIGHT)
{
led_type_light(&app_led_ws2812_1);
}
else if (app_led_ws2812_1.type == LED_TYPE_BREATH)
{
led_type_breath(&app_led_ws2812_1);
}
else if (app_led_ws2812_1.type == LED_TYPE_TWINKLE)
{
led_type_twinkle(&app_led_ws2812_1);
}
else if (app_led_ws2812_1.type == LED_TYPE_SOS)
{
led_type_sos(&app_led_ws2812_1);
}
else if (app_led_ws2812_1.type == LED_TYPE_RISE_SLOWLY)
{
led_type_rise_slowly(&app_led_ws2812_1);
}
else if (app_led_ws2812_1.type == LED_TYPE_FALL_SLOWLY)
{
led_type_fall_slowly(&app_led_ws2812_1);
}
}
#endif
#if BS_WS2812_CH2_EN
static void timer_ws2812_2_light_control(void const *arg)
{
if (app_led_ws2812_2.type == LED_TYPE_OFF)
{
led_type_light(&app_led_ws2812_2);
}
else if (app_led_ws2812_2.type == LED_TYPE_LIGHT)
{
led_type_light(&app_led_ws2812_2);
}
else if (app_led_ws2812_2.type == LED_TYPE_BREATH)
{
led_type_breath(&app_led_ws2812_2);
}
else if (app_led_ws2812_2.type == LED_TYPE_TWINKLE)
{
led_type_twinkle(&app_led_ws2812_2);
}
else if (app_led_ws2812_2.type == LED_TYPE_SOS)
{
led_type_sos(&app_led_ws2812_2);
}
else if (app_led_ws2812_2.type == LED_TYPE_RISE_SLOWLY)
{
led_type_rise_slowly(&app_led_ws2812_2);
}
else if (app_led_ws2812_2.type == LED_TYPE_FALL_SLOWLY)
{
led_type_fall_slowly(&app_led_ws2812_2);
}
}
#endif
#if BS_WS2812_CH3_EN
static void timer_ws2812_3_light_control(void const *arg)
{
if (app_led_ws2812_3.type == LED_TYPE_OFF)
{
led_type_light(&app_led_ws2812_3);
}
else if (app_led_ws2812_3.type == LED_TYPE_LIGHT)
{
led_type_light(&app_led_ws2812_3);
}
else if (app_led_ws2812_3.type == LED_TYPE_BREATH)
{
led_type_breath(&app_led_ws2812_3);
}
else if (app_led_ws2812_3.type == LED_TYPE_TWINKLE)
{
led_type_twinkle(&app_led_ws2812_3);
}
else if (app_led_ws2812_3.type == LED_TYPE_SOS)
{
led_type_sos(&app_led_ws2812_3);
}
else if (app_led_ws2812_3.type == LED_TYPE_RISE_SLOWLY)
{
led_type_rise_slowly(&app_led_ws2812_3);
}
else if (app_led_ws2812_3.type == LED_TYPE_FALL_SLOWLY)
{
led_type_fall_slowly(&app_led_ws2812_3);
}
}
#endif
#endif
static app_led_t *get_app_led(app_led_id_t led_id)
{
if (led_id == APP_LED_ID_0)
{
#if BS_APP_LED_WS2812_DRIVEN_MODE && BS_WS2812_CH0_EN
return &app_led_ws2812_0;
#else
return NULL;
#endif
}
#if BS_APP_LED_WS2812_DRIVEN_MODE && BS_WS2812_CH1_EN
else if (led_id == APP_LED_ID_1)
{
return &app_led_ws2812_1;
}
#endif
#if BS_APP_LED_WS2812_DRIVEN_MODE && BS_WS2812_CH2_EN
else if (led_id == APP_LED_ID_2)
{
return &app_led_ws2812_2;
}
#endif
#if BS_APP_LED_WS2812_DRIVEN_MODE && BS_WS2812_CH3_EN
else if (led_id == APP_LED_ID_3)
{
return &app_led_ws2812_3;
}
#endif
return NULL;
}
void led_ws2812_init(void)
{
if (g_app_led_init)
{
return;
}
g_app_led_init = true;
uint32_t timer_err_ret = 0;
#if BS_APP_LED_WS2812_DRIVEN_MODE
#if BS_WS2812_CH0_EN
app_led_ws2812_0.timer_id = (char *)os_timer_create(os_timer(ws2812_0), OS_TIMER_ONCE, &timer_err_ret);
#endif
#if BS_WS2812_CH1_EN
app_led_ws2812_1.timer_id = (char *)os_timer_create(os_timer(ws2812_1), OS_TIMER_ONCE, &timer_err_ret);
#endif
#if BS_WS2812_CH2_EN
app_led_ws2812_2.timer_id = (char *)os_timer_create(os_timer(ws2812_2), OS_TIMER_ONCE, &timer_err_ret);
#endif
#if BS_WS2812_CH3_EN
app_led_ws2812_3.timer_id = (char *)os_timer_create(os_timer(ws2812_3), OS_TIMER_ONCE, &timer_err_ret);
#endif
#endif
}
uint16_t app_led_ws2812_get_current_period(app_led_id_t led_id)
{
app_led_t *app_led = get_app_led(led_id);
return app_led->period;
}
app_led_type_t app_led_ws2812_get_current_type(app_led_id_t led_id)
{
app_led_t *app_led = get_app_led(led_id);
return app_led->type;
}
bool app_led_ws2812_ioctl(app_led_id_t led_id, app_led_type_t type, uint16_t cycle_time, uint32_t period)
{
app_led_t *led_info = NULL;
led_info = get_app_led(led_id);
if (led_info == NULL)
{
return false;
}
led_info->temp_dir = 0;
led_info->temp_times = 0;
led_info->cycle_time = cycle_time;
led_info->type = type;
if (type == LED_TYPE_OFF)
{
led_info->period = 0;
}
else
{
led_info->period = period;
}
os_timer_start((os_timer_id)(led_info->timer_id), 1);
return true;
}
|