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
请问各路大神有发生过这样的情况吗?
可以提供解决方式吗?
这问题困扰我三天三夜了
用了 内文上的
也用直接输出方式
直接输出更惨
但都有一个特点就是 逐步执行都很正常
尝试通过延时循环确保每次输出后都有足够延时来等待信号稳定:
// 延时函数(通过空循环提供延时)
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();
}
} 这种现象在嵌入式开发中并不罕见,但是 “单步调试正常、直接执行异常” 的问题,其根本原因往往与时序、信号稳定时间以及硬件延时有关。 谢谢大神的回复,由于增加了延迟,会导致当机的情况,所以移除产生问题的PIN了 你所碰到的这种逐步执行正常,但直接执行时数值异常的状况,一般是由硬件响应速度、时序问题或者代码执行速度过快等因素造成的。下面为你详细分析可能的原因以及对应的解决办法:
可能的原因
硬件响应速度:指拨开关在电路里有一定的机械延迟与电气延迟,当代码直接执行时,可能在硬件还未完全响应的情况下就进行了下一次操作,从而造成读取数值异常。
时序问题:代码里的 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 库,若不支持,你可以自行编写延时函数。
你可以尝试使用修改后的代码,看是否能够解决直接执行时读取数值异常的问题。 a87949 发表于 2025-2-26 13:28
谢谢大神的回复,由于增加了延迟,会导致当机的情况,所以移除产生问题的PIN了
那就给他设置一个最佳
页:
[1]