[求助] 两块板子之间的CAN通讯

benbending   2012-11-16 08:56 楼主
      两块5K31的板子,进行CAN通讯,请问时序上应该如何设置?如果一个只负责发送数据,另一个只负责接收数据,又怎么解决?

(新板子的移植程序,两块板子分别跟老板子都能够进行CAN通讯,且协议一致了,再将两块一直程序后的新板子直接上电通讯,没有反应)。

        个人觉得应该是时序的问题,觉得作为发送一方,发送失败可以延迟一段时间,在复位重新发送;对于接收一方,也要不断判断是否有数据过来,进而接收。
        总之,主要在中断处有问题。求解。

主函数如下:

uint8 systick_flag;

//  主函数(程序入口)

int main(void)

{

    uint8 systick_bak;

        

    jtagWait();                                             // 防止JTAG失效,重要!

    clockInit();                                            // 时钟初始化:晶振,6MHz

    board_initialize();                                     // 初始化

                   SysTickPeriodSet(100000UL);                             // 设置SysTick计数器的周期值 2ms

    SysTickIntEnable();                                     // 使能SysTick中断

    IntMasterEnable();                                      // 使能处理器中断

    SysTickEnable();                                        // 使能SysTick计数器

        

           serialInit();                                                                                       

           CANConfigure();

            

           for (;;)

           {

                      if(systick_bak != systick_flag)                     // 2ms 定时到

                     {

                                 systick_bak = systick_flag;      

                                CANSend();

                                if(can_error_flag)

                                 {

                                     can_error_flag = 0;

                                        SysCtlDelay(15 * TheSysClock / 3000);

                                         CANConfigure();

                                  }

                         }      

              }

}

//

void SysTick_ISR(void)

{

    //  硬件会自动清除SysTick中断状态

    systick_flag += 1;

}


#define     _CAN_DEAL_C_

#include "config.h"

#include "can_deal.h"

#include "serial_com.h"

tCANMsgObject g_MsgObjectRx;                               // CAN接收报文对象设置

tCANMsgObject g_MsgObjectTx;                               // CAN发送报文对象设置

tCANBitClkParms CANBitClkSettings[] =

{

    /*50MHz*/

    {5,  4, 3, 5},                                                       /* CANBAUD_1M                   */

    {5,  4, 3, 10},                                                      /* CANBAUD_500K                 */

    {5,  4, 3, 20},                                                      /* CANBAUD_250K                 */

    {5,  4, 3, 40},                                                      /* CANBAUD_125K                 */

    {5,  4, 3, 50},                                                      /* CANBAUD_100k                 */

    {11, 8, 4, 50},                                                      /* CANBAUD_50k                  */

    {11, 8, 4, 100},                                                     /* CANBAUD_25k                  */

    {11, 8, 4, 125},                                                     /* CANBAUD_20k                  */

    {11, 8, 4, 250},                                                     /* CANBAUD_10k                  */

    {11, 8, 4, 500},                                                     /* CANBAUD_5k                   */

    {11, 8, 4, 1000},                                                    /* CANBAUD_2k5                  */

};

uint8  can_recebuf[8];

uint8  can_sendbuf[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x0e};

uint8  cop_frame_addr;

uint16 SendID,ReceID;

/*************************************************

函数名称:       CANConfigure

简要描述:      配置CAN0的外设

               

调用清单:

被调用清单:   

输入:         

输出:         

返回:         

其它:

修改日志:

*************************************************/

void CANConfigure(void)

{                                             

  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);                               // 使能GPIOD系统外设

  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

  SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);                                // 使能CAN控制器系统外设

  GPIOPinConfigure(GPIO_PA6_CAN0RX);

  GPIOPinConfigure(GPIO_PB5_CAN0TX);

  GPIOPinTypeCAN(GPIO_PORTA_BASE, GPIO_PIN_6 );

  GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_5 );

        

  CANInit(CAN0_BASE);                                                        // 初始化CAN节点         

  CANBitTimingSet(CAN0_BASE,

                  (tCANBitClkParms *)&CANBitClkSettings[CANBAUD_50k]);      // CAN控制器位时序进行配置

        

  CANEnable(CAN0_BASE);                                                      // 使能CAN控制器

  CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_STATUS | CAN_INT_ERROR);  // 使能CAN控制器中断源

  IntEnable(INT_CAN0);                                                       // 使能CAN控制器中断(to CPU)

  IntMasterEnable();                                                         // 使能中断总开关

         cop_frame_addr = 0;

}

/*************************************************

函数名称:       CANRece

简要描述:     配置接收数据帧

               

调用清单:

被调用清单:   

输入:      

输出:         

返回:         

其它:

修改日志:

*************************************************/

void CANRece(void)                                                        

{               

                                                         

  g_MsgObjectRx.ulMsgID     = 0x110;                                                    // 报文滤波ID

  g_MsgObjectRx.ulMsgIDMask = 0x00;                                                     // 报文ID掩码

  g_MsgObjectRx.ulFlags = MSG_OBJ_RX_INT_ENABLE

                                 | MSG_OBJ_EXTENDED_ID | MSG_OBJ_USE_ID_FILTER |MSG_OBJ_DATA_LOST ; // tCANObjFlags列举的配置参数:使能或已使能接收中断  g_MsgObjectRx.pucMsgData  = sizeof(can_recebuf);                                       // 指向数据存储空间

  g_MsgObjectRx.ulMsgLen    = 8;                                                         // 设置数据域长度

        

  CANMessageSet(CAN0_BASE, 3, &g_MsgObjectRx, MSG_OBJ_TYPE_RX);                          // 配置数据帧"接收报文对象"

}

/*************************************************

函数名称:       CANSend

简要描述:     配置发送数据

               

调用清单:

被调用清单:   

输入:      

输出:         

返回:         

其它:

修改日志:

*************************************************/

void CANSend(void)                                                           

{      

         g_MsgObjectTx.ulMsgID = SendID;                                                         //取得报文标识符

         g_MsgObjectTx.ulMsgIDMask = 0x00;

  g_MsgObjectTx.ulFlags = MSG_OBJ_TX_INT_ENABLE;                                          // 标记发送中断使能

        g_MsgObjectTx.ulMsgLen = sizeof(can_sendbuf);                                           // 标记数据域长度

        

        

         CAN_ReceDeal();

        

         if(cop_frame_addr == 0)                                                            

         {

                   cop_frame_addr = 1;

                   can_sendbuf[6] = 0x52;                                                                  //参考原始

                   can_sendbuf[7] = crc_8(can_sendbuf,7);

                  

                   g_MsgObjectTx.pucMsgData = can_sendbuf;                                                 // 传递数据存放指针  

                  CANRetrySet(CAN0_BASE, 1);                                                              // 启动发送失败重发

                   CANMessageSet(CAN0_BASE, 1, &g_MsgObjectTx, MSG_OBJ_TYPE_TX);                           // 配置1号报文对象为发送对象

         }

         else                                                                                   

         {

                   cop_frame_addr = 0;

                                    

                   can_sendbuf[6] = 0x51;                                                                  //参考原始

                   can_sendbuf[7] = crc_8(can_sendbuf,7);

                  

                   g_MsgObjectTx.pucMsgData = can_sendbuf;                                                 // 传递数据存放指针  

                    CANRetrySet(CAN0_BASE, 1);                                                              // 启动发送失败重发

                   CANMessageSet(CAN0_BASE, 2, &g_MsgObjectTx, MSG_OBJ_TYPE_TX);                           // 配置2号报文对象为发送对象

  }

}


/*************************************************

函数名称:       CANIntHandler

简要描述:      CAN中断处理

               

调用清单:

被调用清单:   

输入:      

输出:         

返回:         

其它:

修改日志:

*************************************************/

void CANIntHandler(void)

{

    unsigned long ulStatus;        

                 

    ulStatus   = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);                 //读取CANMSGnINT寄存器的值

        

    if(ulStatus == CAN_INT_INTID_STATUS)                                     // Status Interrupt       状态中断

    {                              

                     CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);

    }

    else if(ulStatus == 1||ulStatus == 2)

    {

       CANIntClear(CAN0_BASE, ulStatus);

       CANRece();

    }

    else if(ulStatus == 3)

    {

          g_MsgObjectRx.pucMsgData = can_recebuf;

          CANMessageGet(CAN0_BASE, 3, &g_MsgObjectRx, 0);

         CANIntClear(CAN0_BASE, 3);                             

          CANSend();

     }            

      else

       {

         can_error_flag = 1;

         CANIntClear(CAN0_BASE, ulStatus);

      }

}

有想法或者意见的,请多多指教!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!




A号机发送数据,B号机是接收数据。具体流程应该如何:
A发送,进入中断判断是否发送成功,如果没有延迟时间重新复位发送?
B判断是否有数据发送,有则接收,无则等待?
两块板子之间的CAN通讯时序应该如何设置呢?
A号机发送数据,B号机是接收数据。具体流程应该如何:
A发送,进入中断判断是否发送成功,如果没有延迟时间重新复位发送?
B判断是否有数据发送,有则接收,无则等待?

[ 本帖最后由 benbending 于 2012-11-19 15:42 编辑 ]

回复评论 (2)

CAN通讯不大懂,
移植的时候,时序是一定要考虑的,首先应该考虑两块板子的主频是否一样,如果主频不一样,则有些延时、时序等待等的时间要重新计算
点赞  2012-11-16 15:50

回复 沙发 tiankai001 的帖子

谢谢大侠捧场。
两块板子主频都一样的,两块板子的can模块写法一致,只是主函数一个是接收,一个是发送。
CAN模块是否存在一判断函数,判断发送方有数据过来,接收方可以接收,无则等待数据知道有数据过来才接收并反馈?
点赞  2012-11-16 16:31
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复