Files
ldc1612_cmake_vscode/Src/dlpc3421.c
2025-08-25 10:26:43 +08:00

187 lines
5.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/***************************************************************************
* DLPC3421 全功能驱动模板GD32E230
* 作者xxx
* 版本v1.0
* 说明:
* 1. 覆盖上电→初始化→正常投影→关机→异常复位全部状态
* 2. 提供精简 APIdlp_on / dlp_off / dlp_set_current / dlp_set_pattern
* 3. 所有 I²C 操作带超时重试、CRC 打印、断言保护
* 4. 支持在线调试dlp_dump_regs()
***************************************************************************/
#include "gd32e23x.h"
#include "dlpc3421.h"
#include <string.h>
#include <stdbool.h>
/* -------------------- 用户可调宏 -------------------- */
#define DLPC_I2C_ADDR 0x1B /* 7-bit 地址 */
#define I2C_TIMEOUT_MS 100
#define DLPC_BOOT_DELAY_MS 200
#define MAX_RETRY 3
/* -------------------- 内部宏 ------------------------ */
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
/* -------------------- I²C 底层封装 ------------------ */
static int i2c_write(uint8_t dev, const uint8_t *tx, uint16_t len)
{
/* 你的 i2c 发送实现,这里用伪代码占位 */
/* 返回 0 成功,-1 失败 */
return 0;
}
static int i2c_read(uint8_t dev, uint8_t *rx, uint16_t len)
{
/* 你的 i2c 接收实现,这里用伪代码占位 */
return 0;
}
/* -------------------- 寄存器 / 指令表 --------------- */
typedef enum {
CMD_WRITE_ENABLE = 0x50, /* 1B bit0=1 打开手动电流 / CAIC */
CMD_LED_ENABLE = 0x52, /* 1B bit0=R,bit1=G,bit2=B */
CMD_LED_CURRENT_MANUAL = 0x54, /* 3B R/G/B mA */
CMD_MAX_CURRENT_LIMIT = 0x5C, /* 3B R/G/B max */
CMD_PATTERN_CONTROL = 0x60, /* 2B 模式/触发 */
CMD_STATUS = 0xD0, /* 1B bit0=Busy */
CMD_CHIP_ID = 0xD2, /* 2B 返回 0x34 0x21 */
CMD_SOFTWARE_RESET = 0xF0 /* 1B 0x01 软复位 */
} dlp_cmd_t;
/* -------------------- 内部工具函数 ------------------ */
static bool dlp_wait_not_busy(uint32_t timeout_ms)
{
uint8_t cmd = CMD_STATUS;
uint8_t sts = 0x01;
while (timeout_ms--) {
if (i2c_write(DLPC_I2C_ADDR, &cmd, 1) == 0 &&
i2c_read (DLPC_I2C_ADDR, &sts, 1) == 0) {
if (!(sts & 0x01))
return true;
}
delay_1ms(1);
}
return false;
}
static int dlp_send_cmd(uint8_t cmd, const uint8_t *data, uint8_t len)
{
uint8_t buf[32];
buf[0] = cmd;
if (len) memcpy(&buf[1], data, len);
for (int i = 0; i < MAX_RETRY; ++i) {
if (i2c_write(DLPC_I2C_ADDR, buf, len+1) == 0 &&
dlp_wait_not_busy(I2C_TIMEOUT_MS))
return 0;
}
return -1;
}
/* -------------------- 对外 API ---------------------- */
/* 1. 芯片识别 */
bool dlp_probe(void)
{
uint8_t cmd = CMD_CHIP_ID;
uint8_t id[2] = {0};
if (i2c_write(DLPC_I2C_ADDR, &cmd, 1) == 0 &&
i2c_read(DLPC_I2C_ADDR, id, 2) == 0) {
return (id[0] == 0x34 && id[1] == 0x21);
}
return false;
}
/* 2. 上电初始化流程(参考 TI 手册 Figure 3-1 */
int dlp_init(void)
{
/* Step-1: 上电等待 tPU */
delay_1ms(DLPC_BOOT_DELAY_MS);
if (!dlp_probe()) return -1;
/* Step-2: 设置最大电流限制(可选,按 LED 规格) */
uint8_t max_i[3] = {255, 255, 255};
if (dlp_send_cmd(CMD_MAX_CURRENT_LIMIT, max_i, 3)) return -2;
/* Step-3: 打开手动电流控制 */
uint8_t manual_on = 0x01;
if (dlp_send_cmd(CMD_WRITE_ENABLE, &manual_on, 1)) return -3;
return 0; /* OK */
}
/* 3. 开关光机(含 Busy 轮询) */
void dlp_on(void)
{
uint8_t leds = 0x07; /* RGB ON */
dlp_send_cmd(CMD_LED_ENABLE, &leds, 1);
}
void dlp_off(void)
{
uint8_t leds = 0x00; /* RGB OFF */
dlp_send_cmd(CMD_LED_ENABLE, &leds, 1);
}
/* 4. 手动设置电流 */
void dlp_set_current(uint8_t r, uint8_t g, uint8_t b)
{
uint8_t rgb[3] = {r, g, b};
dlp_send_cmd(CMD_LED_CURRENT_MANUAL, rgb, 3);
}
/* 5. 软件复位(异常恢复用) */
void dlp_reset(void)
{
uint8_t rst = 0x01;
dlp_send_cmd(CMD_SOFTWARE_RESET, &rst, 1);
delay_1ms(DLPC_BOOT_DELAY_MS);
dlp_init(); /* 重新初始化 */
}
/* 6. 打印常用寄存器(调试) */
void dlp_dump_regs(void)
{
uint8_t regs[] = {CMD_STATUS, CMD_CHIP_ID};
uint8_t buf[2];
for (size_t i = 0; i < ARRAY_SIZE(regs); ++i) {
if (i2c_write(DLPC_I2C_ADDR, &regs[i], 1) == 0 &&
i2c_read(DLPC_I2C_ADDR, buf, 1+(regs[i]==CMD_CHIP_ID)) == 0) {
printf("Reg 0x%02X : ", regs[i]);
for (size_t j = 0; j < (regs[i]==CMD_CHIP_ID?2:1); ++j)
printf("%02X ", buf[j]);
printf("\r\n");
}
}
}
/* 7. 可选:测试图案模式 */
#ifdef DLP_PATTERN_TEST
void dlp_test_pattern(uint8_t pattern_id)
{
uint8_t data[2] = {pattern_id, 0x01}; /* 打开内部测试图 */
dlp_send_cmd(CMD_PATTERN_CONTROL, data, 2);
}
#endif
/* -------------------- 使用示例 ---------------------- */
#if 0
int main(void)
{
i2c_init(); /* 你的 GD32 I²C 初始化 */
if (dlp_init() != 0) {
printf("DLPC3421 init fail\r\n");
while (1);
}
dlp_on();
dlp_set_current(80, 80, 80); /* 白光 80 mA */
delay_1ms(5000);
dlp_off();
while (1);
}
#endif
dlpc3421.c dlpc3421.h GD32 Src / Inc
i2c_write / i2c_read / delay_1ms HAL/
dlp_probe() dlp_dump_regs()
DLPC3421