DSP

MCP2515调试笔记(一)

2019-07-13 16:33发布

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