Files
2026-09-04 17:17:14 +08:00

156 lines
5.8 KiB
C
Raw Permalink 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.
/******************************************************************************
* @file bsp_ct1642.c
* @brief CBR3 CT1642 类数码管驱动实现(软件移位)
* @author cyWu <1917507415@qq.com>
* @date 2026.09.04
* @version V1.1.0,转机 180°:段码 A↔D/B↔E/C↔FBOARD_DISP_ROTATE_180
* @history
* - V1.1.0, 2026.09.04, cyWu, 数码管整板旋转 180° 后补偿段码
* - V1.0.1, 2026.08.29, cyWu, IO 分离:CT1642 独立 PG0=CLK/PG1=DATA
*
* @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)
{
#if BOARD_DISP_ROTATE_180
/* 管倒过来看:视觉 A/B/C 落在物理 D/E/F,视觉 D/E/F 落在物理 A/B/CG/DP 不动 */
seg = (uint8_t)(((seg & 0x07u) << 3) | ((seg & 0x38u) >> 3) | (seg & 0xC0u));
#endif
// ct1642_xfer(0, 0);
ct1642_xfer(seg, com); /* 单帧:18bit 移位 + 锁存 + 输出,无消影预帧 */
}