Board logo

标题: 关于指针的使用 [打印本页]

作者: jinandawei    时间: 2011-6-16 09:37     标题: 关于指针的使用

我们的项目使用CAN接口进行数据的传输,通过中断接收CAN消息。主函数中完成接收CAN消息后的处理。前两天在我们的项目中出现问题:
主函数不能正常运行,通过仿真器看到好像程序大多的时间都在CAN收中断中忙活。

于是乎,就开始找中断的问题,本来以为是中断函数中添加了太多的处理所致。下面是我的代码:

  1. //滤除接受CAN消息中的杂波
  2. //入口参数:PCAN_MSG pcan_msg_dst CAN消息结构体数组的首地址,PCAN_MSG pcan_msg_src 接收到的CAN消息地址
  3. void FiltReceivdCanMsg(PCAN_MSG pcan_msg_dst,PCAN_MSG pcan_msg_src)
  4. {
  5. byte i=0;
  6. if((pcan_msg_dst[0].data[0]^pcan_msg_src->data[0])||(pcan_msg_dst[0].data[1]^pcan_msg_src->data[1])||
  7. (pcan_msg_dst[0].data[2]^pcan_msg_src->data[2])||(pcan_msg_dst[0].data[3]^pcan_msg_src->data[3])||
  8. (pcan_msg_dst[0].data[4]^pcan_msg_src->data[4])||(pcan_msg_dst[0].data[5]^pcan_msg_src->data[5])||
  9. (pcan_msg_dst[0].data[6]^pcan_msg_src->data[6])||(pcan_msg_dst[0].data[7]^pcan_msg_src->data[7])) //不相等
  10. {
  11. for(i=0;i<CAN_LENTH;i++)
  12. {
  13. pcan_msg_dst[0].data=pcan_msg_src->data;
  14. }
  15. }else
  16. {
  17. for(i=0;i<CAN_LENTH;i++)
  18. {
  19. pcan_msg_dst[1].data=pcan_msg_src->data;
  20. }
  21. }
  22. }

  23. //复制数据到相应的CAN消息缓存区
  24. void CopyDataToRAM(PCAN_MSG pcan_msg)
  25. {
  26. dword id;
  27. PCAN_MSG pcan_msg_dst;
  28. if (IS_BIT_SET(pcan_msg->id.b[1],4)&&IS_BIT_SET(pcan_msg->id.b[1],3)&&IS_BIT_CLR(pcan_msg->id.b[3],0))//ID满足扩展数据帧的条件
  29. {
  30. id=GetPureID(pcan_msg);
  31. if((id==BCM1_STATUS1_ID)||(id==BCM1_STATUS2_ID)||(id==BCM1_STATUS3_ID)||(id==BCM1_DIAG1_ID)||
  32. (id==BCM1_INFO1_ID)||(id==DashBoard_INFO_ID))
  33. {
  34. if(id==BCM1_STATUS1_ID)
  35. {
  36. CANMSG_BCM1_STATUS1[1].id.dw=id;
  37. pcan_msg_dst=CANMSG_BCM1_STATUS1;//复制驾驶室输入状态信息1的CAN消息
  38. }else if(id==BCM1_STATUS2_ID)
  39. {
  40. CANMSG_BCM1_STATUS2[1].id.dw=id;
  41. pcan_msg_dst=CANMSG_BCM1_STATUS2;//复制驾驶室输入状态信息2的CAN消息
  42. }else if(id==BCM1_STATUS3_ID)
  43. {
  44. CANMSG_BCM1_STATUS3[1].id.dw=id;
  45. pcan_msg_dst=CANMSG_BCM1_STATUS3;//复制驾驶室输入状态信息3的CAN消息
  46. }else if(id==BCM1_DIAG1_ID)
  47. {
  48. CANMSG_BCM1_DIAG1[1].id.dw=id;
  49. pcan_msg_dst=CANMSG_BCM1_DIAG1;//驾驶室诊断信息1
  50. }else if(id==BCM1_INFO1_ID)
  51. {
  52. CANMSG_BCM1_INFO1[1].id.dw=id;
  53. pcan_msg_dst=CANMSG_BCM1_INFO1;//驾驶室模块信息(输出信息)
  54. }else if(id==DashBoard_INFO_ID)
  55. {
  56. CANMSG_DashBoard_INFO[1].id.dw=id;
  57. pcan_msg_dst=CANMSG_DashBoard_INFO;//仪表模块信息(仪表模块状态信息)
  58. }
  59. FiltReceivdCanMsg(pcan_msg_dst,pcan_msg);
  60. }
  61. }
  62. }
  63. //中断函数                              
  64. void interrupt 28 MSCAN_RX(void)
  65. {
  66.    unsigned char j;
  67.    unsigned char arry[13];
  68.    
  69.    for(j = 0; j < 12; j++)
  70.     {
  71.        arry[j] = *(&CANRIDR0 + j);
  72.     }   
  73.    arry[12] = (*(&CANRIDR0 + 12) & 0x0f);
  74.    
  75.    CopyDataToRAM((PCAN_MSG)arry);
  76.    CANRFLG |= 0X01;
  77. }
复制代码
其实发现,中断并非太臃肿,原来还使用了库函数“memcpy,memcmp”,于是以为是不是库函数不合适在这里,可是去掉库函数还是不能解决问题。
最后发现一个很大的BUG,就是在函数CopyDataToRAM中,原来是这样的(未修改前):

  1. //复制数据到相应的CAN消息缓存区
  2. void CopyDataToRAM(PCAN_MSG pcan_msg)
  3. {
  4. dword id;
  5. PCAN_MSG pcan_msg_dst;
  6. if (IS_BIT_SET(pcan_msg->id.b[1],4)&&IS_BIT_SET(pcan_msg->id.b[1],3)&&IS_BIT_CLR(pcan_msg->id.b[3],0))//ID满足扩展数据帧的条件
  7. {
  8. id=GetPureID(pcan_msg);
  9. if(id==BCM1_STATUS1_ID)
  10. {
  11. CANMSG_BCM1_STATUS1[1].id.dw=id;
  12. pcan_msg_dst=CANMSG_BCM1_STATUS1;//复制驾驶室输入状态信息1的CAN消息
  13. }else if(id==BCM1_STATUS2_ID)
  14. {
  15. CANMSG_BCM1_STATUS2[1].id.dw=id;
  16. pcan_msg_dst=CANMSG_BCM1_STATUS2;//复制驾驶室输入状态信息2的CAN消息
  17. }else if(id==BCM1_STATUS3_ID)
  18. {
  19. CANMSG_BCM1_STATUS3[1].id.dw=id;
  20. pcan_msg_dst=CANMSG_BCM1_STATUS3;//复制驾驶室输入状态信息3的CAN消息
  21. }else if(id==BCM1_DIAG1_ID)
  22. {
  23. CANMSG_BCM1_DIAG1[1].id.dw=id;
  24. pcan_msg_dst=CANMSG_BCM1_DIAG1;//驾驶室诊断信息1
  25. }else if(id==BCM1_INFO1_ID)
  26. {
  27. CANMSG_BCM1_INFO1[1].id.dw=id;
  28. pcan_msg_dst=CANMSG_BCM1_INFO1;//驾驶室模块信息(输出信息)
  29. }else if(id==DashBoard_INFO_ID)
  30. {
  31. CANMSG_DashBoard_INFO[1].id.dw=id;
  32. pcan_msg_dst=CANMSG_DashBoard_INFO;//仪表模块信息(仪表模块状态信息)
  33. }
  34. FiltReceivdCanMsg(pcan_msg_dst,pcan_msg);
  35. }
  36. }
复制代码
这样造成只要是ID满足扩展帧的条件,FiltReceivdCanMsg(pcan_msg_dst,pcan_msg);就会被执行。这样不仅造成额外的CPU占用(本来是想着如果ID不满足那几个特定ID的话就不做处理了),更重要的是如果ID不是特定的几个ID的话FiltReceivdCanMsg函数中的指针pcan_msg_dst,pcan_msg就完全跑飞了,从而造成不可预知的各种灾难性的后果。

总结:指针啊指针,逻辑啊逻辑,要谨慎!




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0