手上需要两片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;
}
复制代码