ws2812x数据传输时间
T0H 0 码,高电平时间 220ns~380ns
T0L 0 码,低电平时间 580ns~1.6µs
T1H 1 码,高电平时间 580ns~1.6µs
T1L 1 码,低电平时间 220ns~420µs
RES 帧单位,低电平时间 >280µs 以上
对于ARM_M平台 @24M
1个NOP:(1/24000000)100010001000==41.67ns
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
5个NOP 41.675 = 208.35ns (加上代码执行时间,勉强达到ws2812x标准)
对于n76e003平台 @16M
1个nop 占用87ns
while(1) 占用194ns
函数调用 占用570ns
注:
- 点亮白灯或混色造成灯光无改变,则需要检测供电是否充足,接外部电池则满足需求。
- 多个灯光出现颜色不对,则先检测供电问题。
- 这个例子是按照24M写的,其他频率请重新计算
[单片机框架] [app_led] [WS2812x] 利用软定时器实现WS2812x闪烁和呼吸等灯光模式
伪代码:
temp[0] = 0xF0;
temp[1] = 0x3B;
temp[2] = 0x0F;
onewire_send_data(0, temp, 3);
/********************************************************************************
* @file onewire.c
* @author jianqiang.xue
* @Version V1.0.0
* @Date 2020-12-07
* @brief 可用于ws2812x等
ws2812x数据传输时间
T0H 0 码,高电平时间 220ns~380ns
T0L 0 码,低电平时间 580ns~1.6µs
T1H 1 码,高电平时间 580ns~1.6µs
T1L 1 码,低电平时间 220ns~420µs
RES 帧单位,低电平时间 >280µs 以上
对于ARM_M平台 @16M
1个NOP:(1/24000000)*1000*1000*1000==41.67ns
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
对于n76e003平台 @16M
1个nop 占用87ns
while(1) 占用194ns
函数调用 占用570ns
注:1.如果点亮白灯或混色造成灯光无改变,则需要检测供电是否充足,接外部电池则满足需求。
2. 如果多个灯光出现颜色不对,则先检测供电问题。
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "bsp_gpio.h"
#include "sys_api.h"
#include "os_api.h"
#include "onewire.h"
#include "business_gpio.h"
#include "business_function.h"
/* Private Define ------------------------------------------------------------*/
#if 1
#define T0_BIT_SIGNAL(GPIOX, PIN) \
GPIOX->ODSET=PIN; \
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
GPIOX->ODCLR=PIN; \
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
#define T1_BIT_SIGNAL(GPIOX, PIN) \
GPIOX->ODSET=PIN; \
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
GPIOX->ODCLR=PIN; \
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
#define RESET_SIGNAL(GPIOX, PIN) \
bsp_gpio_set_pin(GPIOX, PIN, BSP_GPIO_PIN_RESET); \
delay(500); \
#endif
/* Private Function Prototypes -----------------------------------------------*/
static void delay(uint16_t cnt)
{
while (cnt--)
{
__NOP();
}
}
void onewire_init(void)
{
#if BS_WS2812_CH0_EN
BS_ONEWIRE_CH0_GPIO_CLK_ENABLE();
bsp_gpio_init_output(ONEWIRE_CH0_PORT, ONEWIRE_CH0_PIN, BSP_GPIO_PIN_OUT_PP);
bsp_gpio_set_pin(ONEWIRE_CH0_PORT, ONEWIRE_CH0_PIN, BSP_GPIO_PIN_RESET);
#endif
#if BS_WS2812_CH1_EN
BS_ONEWIRE_CH1_GPIO_CLK_ENABLE();
bsp_gpio_init_output(ONEWIRE_CH1_PORT, ONEWIRE_CH1_PIN, BSP_GPIO_PIN_OUT_PP);
bsp_gpio_set_pin(ONEWIRE_CH1_PORT, ONEWIRE_CH1_PIN, BSP_GPIO_PIN_RESET);
#endif
#if BS_WS2812_CH2_EN
BS_ONEWIRE_CH2_GPIO_CLK_ENABLE();
bsp_gpio_init_output(ONEWIRE_CH2_PORT, ONEWIRE_CH2_PIN, BSP_GPIO_PIN_OUT_PP);
bsp_gpio_set_pin(ONEWIRE_CH2_PORT, ONEWIRE_CH2_PIN, BSP_GPIO_PIN_RESET);
#endif
#if BS_WS2812_CH3_EN
BS_ONEWIRE_CH3_GPIO_CLK_ENABLE();
bsp_gpio_init_output(ONEWIRE_CH3_PORT, ONEWIRE_CH3_PIN, BSP_GPIO_PIN_OUT_PP);
bsp_gpio_set_pin(ONEWIRE_CH3_PORT, ONEWIRE_CH3_PIN, BSP_GPIO_PIN_RESET);
#endif
}
void onewire_deinit(void)
{
#if BS_WS2812_CH0_EN
bsp_gpio_deinit(ONEWIRE_CH0_PORT, ONEWIRE_CH0_PIN);
#endif
#if BS_WS2812_CH1_EN
bsp_gpio_deinit(ONEWIRE_CH1_PORT, ONEWIRE_CH1_PIN);
#endif
#if BS_WS2812_CH2_EN
bsp_gpio_deinit(ONEWIRE_CH2_PORT, ONEWIRE_CH2_PIN);
#endif
#if BS_WS2812_CH3_EN
bsp_gpio_deinit(ONEWIRE_CH3_PORT, ONEWIRE_CH3_PIN);
#endif
}
bool flag = false;
void onewire_send_data(uint8_t ch, uint8_t *data, uint8_t len)
{
uint8_t temp = 0;
if (ch == 0)
{
#if BS_WS2812_CH0_EN
if (flag)
{
return;
}
flag = true;
uint32_t val = SysTick->CTRL;
SysTick->CTRL &= ~0x00000003; // 禁用 SysTick 中断
sys_disable_irq();
RESET_SIGNAL(ONEWIRE_CH0_PORT, ONEWIRE_CH0_PIN);
for (uint8_t n = 0; n < BS_WS2812_CH0_NUM; n++)
{
for (uint8_t i = 0; i < len; i++)
{
temp = data[i];
for (uint8_t j = 0; j < 8; j++)
{
if (temp & 0x80)
{
T1_BIT_SIGNAL(ONEWIRE_CH0_PORT, ONEWIRE_CH0_PIN)
}
else
{
T0_BIT_SIGNAL(ONEWIRE_CH0_PORT, ONEWIRE_CH0_PIN);
}
temp <<= 1;
}
}
}
RESET_SIGNAL(ONEWIRE_CH0_PORT, ONEWIRE_CH0_PIN);
SysTick->CTRL = val;
sys_enable_irq();
flag = false;
#endif
}
}
/********************************************************************************
* @file onewire.h
* @author jianqiang.xue
* @Version V1.0.0
* @Date 2020-11-23
* @brief NULL
********************************************************************************/
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
/* Public Function Prototypes ------------------------------------------------*/
void onewire_init(void);
void onewire_deinit(void);
void onewire_send_data(uint8_t ch, uint8_t *data, uint8_t len);
#endif /* __ONEWIRE_H */