[资料分享] DSP 2812 SPI 双机通信 实现

灞波儿奔   2019-4-22 20:15 楼主
手上需要两片2812对四个电机进行控制,需要主机向从机发送控制信号,从机向主机发送编码器信息.所以,两机稳定,实时,迅速的通信是很重要的,这里我采用SPI通信 . 虽然是一小段通信代码,也调了很久,TI的东西用的还不是很熟练.其中遇到问题主要有进不去中断,而且数据错位.下面将程序贴下. 两片2812 的SPISOMI,SPISIMO,SPISTEA,SPICLK 互相连接 . 程序中均把引脚功能调为SPI功能.        
  EALLOW;  
   GpioMuxRegs.GPFMUX.bit.SPICLKA_GPIOF2 = 1;
   GpioMuxRegs.GPFMUX.bit.SPISIMOA_GPIOF0 =1;
   GpioMuxRegs.GPFMUX.bit.SPISOMIA_GPIOF1 =1;
   GpioMuxRegs.GPFMUX.bit.SPISTEA_GPIOF3 = 1;           
  EDIS;
复制代码


对于主机SPI初始化,程序如下.开启中断.        
SpiaRegs.SPICCR.all = 0x000F;    //复位,上升沿,16位数据位
        SpiaRegs.SPICTL.all = 0x0007;    //使能主模式,正常相位,开启SPI中断
        SpiaRegs.SPIBRR = 0x007F;        //时钟频率,300k
        SpiaRegs.SPICCR.all = 0x008F;
复制代码
对于从机SPI初始化,和主机一样,不过把SPICTL位2置0;        
SpiaRegs.SPICCR.all = 0x000F;    //复位,上升沿,16位数据位
        SpiaRegs.SPICTL.all = 0x0003;    //使能从模式,正常相位,开启SPI中断
        SpiaRegs.SPIBRR = 0x007F;        //时钟频率,300k
        SpiaRegs.SPICCR.all = 0x008F;      
复制代码
对于主从的主程序,大体上都一样.开启中断,发送数据.注意发送数据时要判断SpiaRegs.SPISTS.bit.BUFFULL_FLAG位的状态.不然会出现数据错位. 判断函数如下:        
unsigned int Spi_TxReady(void)
{
        unsigned int i;
        if(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1)
        {
                i = 0;
        }
        else
        {
                i = 1;
        }
        return(i);
}
复制代码
主机写数据函数如下:        
void Write(Uint16 data)
{
        if(Spi_TxReady() == 1)
        {
                SpiaRegs.SPITXBUF = data;        
        }
        while(Spi_TxReady()!=1);
}
复制代码
主函数如下.使用SPI接收中断        
void main(void)
{
        unsigned long int a;
                              //Step1,初始化系统控制
                              //使能相关外设时钟,PLL锁相环备频和WatchDog(看门狗)使用默认设置
        InitSysCtrl();
                                  // Step2,清除所有的中断并初始化PIE中断向量表
                                 
                                  //禁止CPU中断
        DINT;
                                  //并清除所有的CPU中断标志位
        IER = 0x0000;
        IFR = 0x0000;
                              //初始化PIE控制寄存器为默认值,默认值即所有的PIE中断都被禁止切标志位清零
        InitPieCtrl();
                              //初始化PIE中断向量表,并设置当中断发生时,程序会自动跳转到服务程序(ISR)处
        InitPieVectTable();        
                                  //step3,初始化相关外设,本例中主要是将IO设置为外设功能
        InitPeripherals();
        EALLOW;
        PieVectTable.SPIRXINTA = &spiRxIsr;
        EDIS;                                
    IER |= M_INT6;                        
        PieCtrl.PIEIER6.bit.INTx1=1;
    EINT;                                      //Enable INTM
    ERTM;                                          //Enable DBGM
    sdata = 0xA802;
        while(1)
        {
                Write(sdata);
                for(a=0;a<500000;a++);                     
        }
}
复制代码
关键的接收中断函数如下:        
interrupt void spiRxIsr(void)
{
  rdata = SpiaRegs.SPIRXBUF;
  SpiaRegs.SPISTS.bit.OVERRUN_FLAG = 1;
  PieCtrl.PIEACK.bit.ACK6 = 1;  
}
复制代码
对于从机,则在接收中断函数中发送数据回主机.因为SPI时钟只由主机提供.所以从机写数据进主机需要主机向从机提供时钟.例如当主机向从机写0x0030的时候,从机接收中断函数,将所需写入数据写入SpiaRegs.SPITXBUF,实现从机向主机写数据. 从机接收中断函数如下:        
interrupt void spiRxIsr(void)
{
        rdata = SpiaRegs.SPIRXBUF;        
        sdata = rdata;
        Write(sdata);                        
        SpiaRegs.SPISTS.bit.OVERRUN_FLAG = 1;
        PieCtrl.PIEACK.bit.ACK6 = 1;   
}
复制代码

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复