通过74HC595移位寄存器改变LED亮度
Change LED intencity through 74HC595 shift register
我目前正在进行一个项目,我需要控制 13 个白色 LED 和一个 RGB LED,其中两个 shift registers 74HC595
级联。
我使用 SAMD21 XPLAINED PRO
电路板 (µC samd21j18a
) 和 ATMEL Studio
作为 IDE.
在 windows
上工作
目前我基本上是使用 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)。
谢谢
好的,我正在研究一个非常有效的软件解决方案。
我创建了一个“硬写”值table,这是一种固定 LED 频率的仪表。
我的仪表包含 26 个值(前 13 个值是“0”,后 13 个值是“1”)。根据我想要的强度,我用 13 个值的样本浏览了这个仪表(我的样本中的值从 gauge[intensity] 到 gauge[intensity + 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 调制,但现在不应该那么复杂。
我目前正在进行一个项目,我需要控制 13 个白色 LED 和一个 RGB LED,其中两个 shift registers 74HC595
级联。
我使用 SAMD21 XPLAINED PRO
电路板 (µC samd21j18a
) 和 ATMEL Studio
作为 IDE.
windows
上工作
目前我基本上是使用 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)。
谢谢
好的,我正在研究一个非常有效的软件解决方案。
我创建了一个“硬写”值table,这是一种固定 LED 频率的仪表。
我的仪表包含 26 个值(前 13 个值是“0”,后 13 个值是“1”)。根据我想要的强度,我用 13 个值的样本浏览了这个仪表(我的样本中的值从 gauge[intensity] 到 gauge[intensity + 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 调制,但现在不应该那么复杂。