打印

W806控制WS2812彩灯

[复制链接]
579|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1764376441|  楼主 | 2021-12-2 16:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
利用W806通过寄存器控制IO口来控制WS2812彩灯。
/****************联盛德W806寄存器操作******************/
/****************参考资料:QQ:774145445****************/
/****************功能:WS2812点亮**********************/
/****************快手:共同学习stm8*********************/
/****************AboutCDK 2.10.1***********************/
#include <stdio.h>
#include "wm_hal.h"

static volatile unsigned int key_flag = 1;
/**************************************************/
#define                GPIOB_DATA                        (*(volatile unsigned int*)(0x40011400+0x0000))
#define                GPIOB_DATA_EN                (*(volatile unsigned int*)(0x40011400+0X0004))
#define                GPIOB_DIR                        (*(volatile unsigned int*)(0x40011400+0X0008))

#define                wei0                0b0000000000000001
#define                wei1                0b0000000000000010
#define                wei2                0b0000000000000100
#define                wei3                0b0000000000001000

#define                wei4                0b0000000000010000
#define                wei5                0b0000000000100000
#define                wei6                0b0000000001000000
#define                wei7                0b0000000010000000

#define                wei8                0b0000000100000000
#define                wei9                0b0000001000000000
#define                wei10                0b0000010000000000
#define                wei11                0b0000100000000000

#define                wei12                0b0001000000000000
#define                wei13                0b0010000000000000
#define                wei14                0b0100000000000000
#define                wei15                0b1000000000000000

#define                led1_h                GPIOB_DATA|=wei0 // led1灯灭(高电平)
#define                led1_l                GPIOB_DATA&=~wei0 // led1灯亮(低电平)

#define                led2_h                GPIOB_DATA|=wei1
#define                led2_l                GPIOB_DATA&=~wei1

#define                led3_h                GPIOB_DATA|=wei2
#define                led3_l                GPIOB_DATA&=~wei2

#define                WS2812                (wei5)  //PB5引脚
#define                WS2812L                GPIOB_DATA&=~WS2812
#define                WS2812H                GPIOB_DATA|= WS2812
/**************************************************/

void delay_300ns(void); // 延时100ns
void delay_300us(void); // 延时300us
void RGB_LED_Write0(void); // 写0
void RGB_LED_Write1(void); // 写1
void RGB_LED_Reset(void);
void RGB_LED_Write_Byte(unsigned char byte); // 写一个字节(8bit)
void RGB_LED_Write_24Bits(unsigned char green,unsigned char red,unsigned char blue); // 写24个字节(绿、红、蓝三色)

void WS2812_Clear();
void WS2812_ChangeRGB1(unsigned char num);
void WS2812_Light1(unsigned char num,unsigned char R,unsigned char G,unsigned char B,unsigned char L);
void WS2812_Breath1(unsigned char num,unsigned char R,unsigned char G,unsigned char B);

/**************************************************/
int main(void)
{
        unsigned char n;
        /**************************************************/
        GPIOB_DATA_EN                |=WS2812;
        GPIOB_DIR                        |=WS2812;
        GPIOB_DATA                        |=WS2812;
        /**************************************************/
        SystemClock_Config(CPU_CLK_160M); // 设置系统时钟
        printf("enter main\r\n");
        while (1)
        {
                WS2812_ChangeRGB1(18); // 特效1
//                HAL_Delay(500);
//                WS2812_Clear();
//                HAL_Delay(500);
                //WS2812_Breath1(18,243,98,243);
        }
        return 0;
}


/*******************************************************/
/*
* 函数名:RGB_LED_Write0
* 输入参数:空
* 功能:发送0
* 发送0对时许要求很严格,需要测试delay_100ns()是否满足时序*/
void RGB_LED_Write0(void)
{
        WS2812H; // 灭
        delay_300ns();
       
        WS2812L; // 亮
        delay_300ns();
        delay_300ns();
        delay_300ns();
}
/*
* 函数名:RGB_LED_Write1
* 输入参数:空
* 功能:发送1
* 发送1对时许要求很严格,需要测试delay_100ns()是否满足时序*/
void RGB_LED_Write1(void)
{
        WS2812H; // 灭
        delay_300ns();
        delay_300ns();
        delay_300ns();
       
        WS2812L; // 亮
        delay_300ns();
}
/*
* 函数名:RGB_LED_Reset
* 输入参数:空
* 功能:停止 Reset*/
void RGB_LED_Reset(void)
{
        WS2812L; // 灭
        delay_300us();
}
/*
* 函数名:RGB_LED_Write_Byte
* 输入参数:byte
* 功能:按照WS2812协议写一个字节*/
void RGB_LED_Write_Byte(unsigned char byte)
{
        unsigned char i=0;

        for(i=0;i<8;i++)
                {
                        if(byte&0x80)
                                {
                                        RGB_LED_Write1();
                        }
                        else
                                {
                                        RGB_LED_Write0();
                        }
                byte <<= 1;
        }
}
/*
* 函数名:RGB_LED_Write_24Bits
* 输入参数:red\green\blue三色素
* 功能:设置颜色*/
void RGB_LED_Write_24Bits(unsigned char red,unsigned char green,unsigned char blue)
{
        RGB_LED_Write_Byte(green);
        RGB_LED_Write_Byte(red);
        RGB_LED_Write_Byte(blue);
}

/*
* 函数名:WS2812_Clear()
* 输入值:空
* 功能:熄灭WS2812灯,默认熄灭255个*/
void WS2812_Clear()
{
        unsigned char i = 0;
        for(i=0;i<255;i++)
        {
                RGB_LED_Write_24Bits(0,0,0);
        }
}
/*
* 函数名:WS2812_ChangeRGB1
* 输入值:num 彩色灯的个数
* 功能:红、绿、蓝三种颜色每隔500ms交替变换*/
void WS2812_ChangeRGB1(unsigned char num)
{
        unsigned char i = 0;
        for(i=0;i<num;i++)
        {
                RGB_LED_Write_24Bits(255,0,0); // 红色
               
        }
        RGB_LED_Reset(); // 停止
        HAL_Delay(500); // 延时500ms
        for(i=0;i<num;i++)
        {
                RGB_LED_Write_24Bits(0, 255, 0); // 绿色
               
        }
        RGB_LED_Reset();
        HAL_Delay(500);
        for(i=0;i<num;i++)
        {
                RGB_LED_Write_24Bits(0, 0, 255); // 蓝色
               
        }
        RGB_LED_Reset();
        HAL_Delay(500);
        for(i=0;i<num;i++)
        {
                RGB_LED_Write_24Bits(255, 237, 45); // 黄色
               
        }
        RGB_LED_Reset(); // 停止
        HAL_Delay(500); // 延时500ms
        for(i=0;i<num;i++)
        {
                RGB_LED_Write_24Bits(235, 20, 255); // 紫色
               
        }
        RGB_LED_Reset(); // 停止
        HAL_Delay(500); // 延时500ms
        for(i=0;i<num;i++)
        {
                RGB_LED_Write_24Bits(56, 255, 238); // 淡蓝色
               
        }
        RGB_LED_Reset(); // 停止
        HAL_Delay(500); // 延时500ms
}
/*
* 函数名:WS2812_Light1
* 输入值:num 彩色灯的个数 R\G\B                  L(亮度0~100)
* 功能:设置亮度*/
void WS2812_Light1(unsigned char num,unsigned char R,unsigned char G,unsigned char B,unsigned char L)
{
        unsigned char i = 0;
        R = (unsigned char) R*L/100; // 此处运算量较大,有可能造成不满足时许问题
        G = (unsigned char) G*L/100; // 此处运算量较大,有可能造成不满足时许问题
        B = (unsigned char) B*L/100; // 此处运算量较大,有可能造成不满足时许问题
        for(i=0;i<num;i++)
        {
                RGB_LED_Write_24Bits(R,G,B);
        }
        RGB_LED_Reset();
}
/*
* 函数名:WS2812_Breath1
* 输入值:num 彩色灯的个数 R\G\B
* 功能:呼吸灯
* 需要调用WS2812_Light1函数,WS2812_Light1函数运算量较大,有可能超出时序*/
void WS2812_Breath1(unsigned char num,unsigned char R,unsigned char G,unsigned char B)
{
        unsigned char i = 0;
       
        for(i=0;i<100;i++)
        {
                WS2812_Light1(num,R,G,B,i);
                HAL_Delay(20);
        }
        for(i=100;i>0;i--)
        {
                WS2812_Light1(num,R,G,B,i);
                HAL_Delay(20);
        }
}


/**************************************************/
/*
* 函数名:delay_300ns
* 输入值:空
* 功能:ns级延时,延时300ns
* 该函数误差较大,需要自己用示波器调整,修改for循环此时可以该表延时时间
* 尝试过用定时器延时,可惜本人技术不精,用定时器只能做到us级延时*/
void delay_300ns(void) // 延时300ns
{
        unsigned char i=0;
        for(i=10;i>0;i--)
                __NOP();
}
/*
* 函数名:delay_300us
* 输入值:空
* 功能:us级延时,延时300us
* 该函数误差较大,需要自己用示波器调整,修改for循环此时可以该表延时时间
* WS2812对此函数对精度要求较低*/
void delay_300us(void) // 延时300us
{
        uint32_t i=0;
       
        for (i = 0; i < (45 * 5); i++)
        {
                __NOP();
        }
}
/**************************************************/
/**************************************************/
/**************************************************/
/**************************************************/


W806_WS2812.zip

2.54 KB

W806通过寄存器控制IO口控制WS2812

使用特权

评论回复

相关帖子

沙发
34af9uc| | 2021-12-2 16:57 | 只看该作者
给你点一个赞

使用特权

评论回复
板凳
34af9uc| | 2021-12-5 13:31 | 只看该作者
这个不错,赞

使用特权

评论回复
发新帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

粉丝