fix:修复七段数码管的显示问题

This commit is contained in:
alivender
2025-07-20 10:33:57 +08:00
parent d30712d0f6
commit 27c8ceb1db

View File

@@ -79,6 +79,7 @@ interface SevenSegmentDisplayProps {
size?: number;
color?: string;
AFTERGLOW_BUFFER_SIZE?: number; // 余晖存储槽大小
AFTERGLOW_DURATION?: number; // 余晖持续时间(毫秒)
pins?: {
pinId: string;
constraint: string;
@@ -92,7 +93,7 @@ const props = withDefaults(defineProps<SevenSegmentDisplayProps>(), {
size: 1,
color: "red",
AFTERGLOW_BUFFER_SIZE: 1, // 默认存储槽大小为100
AFTERGLOW_UPDATE_INTERVAL: 5, // 默认更新间隔为2毫秒
AFTERGLOW_DURATION: 2000, // 默认余晖持续时间500毫秒
cathodeType: "common", // 默认为共阴极
pins: () => [
{ pinId: "a", constraint: "", x: 10, y: 170 }, // a段
@@ -149,7 +150,7 @@ const afterglowBuffers = ref<Record<string, boolean[]>>({
});
// 余晖判定阈值比如持续10帧才算稳定可根据刷新间隔和人眼余晖调节
const STABLE_THRESHOLD = 10;
const STABLE_THRESHOLD = 3;
// 实际显示的段状态(只有稳定后才改变)
const stableSegmentStates = ref({
@@ -175,10 +176,54 @@ const segmentStableCounters = ref<Record<string, number>>({
dp: 0,
});
// 判断段是否激活(用稳定状态)
// 段选关闭时的余晖状态保持
const afterglowStates = ref({
a: false,
b: false,
c: false,
d: false,
e: false,
f: false,
g: false,
dp: false,
});
// 余晖计时器
const afterglowTimers = ref<Record<string, number | null>>({
a: null,
b: null,
c: null,
d: null,
e: null,
f: null,
g: null,
dp: null,
});
// 余晖持续时间(毫秒)
const AFTERGLOW_DURATION = computed(() => props.AFTERGLOW_DURATION || 500);
// 当前COM口状态
const currentComActive = ref(false); // 初始化为false等待第一次状态检查
// 是否处于余晖模式
const isInAfterglowMode = ref(false);
// 判断段是否激活(用稳定状态或余晖状态)
function isSegmentActive(
segment: "a" | "b" | "c" | "d" | "e" | "f" | "g" | "dp",
): boolean {
// 如果处于余晖模式,使用余晖状态
if (isInAfterglowMode.value) {
return afterglowStates.value[segment];
}
// 如果COM口未激活所有段都不显示
if (!currentComActive.value) {
return false;
}
// 否则使用稳定状态
return stableSegmentStates.value[segment];
}
@@ -186,21 +231,45 @@ function isSegmentActive(
function updateSegmentStates() {
// 先获取COM口状态
const comPin = props.pins.find((p) => p.pinId === "COM");
let comActive = true;
let comActive = false; // 默认未激活
if (comPin && comPin.constraint) {
const comState = getConstraintState(comPin.constraint);
if (props.cathodeType === "anode") {
// anode模式下COM为电平则所有段都熄灭
comActive = comState !== "high";
// 共阳极模式下COM为电平才激活
comActive = comState === "low";
} else {
// 共阴极模式下COM为低电平才激活
comActive = comState === "low";
}
// 可扩展其他模式
} else if (!comPin || !comPin.constraint) {
// 如果没有COM引脚或者COM引脚没有约束则认为始终激活
comActive = true;
}
// 如果COM口激活,更新所有段的状态到存储槽
if (comActive) {
updateAfterglowBuffers();
// 检查COM口状态是否发生变化
const comStateChanged = currentComActive.value !== comActive;
currentComActive.value = comActive;
// 如果COM从激活变为非激活进入余晖模式
if (comStateChanged && !comActive) {
enterAfterglowMode();
return; // 在余晖模式下,不处理其他引脚变化
}
// 如果COM从非激活变为激活退出余晖模式
if (comStateChanged && comActive) {
exitAfterglowMode();
}
// 关键修复如果COM口未激活或处于余晖模式不处理任何引脚状态变化
if (!comActive || isInAfterglowMode.value) {
return;
}
// 只有当COM口激活时才更新段的状态
updateAfterglowBuffers();
// 先更新 segmentStates
for (const pin of props.pins) {
if (["a", "b", "c", "d", "e", "f", "g", "dp"].includes(pin.pinId)) {
@@ -215,7 +284,8 @@ function updateSegmentStates() {
} else {
newState = pinState === "low";
}
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = newState && comActive;
// 段状态只有在COM激活时才有效
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = newState;
}
}
@@ -255,6 +325,49 @@ function updateAfterglowBuffers() {
}
}
// 进入余晖模式
function enterAfterglowMode() {
isInAfterglowMode.value = true;
// 保存当前稳定状态作为余晖状态
for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) {
const typedSegmentId = segmentId as keyof typeof stableSegmentStates.value;
afterglowStates.value[typedSegmentId] = stableSegmentStates.value[typedSegmentId];
// 设置定时器,在余晖持续时间后退出余晖模式
if (afterglowTimers.value[segmentId]) {
clearTimeout(afterglowTimers.value[segmentId]!);
}
afterglowTimers.value[segmentId] = setTimeout(() => {
afterglowStates.value[typedSegmentId] = false;
// 检查是否所有段都已经关闭
const allSegmentsOff = Object.values(afterglowStates.value).every(state => !state);
if (allSegmentsOff) {
exitAfterglowMode();
}
}, AFTERGLOW_DURATION.value);
}
}
// 退出余晖模式
function exitAfterglowMode() {
isInAfterglowMode.value = false;
// 清除所有定时器
for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) {
if (afterglowTimers.value[segmentId]) {
clearTimeout(afterglowTimers.value[segmentId]!);
afterglowTimers.value[segmentId] = null;
}
// 重置余晖状态
const typedSegmentId = segmentId as keyof typeof afterglowStates.value;
afterglowStates.value[typedSegmentId] = false;
}
}
// 监听约束状态变化
function onConstraintChange(constraint: string, level: string) {
const affectedPin = props.pins.find((pin) => pin.constraint === constraint);
@@ -276,6 +389,15 @@ onMounted(() => {
onConstraintStateChange(onConstraintChange);
});
onUnmounted(() => {
// 清理所有余晖定时器
for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) {
if (afterglowTimers.value[segmentId]) {
clearTimeout(afterglowTimers.value[segmentId]!);
}
}
});
// 暴露属性和方法
defineExpose({
updateSegmentStates,
@@ -307,6 +429,7 @@ export function getDefaultProps() {
size: 1,
color: "red",
cathodeType: "common",
AFTERGLOW_DURATION: 500, // 默认余晖持续时间500毫秒
pins: [
{ pinId: "a", constraint: "", x: 10, y: 170 },
{ pinId: "b", constraint: "", x: 25 - 1, y: 170 },