9s12xet256 CAN

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

9s12xet256 CAN

870 Views
chris_qin
Contributor I

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

 

 

*/

Labels (1)
0 Kudos
Reply
1 Reply

610 Views
RadekS
NXP Employee
NXP Employee

Hi Zhanqiang,

In general, TX flag is set again, when CAN module detect acknowledge.

So, if there isn’t node on bus who acknowledge data from MSCAN module, TX buffer will be not freed.

Note: Be careful, MODRR registers could be written just once in normal mode. So, all you configuration for one MODRR register must be written by single command.

I cannot recommend to using CAN send function inside CAN RX interrupt due to potential problem with selecting TX buffer. This way, we could call CAN_Send() inside CAN_Send() function. So at least one of CAN_Send() will failure in that case.

I hope it helps you.

Best Regards

Radek

0 Kudos
Reply