AnsweredAssumed Answered

9s12xet256 CAN

Question asked by zhanqiang qin on Apr 6, 2016

I met a problem when I was trying to send messages using MSCAN module in 9S12XET256. I read it in the datesheet that  CAN0TFLG would be set by hardware ,but when I put the data in the buffer, I cleared the flag,but the flag did not be set ,so the process was stopped in finding an empty buffer after i sent data 3 times.I donnot know why?

 

code:

########################################################

CAN.h

#########################################################

#ifndef _CAN_H_

#define _CAN_H_

  #include "MC9S12XET256.h"

  #define BOOL  byte

  //宏定义busclk == 16M

  #define busclk  16

  //宏定义busclk == 8M

  //#define busclk 8

 

  //定义结构体 

  typedef struct{

    dword Tx_ID;

    byte Tx_Prio;

    byte Tx_Length;

    byte Tx_Data[8];

  } MSCAN_T_Msg;

 

 

  typedef struct{

     dword Rx_ID;

     byte Rx_Length;

     byte Rx_Data[8];

  } MSCAN_R_Msg;

//函数声明 

//extern void createMsg(MSCAN_T_Msg *Msg,dword id,byte d[8],byte length,byte prio) ;

extern void setBaudRate(word baud_rate);

extern BOOL CAN_Send(MSCAN_T_Msg Msg);

//extern BOOL CAN1_Send(MSCAN_T_Msg Msg);

extern BOOL CAN_Receive(MSCAN_R_Msg *msg);

extern void CAN_Init(byte loop);

//extern void CAN1_Init(byte loop);

#endif

###########################################################################

CAN.c

###########################################################################

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

// 需先在CAN.h中设置总线时钟,默认设置16M 

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

#include "CAN.h"

//MSCAN_R_Msg RxMsg;

//MSCAN_T_Msg TxMsg;

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

//MSCAN 初始化函数

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

void CAN_Init(byte loop)

{

  MODRR_MODRR0 = 0;

  MODRR_MODRR1 = 1;  //选择PM0 PM1作为CAN0的引脚

  if (loop) {                   //如果 loop = 1;使能环回自测

      CAN0CTL1 = CAN0CTL1_LOOPB_MASK;

  }

  CAN0CTL0 = CAN0CTL0_INITRQ_MASK;//进入初始化模式

  while(!CAN0CTL1_INITAK);       //等待初始化响应

  CAN0CTL1 = CAN0CTL1_CANE_MASK;//使能模块,选择晶振(4M)时钟作为时钟源

  //setBaudRate(250);                             

  CAN0BTR0 = 0X00;

  CAN0BTR1 = 0X1C;              //250k

  //CANBTR0 = _canbtr0;

  //CANBTR0 = CANBTR0_BRP0_MASK+CANBTR0_SJW_MASK;

                               //波特率2分频,同步跳转宽度4

  //CANBTR1 = _canbtr1;

  //CANBTR1_TSEG = 3;

  //CANBTR1_TSEG = 10;         //相位缓冲段SEG1、SEG2长度设置 4,11个Tq

 

 

  CAN0IDAC_IDAM = 1;             //Four 16-bit acceptance filters

 

  CAN0IDAR0 = 0x00;CAN0IDMR0 = 0xFF;

  CAN0IDAR1 = 0x00;CAN0IDMR1 = 0xFF;

  CAN0IDAR2 = 0x00;CAN0IDMR2 = 0xFF;

  CAN0IDAR3 = 0x00;CAN0IDMR3 = 0xFF;

  CAN0IDAR4 = 0x00;CAN0IDMR4 = 0xFF;

  CAN0IDAR5 = 0x00;CAN0IDMR5 = 0xFF;

  CAN0IDAR6 = 0x00;CAN0IDMR6 = 0xFF;

  CAN0IDAR7 = 0x00;CAN0IDMR7 = 0xFF;     //接受所有的地址的消息

 

 

  CAN0CTL0_INITRQ = 0;       //关闭CAN初始化

  while(CAN0CTL1_INITAK)     //等待关闭初始化响应

          ;   

           

//     while(!CANCTL0_SYNCH)     //等待CAN同步(连到总线是需要判断同步)

//          ;

   CAN0RFLG_RXF = 1;          //清空消息接受缓冲器

   CAN0RIER_RXFIE = 1;        //使能接收消息中断 

}

 

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

//MSCAN 接收数据函数

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

BOOL CAN_Receive(MSCAN_R_Msg *msg) {        //接收8个数据

  byte i;

  if (CAN0RFLG_RXF){             //如果接收缓冲器满,返回0

    return 0;

  }

 

/* if (CANRXIDR1_IDE==0) {          //如果是标准格式帧结构

    msg->Rx_ID = (word)((CANRXIDR1<<8)+CANRXIDR0);

  }

  else if(CANRXIDR1_IDE==1){       //如果是扩展格式帧结构

    msg->Rx_ID = (CANRXIDR3<<24)+(CANRXIDR2<<16)+(CANRXIDR1<<8)+CANRXIDR0;//MSCAN Receive Identifier Register 0

  }*/

  msg->Rx_ID = (CAN0RXIDR3<<24)+(CAN0RXIDR2<<16)+(CAN0RXIDR1<<8)+CAN0RXIDR0;//MSCAN Receive Identifier Register 0

  msg->Rx_Length= CAN0RXDLR;

 

  for(i=0;i<msg->Rx_Length;i++) {

   

    msg->Rx_Data[i] = *(&(CAN0RXDSR0)+i);

   

  }

  CAN0RFLG = CAN0RFLG_RXF_MASK;

  return (1);

}

 

 

 

 

 

 

 

 

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

//MSCAN 发送数据函数

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

BOOL CAN_Send(MSCAN_T_Msg Msg) {

  byte i,Txbuf_empty_flag=0;

 

  if(Msg.Tx_Length>8)         //如果Msg的长度大于8,返回0

    return (0);

  //if(CANCTL0_SYNCH!= 0 )      //如果没有同步,返回0

  //  return (0);

 

  while (!(CAN0TFLG & (0x01<<Txbuf_empty_flag))) {

    Txbuf_empty_flag++;

    if(Txbuf_empty_flag >= 3)

      Txbuf_empty_flag = 0;

 

  }                           //从三个传输缓冲器中找一个空的

 

  CAN0TBSEL = (0x01<<Txbuf_empty_flag);

                             //选择可用的buffer    

 

 

  CAN0TXIDR0 = (byte)(Msg.Tx_ID);

  CAN0TXIDR1 = (byte)(Msg.Tx_ID>>8);

  CAN0TXIDR2 = (byte)(Msg.Tx_ID>>16);

  CAN0TXIDR3 = (byte)(Msg.Tx_ID>>24);

 

  CAN0TXDLR = Msg.Tx_Length;

  CAN0TXTBPR = Msg.Tx_Prio;

 

  for(i=0;i<Msg.Tx_Length;i++) {

    *(&CAN0TXDSR0 + i) = Msg.Tx_Data[i];

 

  }

  CAN0TFLG =(0x01<<Txbuf_empty_flag);  //清除标志位

  while((CAN0TFLG&(0x01<<Txbuf_empty_flag))== 1);

  return (1);

 

}

 

#########################################################################

main.c

##########################################################################

#include <hidef.h>      /* common defines and macros */

#include "derivative.h"      /* derivative-specific definitions */

 

#include "CAN.h"

 

 

void delay() {

  int i,j;

  for(i=0;i<500;i++)

    for(j=0;j<500;j++);

}

 

 

MSCAN_R_Msg r_msg;

MSCAN_T_Msg t_msg;

unsigned char i;

byte *t;

void main(void) {

 

  PORTA = 0XFF;

  DDRA = 0XFF;/* put your own code here */

  //PLL_SetBusClk_16M();

  //setBusClk16M_4OSC();

  //Timer_OC_Init();

  CAN_Init(1);

  CAN1RIER_RXFIE = 1;

 

  EnableInterrupts;

  for(;;) {

    (void)CAN_Send(t_msg);

    delay();

    PORTA_PA0 = ~PORTA_PA0;

    _FEED_COP(); /* feeds the dog */

  } /* loop forever */

  /* please make sure that you never leave main */

}

/*

#pragma CODE_SEG NON_BANKED

interrupt VectorNumber_Vcan0rx void CAN_Receice_ISR(void) {

  DisableInterrupts;

  CAN0RFLG_RXF = 1;

  (void)CAN_Receive(&r_msg);

  t_msg.Tx_ID = r_msg.Rx_ID;

  t_msg.Tx_Length = r_msg.Rx_Length;

 

  if(r_msg.Rx_Data[7] == 0x01) {

    PORTA =~PORTA;

 

 

  for( i=0;i<8;i++) {

   t = t_msg.Tx_Data+i;

    *t= r_msg.Rx_Data[i];

  }

 

  

  

  (void)CAN_Send(t_msg);

  }

  EnableInterrupts;

}

#pragma CODE_SEG DEFAULT

 

 

*/

Outcomes