本帖最后由 sfesdm 于 2014-4-27 21:37 编辑
一直习惯串口的数据在中断里面发送,用一个函数来触发发送,部分代码如下:
void SendMessage(uint8_t *Addr,uint16_t Len)
{
Send.Start = Addr;
Send.End = Addr+Len-1;
USART_SendData(USART1,*Addr); //发送第一个数据
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_TC) != RESET)
{
if(Send.Start++ < Send.End)
{
USART_SendData(USART1,*Send.Start); //
}
else
{
USART_ClearFlag(USART1,USART_FLAG_TC);//清零TC
}
}
}
今天为了观察一个16位数据的结果,于是把这个值通过串口发送出来,但是结果一直有问题,找不到问题点在哪里。于是把步骤最简化,形如下面的程序:
void fun(void)
{
uint16_t Temp = 0x1234;
SendMessage(uint8_t *)&Temp,2);
}
结果关擦到的数据都是0x34,0x00(小端格式的数据),百思不得其解,然后把Temp定义为全局变量,结果就正确了。。。最后终于悟出,原来如此!这跟局部变量的生存期有关!
因为调用fun函数的时候,所做的操作很少,只是调用了SendMessage函数来发送Temp的数据。
而调用SendMessage函数,只是把指针指向了Temp的地址,再触发发送一个数据,然后就算执行完函数,返回了,这个时间是非常短的。
轮到fun返回之后,因为Temp是临时变量,在函数返回之后,就可作为它用,它的值就会改变。而此时,串口可能第一个数据都还没发送完,等到发送完第一个数据,指针指向的下一个地址,数据已经改变!所以,当然发送了一个不可预料的数据了。
当把Temp定义为全局变量,或者静态变量后,它的生存期跟主程序一样长,所以,结果当然没问题。
总结:不管在实际当中,会不会真的像上面那样操作,对于指针、变量生存期等等,都要小心操作,考虑全面,不然,一不小心,这样的BUG,会搞得人欲哭无泪了。
|