鱼C论坛

 找回密码
 立即注册
查看: 570|回复: 4

[其他] mplab ice2000 神奇的問題

[复制链接]
发表于 2025-2-21 17:34:48 | 显示全部楼层 |阅读模式
60鱼币
先附上程序代码

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

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

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2025-2-24 03:26:02 | 显示全部楼层
这种现象在嵌入式开发中并不罕见,但是 “单步调试正常、直接执行异常” 的问题,其根本原因往往与时序、信号稳定时间以及硬件延时有关。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2025-2-24 03:26:26 | 显示全部楼层
尝试通过延时循环确保每次输出后都有足够延时来等待信号稳定:
// 延时函数(通过空循环提供延时)
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();
    }
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2025-2-26 13:28:57 | 显示全部楼层
谢谢大神的回复,由于增加了延迟,会导致当机的情况,所以移除产生问题的PIN了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 昨天 12:58 | 显示全部楼层
你所碰到的这种逐步执行正常,但直接执行时数值异常的状况,一般是由硬件响应速度、时序问题或者代码执行速度过快等因素造成的。下面为你详细分析可能的原因以及对应的解决办法:
可能的原因
硬件响应速度:指拨开关在电路里有一定的机械延迟与电气延迟,当代码直接执行时,可能在硬件还未完全响应的情况下就进行了下一次操作,从而造成读取数值异常。
时序问题:代码里的 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 库,若不支持,你可以自行编写延时函数。
你可以尝试使用修改后的代码,看是否能够解决直接执行时读取数值异常的问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-3-31 13:48

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表