a87949 发表于 2025-2-21 17:34:48

mplab ice2000 神奇的問題

先附上程序代码

void SCAN_DIP_SET(){

unsigned char scan_mark,scan_cnt;
asm("NOP");
scan_dip_buf=0;
PORTA=0x00;                                        //清所有scan输出PORTA bit3~b0
//原始码

//-------------
//        读取4位DIP_SW
//-------------
        for(scan_cnt=1;scan_cnt<=8;scan_cnt<<=1){        //8421左移4次,故范围=8
                PORTA=scan_cnt;                                //输出"高态"供读取
                asm("NOP");
                if(return2)                                        //取回=RETURN2
                        scan_mark=1;                        //若有ON则移入"1"
                else
                        scan_mark=0;
                scan_dip_buf<<=1;                        //结果变量=往MSB左移1位=空出bit0
                scan_dip_buf|=scan_mark;        //映入bit0
                asm("Nop");
        }
//-------------
//        承接上_读取2位DIP_SW
//-------------
        for(scan_cnt=1;scan_cnt<=2;scan_cnt<<=1){        //32_16左移2次,相同SCAN1~2
                PORTA=scan_cnt;                                //       
                asm("NOP");
                if(return3)                                        //取回=RETURN3
                        scan_mark=1;                        //若有ON则移入"1"
                else
                        scan_mark=0;
                scan_dip_buf<<=1;                        //结果变量=左移1位=空出bit0
                scan_dip_buf|=scan_mark;        //映入bit0
                asm("Nop");       
        }

}

该代码使用mplab ice 2K 测试 使用在PIC16F873A 上
有趣的问题是
使用逐步执行
Scan_dip_buf 会是正确的数值
直接执行的情况下
读取的数值是有异常的
硬件的部分是 由porta 做输出 经过指拨开关 进行回传
Scan_bit_buf = 0x08该值为逐步执行
Scan_bit_buf = 0x04 该值为直接执行
石英为 4M

请问各路大神有发生过这样的情况吗?
可以提供解决方式吗?
这问题困扰我三天三夜了
用了 内文上的
也用直接输出方式
直接输出更惨
但都有一个特点就是 逐步执行都很正常

小甲鱼的二师兄 发表于 2025-2-21 17:34:49

尝试通过延时循环确保每次输出后都有足够延时来等待信号稳定:

// 延时函数(通过空循环提供延时)
void delay_short(void) {
    volatile unsigned int i;
    for (i = 0; i < 200; i++);// 根据需要调整循环次数
}

void SCAN_DIP_SET(){
    unsigned char scan_mark, scan_cnt;
    asm("NOP");
    scan_dip_buf = 0;
    PORTA = 0x00;// 清所有scan输出PORTA bit3~b0

    //-------------
    // 读取4位 DIP_SW
    //-------------
    for(scan_cnt = 1; scan_cnt <= 8; scan_cnt <<= 1) {// 8421左移4次,故范围=8
      PORTA = scan_cnt;      // 输出"高态"供读取
      delay_short();         // 增加延时等待信号稳定
      if (return2)             // 取回=RETURN2
            scan_mark = 1;       // 若有ON则移入"1"
      else
            scan_mark = 0;
      scan_dip_buf <<= 1;      // 结果变量=往MSB左移1位=空出bit0
      scan_dip_buf |= scan_mark;// 映入bit0
      delay_short();         // 可选延时
    }

    //-------------
    // 读取2位 DIP_SW
    //-------------
    for(scan_cnt = 1; scan_cnt <= 2; scan_cnt <<= 1) {// 32_16左移2次,相同SCAN1~2
      PORTA = scan_cnt;
      delay_short();
      if (return3)
            scan_mark = 1;
      else
            scan_mark = 0;
      scan_dip_buf <<= 1;
      scan_dip_buf |= scan_mark;
      delay_short();
    }
}

小甲鱼的二师兄 发表于 2025-2-24 03:26:02

这种现象在嵌入式开发中并不罕见,但是 “单步调试正常、直接执行异常” 的问题,其根本原因往往与时序、信号稳定时间以及硬件延时有关。

a87949 发表于 2025-2-26 13:28:57

谢谢大神的回复,由于增加了延迟,会导致当机的情况,所以移除产生问题的PIN了

Tyroe 发表于 2025-3-30 12:58:32

你所碰到的这种逐步执行正常,但直接执行时数值异常的状况,一般是由硬件响应速度、时序问题或者代码执行速度过快等因素造成的。下面为你详细分析可能的原因以及对应的解决办法:
可能的原因
硬件响应速度:指拨开关在电路里有一定的机械延迟与电气延迟,当代码直接执行时,可能在硬件还未完全响应的情况下就进行了下一次操作,从而造成读取数值异常。
时序问题:代码里的 NOP 指令也许不足以让硬件有足够的时间响应。NOP 指令只是让 CPU 空转一个指令周期,若硬件响应时间较长,就会出现问题。
代码执行速度:PIC16F873A 运行速度较快,直接执行时代码可能会迅速跳过读取操作,导致读取到错误的数值。
解决办法
增加延时:在 PORTA 输出和读取 return2、return3 之间添加适当的延时,以此确保硬件有足够的时间响应。
软件滤波:对读取到的数值进行多次采样,然后取平均值或者进行逻辑判断,以此减少误读的可能性。
修改后的代码示例
c
#include <xc.h>
#include <delay.h>// 假设你使用的编译器支持这个延时库

#define DELAY_TIME 10// 延时时间,可根据实际情况调整

void SCAN_DIP_SET(){
    unsigned char scan_mark, scan_cnt;
    asm("NOP");
    scan_dip_buf = 0;
    PORTA = 0x00;// 清所有scan输出PORTA bit3~b0

    // 读取4位DIP_SW
    for(scan_cnt = 1; scan_cnt <= 8; scan_cnt <<= 1){// 8421左移4次,故范围=8
      PORTA = scan_cnt;// 输出"高态"供读取
      __delay_ms(DELAY_TIME);// 增加延时
      if(return2)// 取回=RETURN2
            scan_mark = 1;// 若有ON则移入"1"
      else
            scan_mark = 0;
      scan_dip_buf <<= 1;// 结果变量=往MSB左移1位=空出bit0
      scan_dip_buf |= scan_mark;// 映入bit0
      asm("Nop");
    }

    // 承接上_读取2位DIP_SW
    for(scan_cnt = 1; scan_cnt <= 2; scan_cnt <<= 1){// 32_16左移2次,相同SCAN1~2
      PORTA = scan_cnt;
      __delay_ms(DELAY_TIME);// 增加延时
      if(return3)// 取回=RETURN3
            scan_mark = 1;// 若有ON则移入"1"
      else
            scan_mark = 0;
      scan_dip_buf <<= 1;// 结果变量=左移1位=空出bit0
      scan_dip_buf |= scan_mark;// 映入bit0
      asm("Nop");
    }
}





说明
延时函数:__delay_ms(DELAY_TIME) 是一个延时函数,DELAY_TIME 能够依据实际情况进行调整,以此保证硬件有足够的时间响应。
延时库:要保证你的编译器支持 delay.h 库,若不支持,你可以自行编写延时函数。
你可以尝试使用修改后的代码,看是否能够解决直接执行时读取数值异常的问题。

player-none 发表于 7 天前

a87949 发表于 2025-2-26 13:28
谢谢大神的回复,由于增加了延迟,会导致当机的情况,所以移除产生问题的PIN了

那就给他设置一个最佳
页: [1]
查看完整版本: mplab ice2000 神奇的問題