#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#define DATA_PIN GPIO_NUM_27
#define LATCH_PIN GPIO_NUM_14
#define CLOCK_PIN GPIO_NUM_2
#define OUTPUT_EN GPIO_NUM_17
#define DIP_PIN_0 GPIO_NUM_13
#define DIP_PIN_1 GPIO_NUM_12
#define DIP_PIN_2 GPIO_NUM_26
#define DIP_PIN_3 GPIO_NUM_25
#define DIP_PIN_4 GPIO_NUM_33
#define POLL_MS 50
static const gpio_num_t DIP_PINS[5] = {
DIP_PIN_0, DIP_PIN_1, DIP_PIN_2, DIP_PIN_3, DIP_PIN_4
};
void write_to_595(int data) {
for (int i = 7; i >= 0; i--) { // MSB先,bit7→Q0,bit0→Q7
gpio_set_level(DATA_PIN, (data >> i) & 1);
gpio_set_level(CLOCK_PIN, 1);
gpio_set_level(CLOCK_PIN, 0);
}
gpio_set_level(LATCH_PIN, 1);
gpio_set_level(LATCH_PIN, 0);
vTaskDelay(1 / portTICK_PERIOD_MS);
}
int read_dip(void) {
int val = 0;
for (int i = 0; i < 5; i++) {
if (gpio_get_level(DIP_PINS[i])) {
val |= (1 << i);
}
}
return val;
}
// G1: Q3=1(bit3), addr Q2Q1Q0=000~111 → 0x08~0x0F
// G2: Q4=1(bit4), addr Q2Q1Q0=000~111 → 0x10~0x17
// G3: Q5=1(bit5), addr Q2Q1Q0=000~111 → 0x20~0x27
// G4: Q6=1(bit6), addr Q2Q1Q0=000~111 → 0x40~0x47
static const int UID_TABLE[28] = {
// G1 (val 1~8): 只有4个灯 led_g1_4~7不存在,你的G1组有8个LED
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
// G2 (val 9~16)
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
// G3 (val 17~24)
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
// G4 (val 25~28): 只有4个
0x40, 0x41, 0x42, 0x43
};
// DIP val(0~31) → uid,线性映射到28个有效槽位
// val=0 → 全灭
// val=1~4 → G1 的4个灯 (uid 4~7)
// val=5~12 → G2 的8个灯 (uid 8~15)
// val=13~20 → G3 的8个灯 (uid 16~23)
// val=21~28 → G4 的8个灯 (uid 32~39)
// val=29~31 → 越界,全灭
int dip_to_uid(int val) {
if (val == 0 || val > 28) return 0;
return UID_TABLE[val - 1];
}
void uid_to_grp_addr(int uid, int *grp, int *addr) {
*addr = uid & 0x07;
if (uid & 0x08) *grp = 1; // Q3=1
else if (uid & 0x10) *grp = 2; // Q4=1
else if (uid & 0x20) *grp = 3; // Q5=1
else if (uid & 0x40) *grp = 4; // Q6=1
else *grp = -1;
}
void app_main(void) {
gpio_set_direction(DATA_PIN, GPIO_MODE_OUTPUT);
gpio_set_direction(LATCH_PIN, GPIO_MODE_OUTPUT);
gpio_set_direction(CLOCK_PIN, GPIO_MODE_OUTPUT);
gpio_set_direction(OUTPUT_EN, GPIO_MODE_OUTPUT);
gpio_set_level(OUTPUT_EN, 0);
for (int i = 0; i < 5; i++) {
gpio_set_direction(DIP_PINS[i], GPIO_MODE_INPUT);
gpio_pullup_en(DIP_PINS[i]);
}
// 扫描测试:遍历全部28个有效 uid
printf("开始扫描测试 (共%d个有效位置)...\n", 28);
for (int i = 0; i < 28; i++) {
int uid = UID_TABLE[i];
write_to_595(uid);
int grp, addr;
uid_to_grp_addr(uid, &grp, &addr);
printf("slot=%2d uid=%2d binary=%d%d%d%d%d%d 应亮: G%d led_g%d_%d\n",
i + 1, uid,
(uid>>5)&1,(uid>>4)&1,(uid>>3)&1,
(uid>>2)&1,(uid>>1)&1,(uid>>0)&1,
grp, grp, addr);
vTaskDelay(800 / portTICK_PERIOD_MS);
}
write_to_595(0);
printf("扫描完成\n\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
printf("DIP Decoder Ready (val 1~28 有效, 29~31越界全灭)\n");
int last_val = -1;
while (true) {
int raw = read_dip();
int val = (~raw) & 0x1F;
if (val != last_val) {
last_val = val;
int uid = dip_to_uid(val);
write_to_595(uid);
if (uid == 0) {
printf("RAW=%2d val=%2d → 全灭\n", raw, val);
} else {
int grp, addr;
uid_to_grp_addr(uid, &grp, &addr);
printf("RAW=%2d val=%2d uid=%2d → G%d led_g%d_%d\n",
raw, val, uid, grp, grp, addr);
}
}
vTaskDelay(POLL_MS / portTICK_PERIOD_MS);
}
}