MCP2515调试笔记(一)

MSP430 + MCP2515调试笔记(一)

        MCP是MricoChip 公司生产的一款独立CAN控制器,相比恩智浦公司的SJA1000,它的主要特点是与微控制器之间通过SPI方式进行数据交换而不是SJA1000的并行方式,这样可以大大减少引脚数量,但在一定程度上也增加了软件的编写复杂度。        

        本次调试的硬件环境:MSP430F169+MCP2515+TJA1050,调试助手为瑞士Kvaser的USBCANII。软件环境为:IAR5.30.1,Kvaser CanKing5.0.2。由于之前已经将MSP430与MCP2515之间的SPI通信调通(包括硬件外设和软件模拟两种方式),因此本次调试目的主要为:调通MCP2515的发送功能。

主要程序步骤如下:

1、初始化时钟     ClockInt();

  BCSCTL2 |= SELM1 + DIVS1 + DIVS0 + SELS; // MCLK为XT2,8MHz; SMCLK为XT2,8分频,1MHz

2、初始化SPI外设  SPIInt();

  U0CTL= CHAR + SYNC + MM + SWRST;         // 8位SPI, 主机模式
  U0TCTL= CKPL + SSEL1 + SSEL0 + STC;         // 子时钟,1MHz;3线模式 下降沿准备,上升沿输出

其中,SPI的时钟设置这块,MSP430的手册上有一定的问题,必须根据MCP32515的SPI时钟来进行匹配,最好用示波器同时读取SCK和SDA两个数据进行观察后确定。

3、MCP2515软复位  MCP2515_SoftReset();

4、进入配置模式,配置MCP2515的CAN通信波特率为100KHz;

   MCP2515_WriteReg(CANCTRL,OPMOD_CONFIG);  //config mode 配置模式
       / /PRSEG + SJW + PS1 + PS2  = 1 + 2 + 3 + 4;
   MCP2515_WriteReg(MCP_CNF1, 0x03);               // SJW = 1*TO; BRP=3  TQ = 2*(BRP+1)/FOSC
   MCP2515_WriteReg(MCP_CNF2, 0x91);               // PS1 = 3*TQ; RSEG= 2*T
   MCP2515_WriteReg(MCP_CNF3, 0x03);               // PS2 = 4*TQ; 
   MCP2515_WriteReg(MCP_TXRTSCTRL , 0x00);          //Disable RTS PINs
   MCP2515_WriteReg(CANCTRL, OPMOD_NORMAL);      //config mode 普通模式

5、初始化发送寄存器

   MCP2515_InitCANBuffers();  //清空14个发送寄存器1+4+1+8

6、写14个发送寄存器 

   MCP2515_WriteReg(MCP_TXB0CTRL,0x03);   //设置为发送最高优先级
   MCP2515_WriteReg(MCP_TXB0SIDH,0xff);   // SID10--SID3
   MCP2515_WriteReg(MCP_TXB0SIDL,0x00);   //SID2--SID0
   MCP2515_WriteReg(MCP_TXB0DLC, 8);     // 发送数据长度为8 字节
   MCP2515_WriteReg(MCP_TXB0D0,0x01);   // 发送的数据88
   MCP2515_WriteReg(MCP_TXB0D1,0x02);   // 发送的数据88
   MCP2515_WriteReg(MCP_TXB0D2,0x03);   // 发送的数据88
   MCP2515_WriteReg(MCP_TXB0D3,0x04);   // 发送的数据88
   MCP2515_WriteReg(MCP_TXB0D4,0x05);   // 发送的数据88
   MCP2515_WriteReg(MCP_TXB0D5,0x06);   // 发送的数据88
   MCP2515_WriteReg(MCP_TXB0D6,0x07);   // 发送的数据88
   MCP2515_WriteReg(MCP_TXB0D7,0x08);   // 发送的数据88

7、等待发送完毕

while((MCP2515_ReadReg(MCP_TXB0CTRL) & 0x08) == 0x08);  //等待发送完毕

在上述步骤中,有以下几个注意点:

1、在SPI调通的基础上,MCP软复位后要对读取CANSTAT寄存器的值以保证系统在复位后默认进入了配置模式,如果不放心,可以对CANSTAT写OPMOD_CONFIG。

2、根据数据手册CNF1、CNF2、CNF3、MCP_TXRTSCTRL必须在配置模式下才能修改。

由于MCP的竞争使用的是8MHz,CAN的波特率选择100KHz,因此需要对8MHz进行

预分频,BRP=3 ,TQ =2*(BRP+1)/FOSC = 1us。一个时钟周期相当于10个TQ。为此将

SJW=1 ,PRSEG = 2,PS1=3,PS3=4。

这里犯了个低级错误,在对CNF写的时候由于直接用复制粘贴,导致波特率设置错误,最后还是通过示波器一位一位的比对才发现波特率设置错误,经校查才发现CNF3写成了CNF1,浪费了一晚上的时间,但是对CAN的数据链路层有了更深的了解,比如在数据位如果大于等于连续5个相同位的情况,CAN控制器将自动添加一个相反位,接收时自动摈弃掉,这也是为了区分帧头和帧尾。

3、第7步中的程序原来写成如下:

     MCP2515_RTS(0x01);//请求发送

     temp= MCP2515_ReadReg(MCP_TXB0CTRL);

     while((temp & 0x08) == 0x08); //等待发送完毕

    发现发送数据时只能发送一次,之后一直在做while循环,temp的值一直是11,TXB0CTRL寄存器中标志数据缓冲区的位bit 3 TXREQ一直为1。数据虽然已经发出去,但是程序显示该位并未清零。

    经仔细分析,上述程序的写法有误,temp是一个临时变量,执行temp= MCP2515_ReadReg(MCP_TXB0CTRL);后该值保持不变,而该语句直接在请求发送语句之后,我们知道数据发送是要一定时间的,当数据还未发送完毕,TXREQ的值自然为1,此时如果去读temp的值,则必然为1,与时while循环一直跳不出来。但是如果改成现在的形式,将查询TXREQ值的语句放在while循环中,则只要缓冲区发送完毕,便能查询到TXREQ值为0,可以跳出循环。根本的原因是微控制器和can控制器未能很好的同步。

     

     总结:经过一天多的时间才将该模块正式调通,期间碰到的两个低级错误浪费了大把时间,主要原因还是程序编写的粗心和对程序逻辑理解的不深刻造成的。希望以后引以为戒编程时切忌图快,逻辑必须要清晰。


你可能感兴趣的:(电子,嵌入式开发)