在给摄像头写SCCB协议时,主机发送完字节等待从机应答的函数如下。当从机应答时会返回0,不应答时返回1。因为没有给从机上电,所以这个函数是返回1的,并且会打印“[sccb_wack]no respond…”。
int sccb_wack()
{
int timecount=0;
sda_high();
sda_in();
delayMicroseconds(half_low_period_time);
scl_high();
while(digitalRead(sda))
{
timecount+=1;
if(timecount>high_period_time)
{
timecount=0;
Serial.println("[sccb_wack]no respond..");
sccb_stop();
return 1;
}
delayMicroseconds(1);
}
delayMicroseconds(high_period_time);
scl_low();
delayMicroseconds(half_low_period_time);
Serial.println("[sccb_wack]got respond..");
return 0;
}
在一个读取从机寄存器数值的函数中,对上述函数进行了调用,如下。其中return写在了最后一个if的执行语句中。由于sccb_wack()一直返回1,所以下面函数中的if是不应该执行的,该函数也不会返回什么数值。
unsigned char sccb_read(unsigned char reg)
{
unsigned char receive=0;
sccb_start();//起始信号
sccb_send_byte(address_w);//从机写入地址
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for address_w..");
sccb_send_byte(reg);//寄存器
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for resID..");
sccb_start();//起始信号
sccb_send_byte(address_r);//从机读取地址
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for address_r..");
receive=sccb_read_byte();
Serial.println("[sccb_read]read successfully..");
sccb_stop();
return receive;
}
}
}
}
主函数如下:
void loop()
{
unsigned char receive=0;
receive=sccb_read(0xf0);
Serial.print("Camera Chip ID is:");
Serial.println(receive,BIN);
delay(1000);
}
所以运行主函数时,打印结果应该如下:

但是实际运行结果如下。sccb_wack()输出了"[sccb_wack]no respond…“,证明该函数返回值是1,所以sccb_read()三个if的判断条件都为0,不应该输出”[sccb_read]respond for address_w…“、”[sccb_read]respond for resID…“、”[sccb_read]respond for address_r…“和”[sccb_read]read successfully…"。图中结果与预期不同。
调整1:当把sccb_read()中的return放到第一个if外,如下:
unsigned char sccb_read(unsigned char reg)
{
unsigned char receive=0;
sccb_start();//起始信号
sccb_send_byte(address_w);//从机写入地址
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for address_w..");
sccb_send_byte(reg);//寄存器
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for resID..");
sccb_start();//起始信号
sccb_send_byte(address_r);//从机读取地址
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for address_r..");
receive=sccb_read_byte();
Serial.println("[sccb_read]read successfully..");
sccb_stop();
}
}
}
return receive;
}
输出结果如下,可见if后的执行语句都没有执行,符合预期。

调整2:当把sccb_read()中的return放到第二个if外,如下:
unsigned char sccb_read(unsigned char reg)
{
unsigned char receive=0;
sccb_start();//起始信号
sccb_send_byte(address_w);//从机写入地址
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for address_w..");
sccb_send_byte(reg);//寄存器
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for resID..");
sccb_start();//起始信号
sccb_send_byte(address_r);//从机读取地址
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for address_r..");
receive=sccb_read_byte();
Serial.println("[sccb_read]read successfully..");
sccb_stop();
}
}
return receive;
}
}
输出结果如下,可见此时第一个if执行了

调整3:当把sccb_read()中的return放到第三个if外,如下:
unsigned char sccb_read(unsigned char reg)
{
unsigned char receive=0;
sccb_start();//起始信号
sccb_send_byte(address_w);//从机写入地址
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for address_w..");
sccb_send_byte(reg);//寄存器
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for resID..");
sccb_start();//起始信号
sccb_send_byte(address_r);//从机读取地址
if(!sccb_wack())
{
Serial.println("[sccb_read]respond for address_r..");
receive=sccb_read_byte();
Serial.println("[sccb_read]read successfully..");
sccb_stop();
}
return receive;
}
}
}
输出结果如下,可见此时第一个if和第二个if执行了。

所以观察到的现象是,在执行语句中加入return后,即便if的判断条件为假,但是执行语句仍然会执行。
在一个在线编译C语言的网页中,没有发生这样的情况。
困惑…
文章描述了在使用C语言编写SCCB协议时,函数sccb_wack()的返回值对后续函数sccb_read()逻辑的影响。当在sccb_read()中加入return语句后,即使if条件不满足,也会执行后续的执行语句,这与在线编译环境的行为不符,引发作者困惑。
857

被折叠的 条评论
为什么被折叠?



