通过74HC595移位寄存器改变LED强度

发布于 2025-01-16 22:44:01 字数 3127 浏览 4 评论 0原文

我目前正在开发一个项目,需要使用两个级联移位寄存器 74HC595 控制 13 个白色 LED 和一个 RGB LED。 我在 windows 上使用 SAMD21 XPLAINED PRO 板 (µC samd21j18a) 和 ATMEL Studio 作为 IDE。

目前,我基本上使用 SPI 来完成此操作(我在 ATMEL Start 上定义了项目的大部分参数)。

#include <atmel_start.h>

#define message_size    2

bool RgbColors[7][3] = {
    {1, 0, 0}, //Red
    {0, 1, 0}, //Green
    {0, 0, 1}, //Blue
    {1, 1, 0}, //Yellow
    {1, 0, 1}, //Pink
    {0, 1, 1}, //Cyan
    {1, 1, 1}, //White
};

uint8_t spi_transfer_array[message_size];
struct spi_xfer spi_driver_xfer;

// Send a 16 bits message through SPI
void spi_16bits_transfer(uint16_t data);
// Control a frame of 13 white LEDs and 1 RGB LED
void turn_led_model_on(uint8_t led, bool red, bool green, bool blue);


int main(void)
{
    atmel_start_init();
    spi_m_sync_enable(&SPI_0);
    
    uint8_t i = 0;
    bool red = 0;
    bool green = 0;
    bool blue = 0;
    
    while (1) {
        
        // Test
        for (uint8_t led = 0; led <= 13; led++){
            
            // RGB modulation
            if (i <= 6){
                red = RgbColors[i][0];
                green = RgbColors[i][1];
                blue = RgbColors[i][2];
                i++;
            }
            else {
                i = 0;
            }
            
            turn_led_model_on(led, red, green, blue);
            delay_ms(200);
        }
        
        for (uint8_t led = 0; led <= 13; led++){
            
            // RGB modulation
            if (i <= 6){
                red = RgbColors[i][0];
                green = RgbColors[i][1];
                blue = RgbColors[i][2];
                i++;
            }
            else {
                i = 0;
            }
            
            turn_led_model_on(13 - led, red, green, blue);
            delay_ms(200);
        }
    }
}


void spi_16bits_transfer(uint16_t data){
    spi_transfer_array[0] = ~data >> 8;
    spi_transfer_array[1] = ~data & 0xFF;
    
    spi_driver_xfer.txbuf = spi_transfer_array;
    spi_driver_xfer.size = message_size;
    
    gpio_set_pin_level(EN_pin, false);
    gpio_set_pin_level(SPI_SS, false);
    spi_m_sync_transfer(&SPI_0, &spi_driver_xfer);
    gpio_set_pin_level(SPI_SS, true);
    gpio_set_pin_level(EN_pin, true);
    delay_ms(1);
    gpio_set_pin_level(EN_pin, false);
}


void turn_led_model_on(uint8_t led, bool red, bool green, bool blue){
    if (led > 13) led = 13;
    
    uint16_t mask = 0;
    
    if (led > 0){
        for (uint8_t i = 1; i <= led; i++){
            mask |= (1 << (led - i));
        }
    }
    
    mask |= (red << 13);
    mask |= (green << 14);
    mask |= (blue << 15);
    
    spi_16bits_transfer(mask);
}

我目前面临的问题是我希望能够改变光强度,但我不知道如何使用 74HC595 做到这一点,并且我不知道是否可以使用 做到这一点>SPI。目标不仅是改变白色 LED 的强度,最重要的是获得更多选择 RGB LED 颜色的可能性(目前我只有 7 种可能性)。

我感觉可以使用定时器创建一种PWM来选择LED的点亮频率,从而修改它们的强度,但我没能做到。

另外,我不知道是否可以独立改变每个 LED 的强度(这就是我需要的 RGB LED)。

谢谢

I'm currently working on a project for which I need to control 13 white LEDs and one RGB LED with two shift registers 74HC595 in cascade.
I work on windows with a SAMD21 XPLAINED PRO board (µC samd21j18a) and ATMEL Studio as IDE.

For the moment I manage to do it quite basically using SPI (I define most of my project's parameters on ATMEL Start).

#include <atmel_start.h>

#define message_size    2

bool RgbColors[7][3] = {
    {1, 0, 0}, //Red
    {0, 1, 0}, //Green
    {0, 0, 1}, //Blue
    {1, 1, 0}, //Yellow
    {1, 0, 1}, //Pink
    {0, 1, 1}, //Cyan
    {1, 1, 1}, //White
};

uint8_t spi_transfer_array[message_size];
struct spi_xfer spi_driver_xfer;

// Send a 16 bits message through SPI
void spi_16bits_transfer(uint16_t data);
// Control a frame of 13 white LEDs and 1 RGB LED
void turn_led_model_on(uint8_t led, bool red, bool green, bool blue);


int main(void)
{
    atmel_start_init();
    spi_m_sync_enable(&SPI_0);
    
    uint8_t i = 0;
    bool red = 0;
    bool green = 0;
    bool blue = 0;
    
    while (1) {
        
        // Test
        for (uint8_t led = 0; led <= 13; led++){
            
            // RGB modulation
            if (i <= 6){
                red = RgbColors[i][0];
                green = RgbColors[i][1];
                blue = RgbColors[i][2];
                i++;
            }
            else {
                i = 0;
            }
            
            turn_led_model_on(led, red, green, blue);
            delay_ms(200);
        }
        
        for (uint8_t led = 0; led <= 13; led++){
            
            // RGB modulation
            if (i <= 6){
                red = RgbColors[i][0];
                green = RgbColors[i][1];
                blue = RgbColors[i][2];
                i++;
            }
            else {
                i = 0;
            }
            
            turn_led_model_on(13 - led, red, green, blue);
            delay_ms(200);
        }
    }
}


void spi_16bits_transfer(uint16_t data){
    spi_transfer_array[0] = ~data >> 8;
    spi_transfer_array[1] = ~data & 0xFF;
    
    spi_driver_xfer.txbuf = spi_transfer_array;
    spi_driver_xfer.size = message_size;
    
    gpio_set_pin_level(EN_pin, false);
    gpio_set_pin_level(SPI_SS, false);
    spi_m_sync_transfer(&SPI_0, &spi_driver_xfer);
    gpio_set_pin_level(SPI_SS, true);
    gpio_set_pin_level(EN_pin, true);
    delay_ms(1);
    gpio_set_pin_level(EN_pin, false);
}


void turn_led_model_on(uint8_t led, bool red, bool green, bool blue){
    if (led > 13) led = 13;
    
    uint16_t mask = 0;
    
    if (led > 0){
        for (uint8_t i = 1; i <= led; i++){
            mask |= (1 << (led - i));
        }
    }
    
    mask |= (red << 13);
    mask |= (green << 14);
    mask |= (blue << 15);
    
    spi_16bits_transfer(mask);
}

The problem I am currently facing is that I want to be able to change light intensity but I don't know how to do it with 74HC595 and I don't know if I can do it using SPI. The goal is not only to change white LEDs intensity but most of all to get more possibility for the choice of the color of the RGB LED (for the moment I only have 7 possibilities).

I have the feeling it's possible to create a kind of PWM using a timer to choose the frequency of lighting of the LEDs and thus to modify their intensity, but I don't manage to do it.

Also, I don't know if it is possible to change the intensity of each LED independently (that's what I would need for the RGB LED).

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

难理解 2025-01-23 22:44:01

好的,我正在开发一个效果非常好的软件解决方案。

我创建了一个“硬写”值表,它是一种固定 LED 频率的仪表。

我的仪表包含 26 个值(前 13 个值是“0”,后 13 个值是“1”)。我根据我想要的强度浏览包含 13 个值的样本的仪表(样本中的值从仪表 [强度] 到仪表 [强度 + 12])。

(当强度为 0 时,我的样本仅包含 13 个 0。当强度为 1 时,我的样本仅包含 12 个 0 和 1 个 1。)。
根据这些值,我打开或关闭 LED 来调节强度。

#include <atmel_start.h>

#define message_size    2

uint8_t spi_transfer_array[message_size];
struct spi_xfer spi_driver_xfer;

void spi_16bits_transfer(uint16_t data);
void turn_led_model_on(uint8_t led, bool red, bool green, bool blue);

bool gauge[26] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};

int main(void)
{
    atmel_start_init();
    spi_m_sync_enable(&SPI_0);
    
    uint8_t intencity = 13; // The highest this value is, the brightest the light will be (from 0 to 13)
    uint8_t cycles = 3; 
    
    while (1) {
        
        // Test to create wave effect with LED
        // Increase
        for (uint8_t j = 0; j <= intencity; j++){
            for (uint8_t k = 0; k <= cycles; k++){
                for (uint8_t i = j; i < (j + 13); i++){
                    if (gauge[i]){
                        turn_led_model_on(13, 1, 0, 0);
                    }
                    else {
                        turn_led_model_on(0, 0, 0, 0);
                    }
                }
            }
        }
        
        // Decrease
        for (uint8_t j = 0; j <= intencity; j++){
            for (uint8_t k = 0; k <= cycles; k++){
                for (uint8_t i = j; i < (j + 13); i++){
                    if (!gauge[i]){
                        turn_led_model_on(13, 1, 0, 0);
                    }
                    else {
                        turn_led_model_on(0, 0, 0, 0);
                    }
                }
            }
        }
        
    }
    
}


void spi_16bits_transfer(uint16_t data){
    spi_transfer_array[0] = ~data >> 8;
    spi_transfer_array[1] = ~data & 0xFF;
    
    spi_driver_xfer.txbuf = spi_transfer_array;
    spi_driver_xfer.size = message_size;
    
    gpio_set_pin_level(EN_pin, false);
    gpio_set_pin_level(SPI_SS, false);
    spi_m_sync_transfer(&SPI_0, &spi_driver_xfer);
    gpio_set_pin_level(SPI_SS, true);
    gpio_set_pin_level(EN_pin, true);
    delay_ms(1);
    gpio_set_pin_level(EN_pin, false);
}


void turn_led_model_on(uint8_t led, bool red, bool green, bool blue){
    if (led > 13) led = 13;
    
    uint16_t mask = 0;
    
    if (led > 0){
        for (uint8_t i = 1; i <= led; i++){
            mask |= (1 << (led - i));
        }
    }
    
    mask |= (red << 13);
    mask |= (green << 14);
    mask |= (blue << 15);
    
    spi_16bits_transfer(mask);
}

我仍然需要对其进行研究才能将其用于 RGB 调制,但现在应该不会那么复杂。

Ok, I'm working on a software solution that works really good.

I create an "hard written" values table which is a kind of gauge to fix the LED frequency.

My gauge contains 26 values (the first 13 values are "0" and the last 13 values are "1"). I browse this gauge with a sample of 13 values depending on the intensity I want (the values in my sample start at gauge[intensity] to gauge[intensity + 12]).

(When intensity is 0, my sample contains only 13 times 0. When intensity is 1, my sample contains only 12 times 0 and one 1.).
Based on these values, I turn on or off my LEDs to modulate the intensity.

#include <atmel_start.h>

#define message_size    2

uint8_t spi_transfer_array[message_size];
struct spi_xfer spi_driver_xfer;

void spi_16bits_transfer(uint16_t data);
void turn_led_model_on(uint8_t led, bool red, bool green, bool blue);

bool gauge[26] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};

int main(void)
{
    atmel_start_init();
    spi_m_sync_enable(&SPI_0);
    
    uint8_t intencity = 13; // The highest this value is, the brightest the light will be (from 0 to 13)
    uint8_t cycles = 3; 
    
    while (1) {
        
        // Test to create wave effect with LED
        // Increase
        for (uint8_t j = 0; j <= intencity; j++){
            for (uint8_t k = 0; k <= cycles; k++){
                for (uint8_t i = j; i < (j + 13); i++){
                    if (gauge[i]){
                        turn_led_model_on(13, 1, 0, 0);
                    }
                    else {
                        turn_led_model_on(0, 0, 0, 0);
                    }
                }
            }
        }
        
        // Decrease
        for (uint8_t j = 0; j <= intencity; j++){
            for (uint8_t k = 0; k <= cycles; k++){
                for (uint8_t i = j; i < (j + 13); i++){
                    if (!gauge[i]){
                        turn_led_model_on(13, 1, 0, 0);
                    }
                    else {
                        turn_led_model_on(0, 0, 0, 0);
                    }
                }
            }
        }
        
    }
    
}


void spi_16bits_transfer(uint16_t data){
    spi_transfer_array[0] = ~data >> 8;
    spi_transfer_array[1] = ~data & 0xFF;
    
    spi_driver_xfer.txbuf = spi_transfer_array;
    spi_driver_xfer.size = message_size;
    
    gpio_set_pin_level(EN_pin, false);
    gpio_set_pin_level(SPI_SS, false);
    spi_m_sync_transfer(&SPI_0, &spi_driver_xfer);
    gpio_set_pin_level(SPI_SS, true);
    gpio_set_pin_level(EN_pin, true);
    delay_ms(1);
    gpio_set_pin_level(EN_pin, false);
}


void turn_led_model_on(uint8_t led, bool red, bool green, bool blue){
    if (led > 13) led = 13;
    
    uint16_t mask = 0;
    
    if (led > 0){
        for (uint8_t i = 1; i <= led; i++){
            mask |= (1 << (led - i));
        }
    }
    
    mask |= (red << 13);
    mask |= (green << 14);
    mask |= (blue << 15);
    
    spi_16bits_transfer(mask);
}

I still have to work on it to use it for RGB modulation but it shouldn't be that complex now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文