修正数码管位序: DIG4=固定F, DIG5=小数位 (APP V1.00.37)

- 布局: DIG1百位/DIG2十位/DIG3个位/DIG4固定F/DIG5小数位; DIG6-A华氏, DIG6-B小数点
- display_decode 重写为温度位序, 钳位 0~999.9, 删除 hex 解码
- disp 去掉 hex 模式; 删除 cli_parse_hex; disptest 序列改为温度值
- 仅 APP 改动, Boot 不动 (仍 V1.00.07)
- docs/开发日志.md: 新增 §65
This commit is contained in:
evan.liu 2026-09-13 09:46:28 +08:00
parent d697885694
commit 39e55e867d
16 changed files with 5848 additions and 5920 deletions

View File

@ -1595,3 +1595,21 @@ APP2 链接的镜像发向 APP1 区。设备端 END 校验(向量表 Reset PC
原 auto 状态并回到 0.0。
- 版本:APP `V1.00.35` → `V1.00.36`(`APP_FW_VERSION_NUM` 0x00010023 →
0x00010024)。Boot 不动(仍 V1.00.07)。
## 65. 修正数码管位序:DIG4 为固定 F、DIG5 为小数位(2026-09-06,APP V1.00.37,仅 APP)
- 用户实测反馈修正数码管位序(原代码把 DIG1~5 当 5 个全功能数字位是错的):
- **DIG1 = 百位、DIG2 = 十位、DIG3 = 个位、DIG4 = 固定标志 F、
DIG5 = 温度小数位(十分位)**;DIG6-A = 华氏标志(°F)、
DIG6-B = 小数点。
- 修改:
- `app_display.c` `display_decode()` 重写为温度位序:value 钳位 0.0~999.9,
×10 后按 `[百][十][个][F][小数]` 落位(百/十前导零消隐,DIG4 恒写
`0x0F`→seg_of_char 出 "F"),`dp_flag` 恒 1(小数位恒显示);删除
hex 解码分支;
- `cli_core.c` `CmdDisp` 去掉 `hex` 模式(`disp <value> [f]`,0~999.9
一位小数),删除 `cli_parse_hex()`;`CmdDispTest` 自检序列改为
`0.0~9.0` → `12.3/456.7/999.9` → `36.5F/36.5C`;
- `app_display.h` 头部注释与 `display_set` 说明更新为温度位序。
- 版本:APP `V1.00.36` → `V1.00.37`(`APP_FW_VERSION_NUM` 0x00010024 →
0x00010025)。Boot 不动(仍 V1.00.07)。

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,9 @@
* @file app_display.h
* @brief YF30137 7-segment display driver.
*
* The YF30137 is a 7-pin Charlieplexed LED module:
* - 5 seven-segment digits (DIG1..DIG5, segments A..G)
* The YF30137 is a 7-pin Charlieplexed temperature display:
* - DIG1 = hundreds, DIG2 = tens, DIG3 = ones, DIG4 = fixed "F",
* DIG5 = tenths (one decimal place)
* - DIG6 holds two single indicators: A6 = "deg F", B6 = decimal point
*
* A dedicated FreeRTOS task (display_task) scans the module continuously.
@ -30,9 +31,9 @@ extern "C" {
/**
* @brief Update what the display should show (read by the scan task).
* @param value floating value to display
* @param type DISP_TYPE_CELSIUS / DISP_TYPE_FAHRENHEIT
* @param base DISP_BASE_DECIMAL (1 decimal place) / DISP_BASE_HEX
* @param value temperature to display, clamped to 0.0..999.9 (1 decimal)
* @param type DISP_TYPE_CELSIUS / DISP_TYPE_FAHRENHEIT (DIG6-A indicator)
* @param base unused (kept for API compatibility)
* @note Non-blocking; may be called from any task context.
*/
void display_set(float value, uint8_t type, uint8_t base);

View File

@ -9,12 +9,12 @@
#define __APP_VERSION_H__
#ifndef APP_FW_VERSION
#define APP_FW_VERSION "V1.00.36"
#define APP_FW_VERSION "V1.00.37"
#endif
/* Numeric form used by the BLE info query / OTA records: 0x00MMmmpp */
#ifndef APP_FW_VERSION_NUM
#define APP_FW_VERSION_NUM 0x00010024u
#define APP_FW_VERSION_NUM 0x00010025u
#endif
#endif /* __APP_VERSION_H__ */

View File

@ -228,95 +228,67 @@ static uint8_t seg_of_char(uint8_t c)
}
/**
* @brief Decode the display value into 5 digit codes + a decimal-point flag.
* @param value value to display
* @param base DISP_BASE_DECIMAL (1 decimal place) or DISP_BASE_HEX
* @param digits out: 5 codes (0..9, 0xA..0xF for hex, CHAR_MINUS, CHAR_BLANK)
* @param dp_flag out: 1 = light the DIG6 decimal point
* @brief Decode the temperature value into the display layout.
*
* Layout (left to right):
* DIG1 = hundreds (百位)
* DIG2 = tens (十位)
* DIG3 = ones (个位)
* DIG4 = fixed "F" (华氏/摄氏度的固定标志)
* DIG5 = tenths (小数位)
* DIG6-A (degF indicator) and DIG6-B (decimal point) are handled by
* the scan loop, not here.
*
* @param value temperature to display, clamped to 0.0..999.9
* @param base unused (kept for API compatibility)
* @param digits out: 5 codes (0..9, 0xF for the fixed "F", CHAR_BLANK)
* @param dp_flag out: 1 = light the DIG6 decimal point (always 1)
*/
static void display_decode(float value, uint8_t base, uint8_t *digits, uint8_t *dp_flag)
{
uint8_t i, j;
int32_t scaled;
uint8_t i;
(void)base;
*dp_flag = 0u;
for (i = 0; i < DISP_DIGITS; i++)
{
digits[i] = CHAR_BLANK;
}
*dp_flag = 1u; /* the tenths digit is always shown, so dot is always on */
if (base == DISP_BASE_HEX)
if (value < 0.0f)
{
uint32_t iv = (uint32_t)(int32_t)value; /* integer part */
uint8_t hx[DISP_DIGITS];
uint8_t lead = 1u;
value = 0.0f;
}
if (value > 999.9f)
{
value = 999.9f;
}
for (j = 0; j < DISP_DIGITS; j++)
{
hx[DISP_DIGITS - 1u - j] = (uint8_t)(iv & 0xFu);
iv >>= 4u;
}
for (j = 0; j < DISP_DIGITS; j++)
{
if (lead && hx[j] == 0u && j < (DISP_DIGITS - 1u))
{
digits[j] = CHAR_BLANK; /* blank leading zeros */
}
else
{
lead = 0u;
digits[j] = hx[j];
}
}
}
else /* DISP_BASE_DECIMAL */
{
int neg = (value < 0.0f);
float a = neg ? -value : value;
int32_t scaled;
uint8_t dc[DISP_DIGITS];
uint8_t lead = 1u;
/* value * 10 -> [hundreds][tens][ones][-][tenths] */
scaled = (int32_t)(value * 10.0f + 0.5f);
if (a > 9999.9f)
{
a = 9999.9f;
}
scaled = (int32_t)(a * 10.0f + 0.5f); /* value * 10, 1 decimal */
for (j = 0; j < DISP_DIGITS; j++)
{
dc[DISP_DIGITS - 1u - j] = (uint8_t)(scaled % 10);
digits[4] = (uint8_t)(scaled % 10); /* DIG5 = tenths */
scaled /= 10;
}
for (j = 0; j < DISP_DIGITS; j++)
digits[2] = (uint8_t)(scaled % 10); /* DIG3 = ones */
scaled /= 10;
digits[1] = (uint8_t)(scaled % 10); /* DIG2 = tens */
scaled /= 10;
digits[0] = (uint8_t)(scaled % 10); /* DIG1 = hundreds */
/* blank leading zeros (hundreds, then tens) */
if (digits[0] == 0u)
{
if (lead && dc[j] == 0u && j < (DISP_DIGITS - 1u))
{
digits[j] = CHAR_BLANK; /* blank leading zeros */
digits[0] = CHAR_BLANK;
}
else
if (digits[0] == CHAR_BLANK && digits[1] == 0u)
{
lead = 0u;
digits[j] = dc[j];
}
digits[1] = CHAR_BLANK;
}
*dp_flag = 1u; /* decimal point always on */
if (neg)
{
for (j = 0; j < DISP_DIGITS; j++)
{
if (digits[j] != CHAR_BLANK)
{
break;
}
}
if (j > 0u)
{
digits[j - 1u] = CHAR_MINUS; /* '-' just before the value */
}
}
}
/* DIG4 = fixed "F" */
digits[3] = 0x0Fu; /* seg_of_char(0xF) -> F */
}
/* Public functions -----------------------------------------------------------*/

View File

@ -519,104 +519,60 @@ static int cli_parse_float(const char* s, float* out)
* @brief Parse a hexadecimal integer ("ff", "0xFF", "10").
* @return 1 on success, 0 on bad input.
*/
static int cli_parse_hex(const char* s, uint32_t* out)
{
uint32_t v = 0u;
int any = 0;
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
{
s += 2;
}
for (;;)
{
uint32_t d;
char c = *s;
if (c >= '0' && c <= '9') { d = (uint32_t)(c - '0'); }
else if (c >= 'a' && c <= 'f') { d = (uint32_t)(c - 'a' + 10); }
else if (c >= 'A' && c <= 'F') { d = (uint32_t)(c - 'A' + 10); }
else { break; }
v = (v << 4) | d;
any = 1;
s++;
}
if (!any || *s != '\0')
{
return 0;
}
*out = v;
return 1;
}
/**
* @brief "disp <value> [f] [hex]": set what the 7-seg display shows.
* Default: decimal with 1 decimal place, Celsius (degF indicator off).
* "f" turns on the degF indicator; "hex" displays the integer in hex.
* @brief "disp <value> [f]": set the temperature display.
* value 0.0..999.9 is shown as [hundreds][tens][ones][F][tenths];
* "f" turns on the DIG6-A degF indicator.
*/
static void CmdDisp(int argc, char* argv[])
{
uint8_t type = DISP_TYPE_CELSIUS;
uint8_t base = DISP_BASE_DECIMAL;
float value = 0.0f;
uint32_t hexval = 0u;
float value;
int i;
if (argc < 2)
{
cli_write("usage: disp <value> [f] [hex] (e.g. disp 36.5, disp ff hex)\r\n");
cli_write("usage: disp <value> [f] (e.g. disp 36.5, disp 36.5 f)\r\n");
return;
}
/* scan mode flags first (so the value is parsed in the right base) */
for (i = 2; i < argc; i++)
{
if (strcmp(argv[i], "f") == 0)
{
type = DISP_TYPE_FAHRENHEIT;
}
else if (strcmp(argv[i], "hex") == 0 || strcmp(argv[i], "16") == 0)
{
base = DISP_BASE_HEX;
}
else
{
cli_printf("bad mode: %s (use f / hex)\r\n", argv[i]);
cli_printf("bad mode: %s (use f)\r\n", argv[i]);
return;
}
}
if (base == DISP_BASE_HEX)
{
if (!cli_parse_hex(argv[1], &hexval))
{
cli_printf("bad hex value: %s\r\n", argv[1]);
return;
}
value = (float)hexval;
}
else if (!cli_parse_float(argv[1], &value))
if (!cli_parse_float(argv[1], &value))
{
cli_printf("bad value: %s\r\n", argv[1]);
return;
}
display_set(value, type, base);
display_set(value, type, DISP_BASE_DECIMAL);
if (base == DISP_BASE_HEX)
/* echo the (clamped) value actually shown */
{
cli_printf("display = 0x%lX %c\r\n", (unsigned long)hexval,
(type == DISP_TYPE_FAHRENHEIT) ? 'F' : 'C');
float shown = value;
int scaled, ip, fp;
if (shown < 0.0f)
{
shown = 0.0f;
}
else
if (shown > 999.9f)
{
int scaled = (int)(value * 10.0f + (value < 0.0f ? -0.5f : 0.5f));
int ip = scaled / 10;
int fp = scaled - ip * 10;
if (fp < 0)
{
fp = -fp;
shown = 999.9f;
}
scaled = (int)(shown * 10.0f + 0.5f);
ip = scaled / 10;
fp = scaled - ip * 10;
cli_printf("display = %d.%d %c\r\n", ip, fp,
(type == DISP_TYPE_FAHRENHEIT) ? 'F' : 'C');
}
@ -840,9 +796,9 @@ static void CmdDispSet(int argc, char* argv[])
/**
* @brief "disptest": automated display self-test. Cycles the display through
* digits 0..9, "88888" (all segments), hex "ABCDE", a degF value and
* "-123.4" so every digit/segment can be verified visually. Restores
* the previous auto-scan state when finished.
* ones digits 0..9, multi-digit values, max 999.9 and a degF value so
* every digit position (hundreds/tens/ones/F/tenths) and the DIG6-A
* indicator can be verified visually. Restores auto-scan when done.
*/
static void CmdDispTest(int argc, char* argv[])
{
@ -857,7 +813,7 @@ static void CmdDispTest(int argc, char* argv[])
/* the test drives values through display_set(), so auto must be on */
display_auto_set(1u);
cli_write("display self-test: 0..9 -> 88888 -> ABCDE -> 72.0F -> -123.4\r\n");
cli_write("display self-test: 0.0..9.0 -> 12.3/456.7/999.9 -> 36.5F\r\n");
for (i = 0; i < 10u; i++)
{
@ -866,20 +822,24 @@ static void CmdDispTest(int argc, char* argv[])
vTaskDelay(pdMS_TO_TICKS(500));
}
display_set(8888.8f, DISP_TYPE_CELSIUS, DISP_BASE_DECIMAL);
cli_write(" 88888 (all segments)\r\n");
display_set(12.3f, DISP_TYPE_CELSIUS, DISP_BASE_DECIMAL);
cli_write(" 12.3\r\n");
vTaskDelay(pdMS_TO_TICKS(1000));
display_set(456.7f, DISP_TYPE_CELSIUS, DISP_BASE_DECIMAL);
cli_write(" 456.7\r\n");
vTaskDelay(pdMS_TO_TICKS(1000));
display_set(999.9f, DISP_TYPE_CELSIUS, DISP_BASE_DECIMAL);
cli_write(" 999.9 (max)\r\n");
vTaskDelay(pdMS_TO_TICKS(1000));
display_set(36.5f, DISP_TYPE_FAHRENHEIT, DISP_BASE_DECIMAL);
cli_write(" 36.5 F (degF indicator on)\r\n");
vTaskDelay(pdMS_TO_TICKS(1200));
display_set((float)0xABCDEu, DISP_TYPE_CELSIUS, DISP_BASE_HEX);
cli_write(" ABCDE (hex)\r\n");
vTaskDelay(pdMS_TO_TICKS(1200));
display_set(72.0f, DISP_TYPE_FAHRENHEIT, DISP_BASE_DECIMAL);
cli_write(" 72.0 F (degF indicator on)\r\n");
vTaskDelay(pdMS_TO_TICKS(1200));
display_set(-123.4f, DISP_TYPE_CELSIUS, DISP_BASE_DECIMAL);
cli_write(" -123.4 (minus sign)\r\n");
display_set(36.5f, DISP_TYPE_CELSIUS, DISP_BASE_DECIMAL);
cli_write(" 36.5 C (degF indicator off)\r\n");
vTaskDelay(pdMS_TO_TICKS(1200));
display_set(0.0f, DISP_TYPE_CELSIUS, DISP_BASE_DECIMAL);
@ -903,10 +863,10 @@ static const CliCmd_t s_cmds[] = {
{"ota", "ota: UART enters OTA binary frame mode (see help ota)", CmdOta},
{"reset", "reset: system reset (reboot)", CmdReset},
{"pinset", "pinset <pxN> [0|1]: set/read GPIO level (pa0-6/pb0-13)", CmdPinSet},
{"disp", "disp <value> [f] [hex]: set 7-seg display value", CmdDisp},
{"disp", "disp <value> [f]: set temperature display (0-999.9, 1 dec)", CmdDisp},
{"dispauto", "dispauto [on|off]: enable/disable auto display scan", CmdDispAuto},
{"dispset", "dispset <pin1-7|all> [0|1|z]: drive display pin(s)", CmdDispSet},
{"disptest", "disptest: run display self-test (0-9/all-seg/hex/degF/minus)", CmdDispTest},
{"disptest", "disptest: run display self-test (digits/multi/max/degF)", CmdDispTest},
{"factory", "factory: restore params to defaults and reboot", CmdFactory},
{"uartrst", "uartrst: re-init USART1 (460800 8N1), flush rx queue", CmdUartRst},
{"uartinfo", "uartinfo: show USART1 pins/baud/format", CmdUartInfo},

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -1,7 +1,7 @@
{
"file": "mothercup_ble_prod_ota.bin",
"target_bank": 1,
"size": 59988,
"crc32": "0x856F26BD",
"version": 65572
"size": 59660,
"crc32": "0xF3E3A0A8",
"version": 65573
}

View File

@ -1,7 +1,7 @@
{
"file": "mothercup_ble_prod_ota_app2.bin",
"target_bank": 2,
"size": 60288,
"crc32": "0x5500BC3A",
"version": 65572
"size": 59960,
"crc32": "0x14643A48",
"version": 65573
}