数码管手动管脚控制: dispauto 开关 + dispset 命令 (APP V1.00.33)
- dispauto [on|off]: 关掉自动显示扫描, 7 脚置高阻, 供手动控制 - dispset <pin1-7> [0|1|z]: 手工驱动数码管 pin1~7 (pin1=PB0..pin7=PA6) - app_display.c: g_disp_auto + display_auto_set/get + display_pin_map, display_task 自动关时释放管脚并让出 - 仅 APP 改动, Boot 不动 (仍 V1.00.07) - docs/开发日志.md: 新增 §61
This commit is contained in:
parent
10531c2fa8
commit
fb681a4b69
23
docs/开发日志.md
23
docs/开发日志.md
@ -1525,3 +1525,26 @@ APP2 链接的镜像发向 APP1 区。设备端 END 校验(向量表 Reset PC
|
|||||||
- 命令表注册:`disp <value> [f] [hex]: set 7-seg display value`。
|
- 命令表注册:`disp <value> [f] [hex]: set 7-seg display value`。
|
||||||
- 版本:APP `V1.00.31` → `V1.00.32`(`APP_FW_VERSION_NUM` 0x0001001F →
|
- 版本:APP `V1.00.31` → `V1.00.32`(`APP_FW_VERSION_NUM` 0x0001001F →
|
||||||
0x00010020)。Boot 不动(仍 V1.00.07)。
|
0x00010020)。Boot 不动(仍 V1.00.07)。
|
||||||
|
|
||||||
|
## 61. 数码管手动管脚控制:`dispauto` 开关 + `dispset` 命令(2026-09-06,APP V1.00.33,仅 APP)
|
||||||
|
|
||||||
|
- 需求:① 加开关可关掉自动显示扫描,用户手工控制数码管 1~7 管脚;② 加
|
||||||
|
`dispset pin1-7 0/1`,pin1~7 直接映射到数码管对应的 CPU IO。
|
||||||
|
- 管脚映射(同 §58,权威表在 `app_display.c` 的 `s_disp_pin[]`):
|
||||||
|
`pin1=PB0 pin2=PB1 pin3=PA0 pin4=PA1 pin5=PB11 pin6=PB13 pin7=PA6`。
|
||||||
|
- 实现:
|
||||||
|
- `app_display.c/h`:
|
||||||
|
- 新增 `g_disp_auto`(默认 1=自动)+ `display_auto_set/get()`;
|
||||||
|
- `display_task`:自动关(`g_disp_auto==0`)时把 7 脚一次性置高阻
|
||||||
|
(`all_pins_input()`,用 `last_auto` 沿检测只做一次),随后仅喂狗+
|
||||||
|
20ms 让出,不碰管脚;自动开时恢复正常扫描;
|
||||||
|
- `display_pin_map(pin_no 1..7, &port, &pin)`:管脚号→GPIO 端口+掩码。
|
||||||
|
- `cli_core.c`:
|
||||||
|
- `dispauto [on|off]`:开关自动显示并回显状态;
|
||||||
|
- `dispset <pin1-7> [0|1]`:手工驱动管脚——`0` 拉低 / `1` 拉高
|
||||||
|
(输出推挽),`z` 置高阻(Charlieplexing 手工驱动必需),不带值读电平;
|
||||||
|
自动扫描未关时打印 warning 提示先 `dispauto off`;回显带 CPU IO 名
|
||||||
|
(如 `pin1 (PB0) = 1`),用 `cli_pin_str()` 由 port+pin 生成;
|
||||||
|
- `cli_parse_disp_pin()`:解析 `pin1`~`pin7`(或裸 `1`~`7`)。
|
||||||
|
- 版本:APP `V1.00.32` → `V1.00.33`(`APP_FW_VERSION_NUM` 0x00010020 →
|
||||||
|
0x00010021)。Boot 不动(仍 V1.00.07)。
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@ -18,6 +18,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "n32wb03x.h"
|
||||||
|
|
||||||
/* Display type / unit (controls the DIG6 "deg F" indicator A6) */
|
/* Display type / unit (controls the DIG6 "deg F" indicator A6) */
|
||||||
#define DISP_TYPE_CELSIUS 0u /* degree C: A6 off */
|
#define DISP_TYPE_CELSIUS 0u /* degree C: A6 off */
|
||||||
@ -41,6 +42,27 @@ void display_set(float value, uint8_t type, uint8_t base);
|
|||||||
*/
|
*/
|
||||||
void display_task(void *pvParameters);
|
void display_task(void *pvParameters);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable (1) / disable (0) the automatic Charlieplexing scan.
|
||||||
|
* When disabled the scan task releases all 7 pins to high-impedance
|
||||||
|
* so another task (e.g. the "dispset" CLI) can drive them manually.
|
||||||
|
*/
|
||||||
|
void display_auto_set(uint8_t on);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief @return 1 when the automatic scan is enabled.
|
||||||
|
*/
|
||||||
|
uint8_t display_auto_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Map a display pin number (1..7) to its GPIO port + pin mask.
|
||||||
|
* @param pin_no display pin number 1..7 (pin1=PB0 ... pin7=PA6)
|
||||||
|
* @param port out: GPIO port
|
||||||
|
* @param pin out: GPIO pin mask
|
||||||
|
* @return 1 on success, 0 when pin_no is out of range.
|
||||||
|
*/
|
||||||
|
int display_pin_map(uint8_t pin_no, GPIO_Module** port, uint16_t* pin);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -9,12 +9,12 @@
|
|||||||
#define __APP_VERSION_H__
|
#define __APP_VERSION_H__
|
||||||
|
|
||||||
#ifndef APP_FW_VERSION
|
#ifndef APP_FW_VERSION
|
||||||
#define APP_FW_VERSION "V1.00.32"
|
#define APP_FW_VERSION "V1.00.33"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Numeric form used by the BLE info query / OTA records: 0x00MMmmpp */
|
/* Numeric form used by the BLE info query / OTA records: 0x00MMmmpp */
|
||||||
#ifndef APP_FW_VERSION_NUM
|
#ifndef APP_FW_VERSION_NUM
|
||||||
#define APP_FW_VERSION_NUM 0x00010020u
|
#define APP_FW_VERSION_NUM 0x00010021u
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __APP_VERSION_H__ */
|
#endif /* __APP_VERSION_H__ */
|
||||||
|
|||||||
@ -106,6 +106,8 @@ static volatile float g_disp_value = 0.0f;
|
|||||||
static volatile uint8_t g_disp_type = DISP_TYPE_CELSIUS;
|
static volatile uint8_t g_disp_type = DISP_TYPE_CELSIUS;
|
||||||
/** Number base: DISP_BASE_DECIMAL / DISP_BASE_HEX. */
|
/** Number base: DISP_BASE_DECIMAL / DISP_BASE_HEX. */
|
||||||
static volatile uint8_t g_disp_base = DISP_BASE_DECIMAL;
|
static volatile uint8_t g_disp_base = DISP_BASE_DECIMAL;
|
||||||
|
/** Automatic scan enable: 1 = auto scan, 0 = manual pin control. */
|
||||||
|
static volatile uint8_t g_disp_auto = 1u;
|
||||||
|
|
||||||
/* Private function prototypes -----------------------------------------------*/
|
/* Private function prototypes -----------------------------------------------*/
|
||||||
/* Private functions ----------------------------------------------------------*/
|
/* Private functions ----------------------------------------------------------*/
|
||||||
@ -334,30 +336,80 @@ void display_set(float value, uint8_t type, uint8_t base)
|
|||||||
g_disp_base = base;
|
g_disp_base = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable (1) / disable (0) the automatic scan.
|
||||||
|
*/
|
||||||
|
void display_auto_set(uint8_t on)
|
||||||
|
{
|
||||||
|
g_disp_auto = (on != 0u) ? 1u : 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief @return 1 when the automatic scan is enabled.
|
||||||
|
*/
|
||||||
|
uint8_t display_auto_get(void)
|
||||||
|
{
|
||||||
|
return g_disp_auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Map a display pin number (1..7) to its GPIO port + pin mask.
|
||||||
|
*/
|
||||||
|
int display_pin_map(uint8_t pin_no, GPIO_Module** port, uint16_t* pin)
|
||||||
|
{
|
||||||
|
if (pin_no < 1u || pin_no > 7u)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*port = s_disp_pin[pin_no - 1u].port;
|
||||||
|
*pin = s_disp_pin[pin_no - 1u].pin;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Display driver task: decode the global value and scan every lit
|
* @brief Display driver task: decode the global value and scan every lit
|
||||||
* segment, one at a time, forever.
|
* segment, one at a time, forever.
|
||||||
*/
|
*/
|
||||||
void display_task(void *pvParameters)
|
void display_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
|
uint8_t last_auto = 1u; /* auto scan is on at boot */
|
||||||
|
|
||||||
(void)pvParameters;
|
(void)pvParameters;
|
||||||
|
|
||||||
all_pins_input();
|
all_pins_input();
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
float value = g_disp_value;
|
float value;
|
||||||
uint8_t type = g_disp_type;
|
uint8_t type;
|
||||||
uint8_t base = g_disp_base;
|
uint8_t base;
|
||||||
uint8_t digits[DISP_DIGITS];
|
uint8_t digits[DISP_DIGITS];
|
||||||
uint8_t dp_flag;
|
uint8_t dp_flag;
|
||||||
uint8_t d, s;
|
uint8_t d, s;
|
||||||
uint8_t segmask;
|
uint8_t segmask;
|
||||||
|
|
||||||
display_decode(value, base, digits, &dp_flag);
|
|
||||||
|
|
||||||
app_wdt_heartbeat();
|
app_wdt_heartbeat();
|
||||||
|
|
||||||
|
/* Manual mode (auto disabled): release every pin once, then keep the
|
||||||
|
* task alive and leave the pins for the caller to drive. */
|
||||||
|
if (g_disp_auto == 0u)
|
||||||
|
{
|
||||||
|
if (last_auto)
|
||||||
|
{
|
||||||
|
all_pins_input();
|
||||||
|
last_auto = 0u;
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(20));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
last_auto = 1u;
|
||||||
|
|
||||||
|
value = g_disp_value;
|
||||||
|
type = g_disp_type;
|
||||||
|
base = g_disp_base;
|
||||||
|
|
||||||
|
display_decode(value, base, digits, &dp_flag);
|
||||||
|
|
||||||
/* DIG1..DIG5 */
|
/* DIG1..DIG5 */
|
||||||
for (d = 1u; d <= DISP_DIGITS; d++)
|
for (d = 1u; d <= DISP_DIGITS; d++)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -622,6 +622,158 @@ static void CmdDisp(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse a display pin selector "pin1".."pin7" (or bare "1".."7").
|
||||||
|
* @return 1 on success, 0 on bad input.
|
||||||
|
*/
|
||||||
|
static int cli_parse_disp_pin(const char* s, uint8_t* pin_no)
|
||||||
|
{
|
||||||
|
if (s[0] == 'p' || s[0] == 'P')
|
||||||
|
{
|
||||||
|
if ((s[1] != 'i' && s[1] != 'I') || (s[2] != 'n' && s[2] != 'N'))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s += 3;
|
||||||
|
}
|
||||||
|
if (s[0] < '1' || s[0] > '7' || s[1] != '\0')
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*pin_no = (uint8_t)(s[0] - '0');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Format a GPIO port + pin mask as a pin name ("PA6"/"PB0"/"PB11").
|
||||||
|
*/
|
||||||
|
static void cli_pin_str(GPIO_Module* port, uint16_t pin, char* out)
|
||||||
|
{
|
||||||
|
char pc = (port == GPIOA) ? 'A' : 'B';
|
||||||
|
uint8_t n = 0u;
|
||||||
|
|
||||||
|
while ((pin & 1u) == 0u)
|
||||||
|
{
|
||||||
|
pin >>= 1;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
if (n >= 10u)
|
||||||
|
{
|
||||||
|
out[0] = 'P';
|
||||||
|
out[1] = pc;
|
||||||
|
out[2] = '1';
|
||||||
|
out[3] = (char)('0' + (n - 10u));
|
||||||
|
out[4] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out[0] = 'P';
|
||||||
|
out[1] = pc;
|
||||||
|
out[2] = (char)('0' + n);
|
||||||
|
out[3] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief "dispauto [on|off]": enable/disable the automatic display scan.
|
||||||
|
* Turning it off releases all 7 display pins to high-impedance so
|
||||||
|
* "dispset" can drive them manually.
|
||||||
|
*/
|
||||||
|
static void CmdDispAuto(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc >= 2)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[1], "on") == 0)
|
||||||
|
{
|
||||||
|
display_auto_set(1u);
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "off") == 0)
|
||||||
|
{
|
||||||
|
display_auto_set(0u);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cli_write("usage: dispauto [on|off]\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cli_printf("auto display: %s\r\n", display_auto_get() ? "on" : "off");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief "dispset <pin1-7> [0|1]": drive a display pin low/high manually.
|
||||||
|
* pin1..pin7 map to PB0/PB1/PA0/PA1/PB11/PB13/PA6. "z" = high-Z.
|
||||||
|
* No value reads the current level. Use after "dispauto off".
|
||||||
|
*/
|
||||||
|
static void CmdDispSet(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
GPIO_Module* port;
|
||||||
|
uint16_t pin;
|
||||||
|
uint8_t pin_no;
|
||||||
|
GPIO_InitType s;
|
||||||
|
char name[8];
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
cli_write("usage: dispset <pin1-7> [0|1] (e.g. dispset pin1 1)\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cli_parse_disp_pin(argv[1], &pin_no) ||
|
||||||
|
!display_pin_map(pin_no, &port, &pin))
|
||||||
|
{
|
||||||
|
cli_printf("bad pin: %s (use pin1..pin7)\r\n", argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cli_pin_str(port, pin, name);
|
||||||
|
|
||||||
|
if (argc >= 3)
|
||||||
|
{
|
||||||
|
if (display_auto_get())
|
||||||
|
{
|
||||||
|
cli_write("warning: auto display is ON - use 'dispauto off' first\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv[2][0] == '1' && argv[2][1] == '\0')
|
||||||
|
{
|
||||||
|
GPIO_InitStruct(&s);
|
||||||
|
s.Pin = pin;
|
||||||
|
s.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
|
GPIO_InitPeripheral(port, &s);
|
||||||
|
GPIO_SetBits(port, pin);
|
||||||
|
cli_printf("pin%u (%s) = 1\r\n", (unsigned)pin_no, name);
|
||||||
|
}
|
||||||
|
else if (argv[2][0] == '0' && argv[2][1] == '\0')
|
||||||
|
{
|
||||||
|
GPIO_InitStruct(&s);
|
||||||
|
s.Pin = pin;
|
||||||
|
s.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
|
GPIO_InitPeripheral(port, &s);
|
||||||
|
GPIO_ResetBits(port, pin);
|
||||||
|
cli_printf("pin%u (%s) = 0\r\n", (unsigned)pin_no, name);
|
||||||
|
}
|
||||||
|
else if (argv[2][0] == 'z' || argv[2][0] == 'Z')
|
||||||
|
{
|
||||||
|
/* high-impedance (release the pin) */
|
||||||
|
GPIO_InitStruct(&s);
|
||||||
|
s.Pin = pin;
|
||||||
|
s.GPIO_Mode = GPIO_MODE_INPUT;
|
||||||
|
s.GPIO_Pull = GPIO_NO_PULL;
|
||||||
|
GPIO_InitPeripheral(port, &s);
|
||||||
|
cli_printf("pin%u (%s) = high-Z\r\n", (unsigned)pin_no, name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cli_write("usage: dispset <pin1-7> [0|1] (0=low, 1=high, z=hi-Z)\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cli_printf("pin%u (%s) = %u\r\n", (unsigned)pin_no, name,
|
||||||
|
(unsigned)(GPIO_ReadInputDataBit(port, pin) ? 1u : 0u));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Command table; add new commands here */
|
/* Command table; add new commands here */
|
||||||
static const CliCmd_t s_cmds[] = {
|
static const CliCmd_t s_cmds[] = {
|
||||||
{"help", "help [cmd]: list commands / show one command's help", CmdHelp},
|
{"help", "help [cmd]: list commands / show one command's help", CmdHelp},
|
||||||
@ -639,6 +791,8 @@ static const CliCmd_t s_cmds[] = {
|
|||||||
{"reset", "reset: system reset (reboot)", CmdReset},
|
{"reset", "reset: system reset (reboot)", CmdReset},
|
||||||
{"pinset", "pinset <pxN> [0|1]: set/read GPIO level (pa0-6/pb0-13)", CmdPinSet},
|
{"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] [hex]: set 7-seg display value", CmdDisp},
|
||||||
|
{"dispauto", "dispauto [on|off]: enable/disable auto display scan", CmdDispAuto},
|
||||||
|
{"dispset", "dispset <pin1-7> [0|1]: drive display pin (pin1=PB0..pin7=PA6)", CmdDispSet},
|
||||||
{"factory", "factory: restore params to defaults and reboot", CmdFactory},
|
{"factory", "factory: restore params to defaults and reboot", CmdFactory},
|
||||||
{"uartrst", "uartrst: re-init USART1 (460800 8N1), flush rx queue", CmdUartRst},
|
{"uartrst", "uartrst: re-init USART1 (460800 8N1), flush rx queue", CmdUartRst},
|
||||||
{"uartinfo", "uartinfo: show USART1 pins/baud/format", CmdUartInfo},
|
{"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.
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"file": "mothercup_ble_prod_ota.bin",
|
"file": "mothercup_ble_prod_ota.bin",
|
||||||
"target_bank": 1,
|
"target_bank": 1,
|
||||||
"size": 58060,
|
"size": 59184,
|
||||||
"crc32": "0x71068ACD",
|
"crc32": "0xCE4E676C",
|
||||||
"version": 65568
|
"version": 65569
|
||||||
}
|
}
|
||||||
Binary file not shown.
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"file": "mothercup_ble_prod_ota_app2.bin",
|
"file": "mothercup_ble_prod_ota_app2.bin",
|
||||||
"target_bank": 2,
|
"target_bank": 2,
|
||||||
"size": 58364,
|
"size": 59484,
|
||||||
"crc32": "0x6DC77249",
|
"crc32": "0x3A51266C",
|
||||||
"version": 65568
|
"version": 65569
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user