jacksonjim 发表于 2026-1-4 14:23:09

STC32G12K128 遇到一个问题关于xdata的问题



typedef struct Key
{
    u8 key_code : 4;   // key code
    u8 state : 1;      // 0 released 1 pressd
    u8 short_flag : 1; // 短按待处理标志
    u8 long_flag : 1;// 长按待处理标志
    u8 lock_flag : 1;    // 预留
    u16 press_time;    // 持续按下时间
} Key_t;

#define NUM_KEYS 5

#define KEY1 1
#define KEY2 2
#define KEY3 3
#define KEY4 4
#define KEY5 5

Key_t xdata g_keys;

void keyInit(void)
{
    Key_t *key = NULL;
    u8 key_i = 0;
#ifdef KEY1
    key = &g_keys;
    key->key_code = KEY1;// 这里是问题出现的地方,其它没有,永远是0,实际KEY1定义是1,尝试过任何值最终都为0
#endif // KEY1
#ifdef KEY2
    key = &g_keys;
    key->key_code = KEY2;
#endif // KEY2
#ifdef KEY3
    key = &g_keys;
    key->key_code = KEY3;
#endif // KEY3
#ifdef KEY4
    key = &g_keys;
    key->key_code = KEY4;
#endif // KEY4
#ifdef KEY5
    key = &g_keys;
    key->key_code = KEY5;
#endif // KEY5
#ifdef KEY6
    key = &g_keys;
    key->key_code = KEY6;
#endif // KEY6
}
但是将xdata删除或修改为idata就能正常初始值

Ayb_ice 发表于 2026-1-4 15:24:03

看反汇编很正常啊

Ayb_ice 发表于 2026-1-4 15:27:10

都正常

jacksonjim 发表于 2026-1-4 17:29:04

Ayb_ice 发表于 2026-1-4 15:27
都正常

目前我这运行输出来的结果是0,0,0,02,0,0...这样的结果,我上传编译你反编译看下结果

Ayb_ice 发表于 2026-1-4 17:30:26

jacksonjim 发表于 2026-1-4 17:29
目前我这运行输出来的结果是0,0,0,02,0,0...这样的结果,我上传编译你反编译看下结果
...

可以

jacksonjim 发表于 2026-1-4 17:32:16

这是编译的,手上没有反编译工具,你帮查看下

jacksonjim 发表于 2026-1-5 09:11:13

上传了一个工程代码,目前发现是不是初始化的原因了,在按键扫描那输出这个结构体的数据,初始化中输出一次,结果是被修改了

#include "key.h"
#include "uart.h"

#ifdef HAS_KEYS

Key_t xdata g_keys = {
#ifdef KEY1
    {KEY1},
#endif // KEY1
#ifdef KEY2
    {KEY2},
#endif // KEY2
#ifdef KEY3
    {KEY3},
#endif // KEY3
#ifdef KEY4
    {KEY4},
#endif // KEY4
#ifdef KEY5
    {KEY5},
#endif // KEY5
#ifdef KEY6
    {KEY6},
#endif // KEY6
};

void keyInit(void)
{
    UART_sendBytes(RS485_USE_UART, (u8 *)g_keys, sizeof(Key_t) * NUM_KEYS);
}

bit read_key(const u8 key_code)
{
    switch (key_code)
    {
#ifdef KEY1
    case KEY1:
      return !KEY1_PIN;
#endif
#ifdef KEY2
    case KEY2:
      return !KEY2_PIN;
#endif
#ifdef KEY3
    case KEY3:
      return !KEY3_PIN;
#endif
#ifdef KEY4
    case KEY4:
      return !KEY4_PIN;
#endif
#ifdef KEY5
    case KEY5:
      return !KEY5_PIN;
#endif
#ifdef KEY6
    case KEY6:
      return !KEY6_PIN;
#endif
    default:
      return 0; // 无效键码
    }
}
void keyScan(void)
{
    // 按键消抖计数
    static u8 keys_debounce = {0}, test = 0;
    bit key_stable_sta, key_sta;
    Key_t *key = NULL;
    u8 i;

#ifdef SW_KTDY01
    WKTCL = 0xFF;
    WKTCH = 0x87;
    NOP2();
    MCU_IDLE();
    NOP2();
#endif

#ifdef KEY_ISP
    if (!KEY_ISP_PIN)
    {
      IAP_CONTR = 0x60; // in system programe ISP
      NOP2();
    }
#endif // KEY_ISP
    if (test++ > 20)
    {
      test = 0;
      UART_sendBytes(RS485_USE_UART, (u8 *)g_keys, sizeof(Key_t) * NUM_KEYS);
    }
    for (i = 0; i < NUM_KEYS; i++)
    {
      key = &g_keys;
      key_sta = read_key(key->key_code);

      // 消抖处理 连续3次一致才认为按键有效
      if (key_sta)
      {
            if (keys_debounce < 3)
                keys_debounce++;
      }
      else
      {
            if (keys_debounce > 0)
                keys_debounce--;
      }
      key_stable_sta = keys_debounce >= 3 ? 1 : 0;

      if (key_stable_sta)
      {
            if (key->state == 0)
            {
                // 按键按下时,初始化
                key->state = 1;
                key->press_time = 0;
                key->long_flag = 0;
                key->short_flag = 0;
                key->lock_flag = 0;
            }
            else
            {
                // 持续按下时,计时
                if (key->press_time < LONG_PRESS_TIME)
                  key->press_time++;

                // 检查是否达到长按阈值且未触发过
                if (key->press_time >= LONG_PRESS_TIME && !key->long_flag && !key->lock_flag)
                {
                  key->long_flag = 1; // 标记长按事件待处理
                  key->lock_flag = 1;
                }
            }
      }
      else
      { // 释放按键
            if (key->state == 1)
            {
                if (!key->long_flag && !key->lock_flag && key->press_time >= SHORT_PRESS_TIME && key->press_time < LONG_PRESS_TIME)
                {
                  key->short_flag = 1;
                }
                // 释放按键时, 重置按键状态
                key->state = 0;
                key->press_time = 0;
                key->lock_flag = 0;
            }
      }
    }
}

void keyService(void)
{
    int i;
    Key_t *key = NULL;
    for (i = 0; i < NUM_KEYS; i++)
    {
      key = &g_keys;
      if (key->short_flag)
      {
            key->short_flag = 0;
            // Key_onClick(key->key_code);
            UART_sendBytes(RS485_USE_UART, (u8 *)key, sizeof(Key_t));
      }
      if (key->long_flag)
      {
            key->long_flag = 0;
            // Key_onLongPress(key->key_code);
      }
    }
}
#endif // HAS_KEYS

运行时输出结果
收←◆01 00 00 02 00 00 03 00 00 04 00 00 05 00 00 初始化函数输出的结果,下方所有输出是在扫描函数1秒输出一次
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆00 00 00 02 00 00 03 00 00 04 00 00 05 00 00 将xdata修改为idata或删除就输出的结果是正常的
收←◆01 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆01 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆01 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆01 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆01 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆01 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆01 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆01 00 00 02 00 00 03 00 00 04 00 00 05 00 00
收←◆01 00 00 02 00 00 03 00 00 04 00 00 05 00 00

Ayb_ice 发表于 2026-1-5 10:00:43

jacksonjim 发表于 2026-1-5 09:11
上传了一个工程代码,目前发现是不是初始化的原因了,在按键扫描那输出这个结构体的数据,初始化中输出一次 ...

建议不要使用位域,另外将数据打印成ASCII码,即调用printf或sprintf

jacksonjim 发表于 2026-1-5 10:23:42

Ayb_ice 发表于 2026-1-5 10:00
建议不要使用位域,另外将数据打印成ASCII码,即调用printf或sprintf

那个打印只是临时调试使用不是正常使用,目前就是这个原因,改回idata就能正常使用了

Ayb_ice 发表于 2026-1-5 10:26:03

jacksonjim 发表于 2026-1-5 10:23
那个打印只是临时调试使用不是正常使用,目前就是这个原因,改回idata就能正常使用了 ...

看反汇编,看看有什么区别
页: [1] 2
查看完整版本: STC32G12K128 遇到一个问题关于xdata的问题