接入温湿度风扇产品固件(仲裁/条件/定时/显示),并补齐规格书与外设驱动

新增 usr_app 产品逻辑:手动>定时>条件仲裁、条件控温湿、定时任务、数码管显示、
按键/LED、风扇档位、NVM 掉电恢复、配对与开关机,上电按规格恢复上次状态。
新增 usr_periph:AHT20、CT1642、板级引脚与硬件封装;见宝协议 cond_config
改为 7 字节编解码,并接入产品 DP。
补充《温湿度风扇_固件需求规格书》,工程加入对应源文件。
.gitignore 忽略 WorkBuddy/Cursor 本地会话
This commit is contained in:
2026-08-31 15:17:27 +08:00
parent 4cb7418a02
commit 5cc7e9dbd6
53 changed files with 7028 additions and 513 deletions
+153
View File
@@ -0,0 +1,153 @@
/******************************************************************************
* @file bsp_ct1642.c
* @brief CBR3 CT1642 类数码管驱动实现(软件移位)
* @author cyWu <1917507415@qq.com>
* @date 2026.08.29
* @version V1.0.1
* @history
* - V1.0.0, 2026.08.29, cyWu, 首次发布
* - V1.0.1, 2026.08.29, cyWu, IO 分离:CT1642 独立 PG0=CLK/PG1=DATA,删除
* bsp_bus 共线机制;删调试遗留 latch/show4/scan_seg/scan_com
* 新增 bsp_ct1642_init()
*
* @note 驱动协议严格参照 CT1642 手册(与 CSDN yitx 一致):
* 一帧 = 18bitCLK 上升沿采样 DATADATA 只在 CLK=低时改变):
* [0:3] C1-C4 位选(低有效,入参 com 取反后发送,先发 C1)
* [4:9] 6 位保留位(固定填 1)
* [10:17] Q2-Q9 段码(LSB 先,seg 的 bit0 → Q2 引脚)
* 发完 18bit 后:CLK=高时 DATA 0→1 = 锁存;CLK=低时 DATA 0→1 = 输出。
* 段码/位选物理映射由 PCB 决定,SCAN_TEST 扫段/扫位已定型(见 board_pin.h)。
* 本驱动独立使用 PG0/PG1,与 AHT20 的 PC4/PC5 互不干扰。
******************************************************************************/
#include "bsp_ct1642.h"
#include "board_pin.h"
#include "asm/gpio.h"
/* 软件延时:1 次空循环(24MHz 下 ~0.1us 量级,gpio 调用本身开销另计)。
* ⚠ 提速历程:8→2(鬼影明显→一点点)→1(继续压残余微亮)。
* 若出现显示乱码/错位(低于 CT1642 最小脉宽),回调到 2。
* 软件压到极限后残余的微亮 = 硬件层(Q2-Q9 段线加 1~10k 下拉可根除)。 */
static void ct1642_delay(void)
{
volatile uint32_t i;
for (i = 0; i < 1; i++) {
/* nop */
}
}
/**
* @brief 初始化 PG0(CLK)/PG1(DATA) 为推挽输出,初始 0
* @note ⚠ 必须在第一次发帧前调用(app_disp_init 内)。
* CT1642 为纯输入从机,两根线全程推挽驱动即可,无需上拉/开漏。
* @return 无
*/
void bsp_ct1642_init(void)
{
gpio_set_pull_up(BOARD_DISP_CLK_PIN, 0);
gpio_set_pull_down(BOARD_DISP_CLK_PIN, 0);
gpio_set_die(BOARD_DISP_CLK_PIN, 1);
gpio_direction_output(BOARD_DISP_CLK_PIN, 0);
gpio_set_pull_up(BOARD_DISP_DATA_PIN, 0);
gpio_set_pull_down(BOARD_DISP_DATA_PIN, 0);
gpio_set_die(BOARD_DISP_DATA_PIN, 1);
gpio_direction_output(BOARD_DISP_DATA_PIN, 0);
}
static void ct1642_clk(uint8_t level)
{
gpio_direction_output(BOARD_DISP_CLK_PIN, level);
ct1642_delay();
}
static void ct1642_data(uint8_t level)
{
gpio_direction_output(BOARD_DISP_DATA_PIN, level);
ct1642_delay();
}
/**
* @brief 7 段数码管数字转段码(共阴,A=bit0 ... G=bit6DP=bit7
* @param digit 0~910='-'G 段);11=全灭
* @return 段码
*/
uint8_t bsp_ct1642_seg(uint8_t digit)
{
static const uint8_t seg_tbl[12] = {
0x3F, /* 0: abcdef */
0x06, /* 1: bc */
0x5B, /* 2: abdeg */
0x4F, /* 3: abcdg */
0x66, /* 4: bcfg */
0x6D, /* 5: acdfg */
0x7D, /* 6: acdefg */
0x07, /* 7: abc */
0x7F, /* 8: abcdefg */
0x6F, /* 9: abcdfg */
0x40, /* '-': g */
0x00, /* 灭 */
};
if (digit > 11) {
digit = 11;
}
return seg_tbl[digit];
}
/**
* @brief 发一帧 18bit(不含消影):C1-C4 → 6保留 → Q2-Q9,再锁存+输出
* @note 内部函数;com/seg 的消影由 bsp_ct1642_send_frame 负责。
*/
static void ct1642_xfer(uint8_t seg, uint8_t com)
{
uint8_t i;
uint8_t posn = (uint8_t)(~com); /* C1-C4 低有效:位0=选中位 */
/* 起始空闲:CLK=低,DATA=高(规格“上电 CLK 低、DATA 高”) */
ct1642_data(1);
ct1642_clk(0);
/* 1. 移位 18bitC1-C4(4) → 6位保留(填1) → Q2-Q9(8LSB=Q2=seg bit0) */
for (i = 0; i < 4; i++) { /* C1-C4,先发 C1 */
ct1642_data((uint8_t)(posn & 0x01u));
ct1642_clk(0); ct1642_clk(1); /* 下降沿改完,上升沿采样 */
posn >>= 1;
}
for (i = 0; i < 6; i++) { /* 6 位保留,固定填 1 */
ct1642_data(1);
ct1642_clk(0); ct1642_clk(1);
}
for (i = 0; i < 8; i++) { /* Q2-Q9 段码,先发 Q2(=seg bit0) */
ct1642_data((uint8_t)(seg & 0x01u));
ct1642_clk(0); ct1642_clk(1);
seg >>= 1;
}
/* 2. 锁存:CLK 保持高,DATA 给 0→1 上升沿 */
ct1642_clk(1);
ct1642_data(0);
ct1642_data(1);
/* 3. 输出:CLK 拉低,DATA 给 0→1 上升沿(刷新该位显示) */
ct1642_clk(0);
ct1642_data(0);
ct1642_data(1);
}
/**
* @brief 发一帧刷新一位数码管(CT1642 18bit 协议)
* @param seg 段码(bit7=DP ... bit0=A,与 seg_tbl 一致;先发 bit0→Q2
* @param com COM 位选掩码(bit3=C4 ... bit0=C1,仅 1 位置位;硬件低有效内部取反)
* @note ⚠ 不做任何消影预帧:CT1642 移位过程实时输出,“持续刷新”才是鬼影根因
* (切位瞬间杂段),预帧/全灭帧都无法根除,且每帧翻倍会饿死 ISR 喂狗导致
* 上电复位(实测)。鬼影的正确解法在应用层:数字没变就不刷新(值变化才
* 刷一次,其余时间锁存静止显示)。本函数保持单帧、极短,适配 ISR 上下文。
* @return 无
*/
void bsp_ct1642_send_frame(uint8_t seg, uint8_t com)
{
// ct1642_xfer(0, 0);
ct1642_xfer(seg, com); /* 单帧:18bit 移位 + 锁存 + 输出,无消影预帧 */
}