This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

msp430AFE253的SPI接口 和mcp2515通讯问题

Other Parts Discussed in Thread: MSP430F2272, MSP430AFE253

TI工程师:

您好!

我用msp430f2272芯片通过SPI和mcp2515实现通讯,程序运行很好,如下:

 

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

函数名称:UCB0_SPI_Init

函数功能:UCB0初始化

入口参数:BRX ---SPI时钟分频值

返回参数:无

函数说明:初始化UCB0模块的SPI模式

默认情况下分频值配置为0X20,即32分频

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

void UCB0_SPI_Init(uint BRX)  

{

      P3DIR |= BIT0;      //P3.0引脚作为片选引脚,控制外设

      P3SEL |= BIT1 + BIT2 + BIT3;     //引脚工作在USCI模式下 

      UCB0CTL0 = UCMST  + UCMSB + UCCKPL; //UCMSB , 3线,8位SPI主机模式,MSB 1st ,0 0 模式

      UCB0CTL1 |= UCSSEL_2;     //SMCLK

      UCB0BR0 = BRX & 0XFF;       //32分频

      UCB0BR1 = BRX >> 8;

      UCB0CTL1 &= ~UCSWRST;     //退出复位

}

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

函数名称:UCB0_SPI_WriteByte

函数功能:通过SPI口主机发送一个字节给从机

入口参数:发出的一个字节

返回参数:读回来的一个字节

函数说明:无

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

uchar UCB0_SPI_WriteByte(uchar data)

{

      while((IFG2 &  BIT3) == 0);        //等待发送缓冲器空

      UCB0TXBUF  = data;

      while((IFG2 &  BIT2) == 0);        //等待接收缓冲器

      return UCB0RXBUF ;

}

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

函数名称:UCB0_SPI_ReadByte

函数功能:主机通过SPI口读一个字节的数据

入口参数:无

返回参数:RX_data

函数说明:无

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

uchar UCB0_SPI_ReadByte(void)

{

        uchar RX_data;

        RX_data = UCB0_SPI_WriteByte(0X00);

        return RX_data;

}

 

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

 

 

 

现在我用msp430AFE253SPI接口和和mcp2515通讯,程序总是不能运行,请帮忙看下msp430AFE253SPI设置是否有问题(加黑部分为需要移植的程序),程序如下:

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

函数名称:UCB0_SPI_Init

函数功能:UCB0初始化

入口参数:BRX ---SPI时钟分频值

返回参数:无

函数说明:初始化UCB0模块的SPI模式

默认情况下分频值配置为0X20,即32分频

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

void UCB0_SPI_Init(uint BRX)  

{

      P1DIR |= BIT2;      //P1.2引脚作为片选引脚,控制外设

      P1SEL |= BIT5 + BIT6 + BIT7;     //引脚工作在USCI模式下 

      P1SEL2 = 0x00;

//SPI寄存器配置

U0CTL = SWRST;  // Software reset enable

delay_us(5);

U0CTL = MM+CHAR+ SYNC;  // MASTER  MODE,8-bit,SPI mode

U0TCTL =  STC+CKPL+SSEL1; //3-wire,The inactive state is high,SMCLK

//波特率设置

U0BR0 = BRX & 0XFF;       //32分频

U0BR1 = BRX >> 8;

U0MCTL = 0x000;

ME1 |= USPIE0; // USART0 SPI enable

U0CTL &= ~SWRST; // SPI Software reset DISable

}

 

 

 

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

函数名称:UCB0_SPI_WriteByte

函数功能:通过SPI口主机发送一个字节给从机

入口参数:发出的一个字节

返回参数:读回来的一个字节

函数说明:无

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

uchar UCB0_SPI_WriteByte(uchar data)

{

      while((IFG1 &  BIT7) == 0);        //等待发送缓冲器空,发送中断

      U0TXBUF  = data;

      while((IFG1 &  BIT6) == 0);        //等待接收缓冲器,接收中断

      return U0RXBUF ;

}

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

函数名称:UCB0_SPI_ReadByte

函数功能:主机通过SPI口读一个字节的数据

入口参数:无

返回参数:RX_data

函数说明:无

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

uchar UCB0_SPI_ReadByte(void)

{

        uchar RX_data;

        RX_data = UCB0_SPI_WriteByte(0X00);

        return RX_data;

}

  • 会不会是硬件上的问题,软件上没看出有啥问题。


  • 问题已经解决,并制作了学习板,例程提供如下:

    MSP430单片机CAN总线开发板

     

    1、电气特性:USB延长线从计算机取电,方便使用者学习,或者DC5V供电。

    2、芯片构成:MCU为MSP430AFE253、CAN控制器芯片为MCP2515、带有DC-DC光电隔离的CAN收发模块CTM1050T、串口芯片MAX202E。

    3、实现功能:24位ADC采集数据,通过CAN总线发送采集的数据。

    4、程序说明:MSP430AFE253芯片通过SPI总线控制MCP2515;

                 MSP430AFE253芯片用IO口模拟SPI总线,控制MCP2515。

                 以上两种控制方式的程序都调试完毕,提供给学习者使用。

    5、串口说明:开发板设置有232串口,供使用者学习使用。

    6、单片机的全部引脚全部引出,可作为单片机最小系统板

     

     

     

    程序示例:#include "CAN.h"

    #include "msp430_config.h"

    #include "mcp2515.h"

     

    #define uchar unsigned char

    #define uint unsigned int

     

    uchar flag;

    INT16U NUM_COUNT = 0;

    INT8U  Time_Flag = 0;

    #define CAN_RST_0      P1OUT &=~BIT1   //

    #define CAN_RST_1      P1OUT |= BIT1    //

     

    uchar Address;                      //地址

    uchar RecvBuff[8]={0};              //接收缓存区     

    uchar SendBuff[8]={0}, SendIndex=0; //发送缓存区,接发送数据缓存区对应数

     

     

    uchar can_isr_flag = 0;         //P1.2有CAN中断标志:接收、发送、错误、溢出

    uchar can_rcv_data_flag = 0;    //CAN接收数据标志

    uchar datapro_write_flag=0;//处理接收的数据正确,置位发送

    uchar times;                   //计数次数

    uchar SYSTime;

     

     

    /////////////////////////////////////////////////////////////////////////////////////////////

    void delay(uint x)

    {

      uchar i;

      while(x--) for(i=120;i>0;i--);

    }

    ///////////////////////////////////////////////////////////

    void Init_Clk()

    {

      uchar i;

      BCSCTL1&=~XT2OFF;             //打开XT2振荡器 //基础时钟控制寄存器BCSCTL1的第7位置0,使XT2启动

      do

      {

        IFG1 &= ~OFIFG;               // 清除振荡器失效标志

        for (i = 0xFF; i > 0; i--);   // 延时,等待XT2起振

      }

      while ((IFG1 & OFIFG) != 0);     // 判断XT2是否起振

      BCSCTL2 =SELM_2+SELS+DIVS_0;    //选择MCLK为XT2  SMCLK为XT2 不分频

    }

    /////////////////////////////////////////////////////////

    void Init_TimeA()

    {

       TACCTL0 = CCIE;               //TBCCR0允许中断

       TACCR0 = 8000;                //TIME:8000/(8mhz) =1ms                    

       TACTL = TASSEL_2 + MC_1;     //SMCLK,增计数模式

       _BIS_SR( GIE);    

     

    ///////////////////////////////////////////////////////////

    void set_p12_to_int( void )

    {

      

     P1DIR&=~BIT2; // 中断引脚应该设置为输入

     P1IES|=BIT2;  //设置为下降沿触发,=0上升触发

     P1IFG&=~BIT2; //因为P2IES设置会使中断标志位置位,故清零

     P1IE|=BIT2;   //设置中断使能

    }

    //////////////////////////////////////////////

    void init_SD24()

    {

      uint i;

      SD24CTL = SD24SSEL_1+SD24REFON+SD24DIV_3;                       // 1.2V ref, SMCLK,SMLCK 8分频

      SD24INCTL0 = SD24INCH_0+SD24GAIN_16;                            // Set channel A0+/- 16倍增益 

      SD24CCTL0 |= SD24SNGL  + SD24IE+SD24OSR_512+SD24DF;             // Single conv,enable interrupt  采样率为512  数据格式(当增益为1时0-32768表示0~-600mv  65535~32768表示0~600mv) 

      for (i = 0; i < 0x3600; i++);                                   // Delay for 1.2V ref startup

     

    }

    /////////////////////////////////////////////////////////////////////

    void RecvDataProc()  //处理从can来的数据或者命令

    {

      if(RecvBuff[1]<0x40)

      {

        switch(RecvBuff[1])

        {

          case 0x01:   //读地址 ,单机命令 

              SendBuff[0]=0x00;

              SendBuff[1]=0x01;

              SendBuff[2]=Address;

              SendBuff[3]=0X21;

              SendIndex=4; 

              datapro_write_flag=1;

              break;

          case 0x02:   //读压力

              SendBuff[0]=Address;

              SendBuff[1]=0x02;

              SendBuff[2]= Ch0Adc /256;

              SendBuff[3]= Ch0Adc %256;

              SendBuff[4]= 0X21;

              SendIndex=5;

              datapro_write_flag=1;

              break;        

          default  :

            datapro_write_flag=0;

            break;

        }//end switch

      }//end

    }

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

    ** 函数名称: Pro_CAN_ERROR()

    ** 功能描述: CAN总线错误处理

    ** 输  入  : 数据类型       形参名      功能

    ** 输  出  : 数据类型       形参名      功能

    ** 全局变量: 无

    ** 调用模块: 无

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

    void Pro_CAN_ERROR( void )

    {

             unsigned char num;

             num=mcp2515_read_register( EFLG );            // 读错误标志寄存器,判断错误类型

             if( num & EWARN )                              // 错误警告寄存器,当TEC或REC大于或等于96时置1

             {

                       mcp2515_write_register( TEC, 0 );

                       mcp2515_write_register( REC, 0 );

             }

             if( num & RXWAR )                               // 当REC大于或等于96时置1

             { ;      }

             if( num & TXWAR )                               // 当TEC大于或等于96时置1

             { ;      }

             if( num & RXEP )                                   // 当REC大于或等于128时置1

             { ;      }

             if( num & TXEP )                                   // 当TEC大于或等于128时置1

             { ;      }

             if( num & TXBO )                    // 当TEC大于或等于255时置1

             { delay_s(10);   }               //延时10s,等待单片机看门狗复位

             if( num & RX0OVR )                    // 接收缓冲区0溢出

             {

               mcp2515_write_register( EFLG, num & ~RX0OVR );             // 清中断标志;      // 根据实际情况处理,一种处理办法是发送远程桢,请求数据重新发送

             }

             if( num & RX1OVR )                    // 接收缓冲区1溢出

             {

                mcp2515_write_register( EFLG, num & ~RX1OVR );             // 清中断标志;

             }

    }

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

    ** 函数名称: CAN_ISR()

    ** 功能描述: CAN中断处理函数

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

    void CAN_ISR(void)

    {

      uchar num1,num2,num3,num,i;

      num1 = mcp2515_read_register(CANINTF);

                            // 读中断标志寄存器,根据中断类型,分别处理

       //---------------------------  报文错误中断

       if( num1 & MERRF )                                 

       {

          mcp2515_write_register( CANINTF, num1 & ~MERRF );             // 清中断标志

       }

       //---------------------------  唤醒中断

       if( num1 & WAKIF )

       {

          mcp2515_write_register( CANINTF, num1 & ~WAKIF );             // 清中断标志

          mcp2515_write_register( CANCTRL, CAN_NORMAL_MODE );           // 唤醒后,在仅监听模式,须设置进入正常工作模式

              //---------------------------  判断是否进入正常工作模式

          do

          {

              num = mcp2515_read_register( CANSTAT )& CAN_NORMAL_MODE;

          }

          while( num != CAN_NORMAL_MODE );

       }

       //---------------------------  Error interrupt!

       if(num1 & ERRIF)                                    // 错误中断

       {

          mcp2515_write_register(CANINTF, num1 & ~ERRIF);               // 清中断标志

          Pro_CAN_ERROR( );                                // 分别处理各个错误

       }

       //---------------------------  TX2 success!

       if( num1 & TX2IF )                                  // 发送2成功中断

       {

          mcp2515_write_register( CANINTF, num1 & ~TX2IF );             // 清中断标志

       }

       //---------------------------  TX1 success!

       if( num1 & TX1IF )                                  // 发送1成功中断

       {

          mcp2515_write_register( CANINTF, num1 & ~TX1IF );             // 清中断标志

       }

       //---------------------------  TX0 success!

       if(num1 & TX0IF)                                    // 发送0成功中断

       {

          mcp2515_write_register(CANINTF, num1 & ~TX0IF);               // 清中断标志

       }

       //---------------------------  RX1 interrupt!

       if( num1 & RX1IF )                                  // 接收1成功中断

       {

          mcp2515_write_register( CANINTF, num1 & ~RX1IF );             // 清中断标志

       }

      if(num1 & RX0IF)

      {

        mcp2515_write_register(CANINTF, num1 & ~RX0IF);  // 清中断标志

        num2 = mcp2515_read_register( RXB0SIDL );

        num3 = mcp2515_read_register( RXB0DLC );

        num = num3 & 0x0f;                               // 求数据长度

        if( num2 & IDE )                                 // 收到扩展帧

          {

             //---------------------------  Buffer 0 received extended remote frame!

             if( num3 & RTR )                              // 远程桢,则读取标识符,按照此标识符发送要求的数据

               { ; }

             else                                          // 数据桢,接收处理数据

                {  //---------------------------  Buffer 0 received extended data frame,data length is num

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

                   {

                      RecvBuff[ i ] = mcp2515_read_register( RXB0D0 + i );

                   }

                }

            }

        RecvDataProc();        //处理接收到的数据命令,诸如:读地址、读压力、设置地址。。。。

      } 

     

    }

    /////////////////////////////////////////////////////////

     

    void can_service()

    {

     if(can_isr_flag==1)            //如果有CAN中断

       {  

        can_isr_flag=0;

        CAN_ISR();                  //can中断处理 :接收数据,以及错误、溢出等中断处理

        if(datapro_write_flag==1)

              {

                datapro_write_flag=0;

                CAN_TX_D_Frame( 0, SendIndex, &SendBuff[0] ); // 通过CAN发送缓冲区0,发送数据长度为SendIndex的扩展帧数据,数据在 SendBuff[]中 

              }

       } 

    }

     

    ////////////////////////////////////////////////////////////////////////

    void main(void)

     

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

      WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

      Init_Clk();

     

      CAN_RST_1;        //mcp2515退出复位

      set_p12_to_int();

       init_SD24();

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

      UCB0_SPI_Init(0X40);          //USCI SPI模式初始化

      UCB0_SPI_WriteByte(0X00);

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

      CanBusConfig();               //MCP2515初始化模块

      delay_s(1);

      Init_TimeA();

     __enable_interrupt();         //Enable the Global Interrupt

     

      while(1)

      {       

          if(SYSTime>=10)   //TIME:100ms*10=1 S

            {

              SYSTime=0;

              ConvToPreVal();  

            }

          can_service();   //CAN服务程序,接收数据并按照协议处理数据,然后将处理的结果通过CAN总线上传

       }

    }

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

    函数名称:

    函数功能:CAN接收中断处理函数

    入口参数:

    返回参数:

    函数说明:

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

    #pragma vector = PORT1_VECTOR

    __interrupt void CanRxISR_Handler(void)

    {

    if((P1IFG&BIT2) == BIT2) //处理P1IN.2中断

        { 

         P1IFG &= ~BIT2; //清除中断标志

         can_isr_flag=1;

        }

    }

    /////////////////////////////////////////////////////////////

    #pragma vector=TIMERA0_VECTOR      

    __interrupt void Timer_A (void)

    {

      __disable_interrupt();

      times++;  

      if(times>=100)  //IME:1ms*100=100MS           

      {

       SYSTime++;

       SD24CCTL0 |= SD24SC;//AD开始转换

       times=0;

       }

     __enable_interrupt();

    }

     

    /////////////////////////////////////////////////////////////////

    uchar FilterIndex=0;

    uint FilterBuf[4]={0};

     

    #pragma vector=SD24_VECTOR            //SD24 interrupt

    __interrupt void SDA24(void)

    {               

      //滑动平均滤波算法(递推平均滤波法)

      uchar i;

      long  uint sum=0;

      FilterBuf[FilterIndex++]=SD24MEM0;// Save CH0 results (clears IFG)

      if(FilterIndex==4) FilterIndex=0; //先进先出,再求平均值

      for(i=0;i<4;i++)sum+=FilterBuf[i];

      Ch0Adc=(sum/4);

      SD24INCTL0 = SD24INCH_0;

      SD24CCTL0 |= SD24SNGL  + SD24IE+SD24OSR_256;    // Single conv,enable interrupt  采样率为512  数据格式(当增益为1时0-32768表示0~-600mv  65535~32768表示0~600mv

    }

     

     

    http://item.taobao.com/item.htm?spm=a1z10.1.w4004-1271027521.24.zhS1eR&id=35458937249 淘宝链接

    联系方式>>QQ:531706356   Phone:13106551527   E-mail:nnyt@tom.com

     

  • 程序运行正常