这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » FPGA » DSP 2812 SPI 双机通信 实现.

共2条 1/1 1 跳转至

DSP 2812 SPI 双机通信 实现.

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

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

菜鸟
2016-09-06 20:05:17     打赏
2楼

帖子时间也是久了点,最近也在弄这个东西,主给从发已经实现了,但从给主发没有实现。参考了一下你的程序,感觉不错。

但是有个疑问:
下面的你自己的这个程序段,为什么主和从的发送和接收数据的模式是相同的,这样就相当于主在发数据的时候,从也在发,这样岂不是收不了数据了,我的配置是主发时,从正好是收。

比如:主上升沿发,那么从上升沿收。

对于主机SPI初始化,程序如下.开启中断.        

  1.  SpiaRegs.SPICCR.all = 0x000F;    //复位,上升沿,16位数据位
  2.         SpiaRegs.SPICTL.all = 0x0007;    //使能主模式,正常相位,开启SPI中断
  3.         SpiaRegs.SPIBRR = 0x007F;        //时钟频率,300k
  4.         SpiaRegs.SPICCR.all = 0x008F;
复制代码 
对于从机SPI初始化,和主机一样,不过把SPICTL位2置0;        
  1.  SpiaRegs.SPICCR.all = 0x000F;    //复位,上升沿,16位数据位
  2.         SpiaRegs.SPICTL.all = 0x0003;    //使能从模式,正常相位,开启SPI中断
  3.         SpiaRegs.SPIBRR = 0x007F;        //时钟频率,300k
  4.         SpiaRegs.SPICCR.all = 0x008F;  

共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]