本次使用DSP开发板位TMS320F28335
由于DSP只要一个SPI所以当需要两个SPI时可以使用MCBSP配置为SPI使用,MCBSP的配置手册链接:TMS320F28335数据表、产品信息和支持 |TI.com
由于网上的MCBSP技术资料较少所以会介绍一些MCBSP的知识以及修改方法,会的朋友可以直接跳转到最终代码处查看。
下载关于TMS320F28335的技术手册
查看关于MCBSP的技术手册
本次MCBSP的代码是在官方给出示例代码配置的基础上修改的
如果你需要查看官方代码可以下载CONTROLSUITE,安装教程可以参考网上的一下教程,软件下载官方地址为:CONTROLSUITE Driver or library | TI.com
安装完成后示例代码在软件安装路径下的:\device_support\f2833x\v142\DSP2833x_examples_ccsv5
官方给出的MCBSP配置如下,看不懂配置的可以对照手册查看
void init_mcbsp_spi()
{
// McBSP-A register settings
McbspaRegs.SPCR2.all=0x0000; // Reset FS generator, sample rate generator & transmitter
McbspaRegs.SPCR1.all=0x0000; // Reset Receiver, Right justify word, Digital loopback dis.
McbspaRegs.PCR.all=0x0F08; //(CLKXM=CLKRM=FSXM=FSRM= 1, FSXP = 1)
McbspaRegs.SPCR1.bit.DLB = 1;
McbspaRegs.SPCR1.bit.CLKSTP = 2; // Together with CLKXP/CLKRP determines clocking scheme
McbspaRegs.PCR.bit.CLKXP = 0; // CPOL = 0, CPHA = 0 rising edge no delay
McbspaRegs.PCR.bit.CLKRP = 0;
McbspaRegs.RCR2.bit.RDATDLY=01; // FSX setup time 1 in master mode. 0 for slave mode (Receive)
McbspaRegs.XCR2.bit.XDATDLY=01; // FSX setup time 1 in master mode. 0 for slave mode (Transmit)
McbspaRegs.RCR1.bit.RWDLEN1=5; // 32-bit word
McbspaRegs.XCR1.bit.XWDLEN1=5; // 32-bit word
McbspaRegs.SRGR2.all=0x2000; // CLKSM=1, FPER = 1 CLKG periods
McbspaRegs.SRGR1.all= 0x000F; // Frame Width = 1 CLKG period, CLKGDV=16
McbspaRegs.SPCR2.bit.GRST=1; // Enable the sample rate generator
delay_loop(); // Wait at least 2 SRG clock cycles
McbspaRegs.SPCR2.bit.XRST=1; // Release TX from Reset
McbspaRegs.SPCR1.bit.RRST=1; // Release RX from Reset
McbspaRegs.SPCR2.bit.FRST=1; // Frame Sync Generator reset
}
以下是需要修改的地方
McbspaRegs.SPCR1.bit.DLB = 1; 这个设置为1表示的是数据回环模式,我们删除掉这行代码默认设置DLB为0,表示不回环
下列代码代表的是SPI的数据采样和移位模式
McbspaRegs.SPCR1.bit.CLKSTP = 2; // Together with CLKXP/CLKRP determines clocking scheme
McbspaRegs.PCR.bit.CLKXP = 0; // CPOL = 0, CPHA = 0 rising edge no delay
McbspaRegs.PCR.bit.CLKRP = 0;
具体设置可以参考手册
下列代码设置两个SPI数据之间的发送间隔,由于我们是要与W5500进行通信所有需要的是连续传输数据所以设置为0
McbspaRegs.RCR2.bit.RDATDLY=01; // FSX setup time 1 in master mode. 0 for slave mode (Receive)
McbspaRegs.XCR2.bit.XDATDLY=01; // FSX setup time 1 in master mode. 0 for slave mode (Transmit)
下列代码表示传输字节长度我们需要设置为8字节长度,所以设置都为0
McbspaRegs.RCR1.bit.RWDLEN1=5; // 32-bit word
McbspaRegs.XCR1.bit.XWDLEN1=5; // 32-bit word
SPRG1寄存器中的CLKGDV为可以修改传输CLK时钟的频率,由于我们此次配置使用的是外部低速时钟LSPCLK,分频最大不能超过LSPCLK/2,根据自己需求修改。
McbspaRegs.SRGR1.all= 0x000F; // Frame Width = 1 CLKG period, CLKGDV=16
根据以上的配置会出现一个情况,当你不传输数据时,时钟CLK也会进行跳变,我们需要让他在数据不传输的时候CLK保持在一个电平
可以设置McbspaRegs.SPCR1.bit.DXENA=1;达到想要的效果,这样修改会让不传输数据的时候CLK保持在低电平状态,我想要他保持在高电平状态
所以我修改了McbspaRegs.PCR.bit.CLKXP = 1;配置使它默认状态保持在高电平
最终修改寄存器配置代码如下
void init_mcbsp_reg(void)
{
// McBSP-A register settings
McbspaRegs.SPCR2.all=0x0000; // Reset FS generator, sample rate generator & transmitter
McbspaRegs.SPCR1.all=0x0000; // Reset Receiver, Right justify word, Digital loopback dis.
McbspaRegs.PCR.all=0x0F08; //(CLKXM=CLKRM=FSXM=FSRM= 1, FSXP = 1)
// McbspaRegs.PCR.bit.FSXM = 0;
// McbspaRegs.SPCR1.bit.DLB = 1;
McbspaRegs.SPCR1.bit.CLKSTP = 2; // Together with CLKXP/CLKRP determines clocking scheme
McbspaRegs.PCR.bit.CLKXP = 1; // CPOL = 0, CPHA = 1 rising edge have delay
McbspaRegs.PCR.bit.CLKRP = 1;
McbspaRegs.RCR2.bit.RDATDLY=0; // FSX setup time 0 in master mode. 0 for slave mode (Receive)
McbspaRegs.XCR2.bit.XDATDLY=0; // FSX setup time 0 in master mode. 0 for slave mode (Transmit)
McbspaRegs.RCR1.bit.RWDLEN1=0; // 8-bit word
McbspaRegs.XCR1.bit.XWDLEN1=0; // 8-bit word
McbspaRegs.SRGR2.all=0x2000; // CLKSM=1, FPER = 1 CLKG periods
McbspaRegs.SRGR1.all= 0x000F; // Frame Width = 1 CLKG period, CLKGDV=16
McbspaRegs.SPCR1.bit.DXENA=1;
// McbspaRegs.XCR1.bit.XFRLEN1 = 1;
// McbspaRegs.SRGR2.bit.GSYNC = 1;
// McbspaRegs.SRGR2.bit.FSGM = 1;
// McbspaRegs.SRGR2.bit.FPER = 7;
// McbspaRegs.SRGR1.bit.FWID=0;
McbspaRegs.SPCR2.bit.GRST=1; // Enable the sample rate generator
delay_loopa(); // Wait at least 2 SRG clock cycles
McbspaRegs.SPCR2.bit.XRST=1; // Release TX from Reset
McbspaRegs.SPCR1.bit.RRST=1; // Release RX from Reset
McbspaRegs.SPCR2.bit.FRST=1; // Frame Sync Generator reset
}
最终完整驱动代码如下
/*
* mcbsp.c
*
* Created on: 2024年6月20日
* Author: GuiHe
*/
#include "mcbsp.h"
void delay_loopa(void)
{
long i;
for (i = 0; i < 8; i++) {} //delay in McBsp init. must be at least 2 SRG cycles
}
void WIZ_mcbsp_init(void)
{
init_mcbspa_gpio();
init_mcbsp_reg();
}
void init_mcbspa_gpio()
{
EALLOW;
GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 2; // GPIO20 is MDXA pin
GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 2; // GPIO21 is MDRA pin
GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 2; // GPIO22 is MCLKXA pin
GpioCtrlRegs.GPAPUD.bit.GPIO20 = 0; // Enable pull-up on GPIO20 (MDXA)
GpioCtrlRegs.GPAPUD.bit.GPIO21 = 0; // Enable pull-up on GPIO21 (MDRA)
GpioCtrlRegs.GPAPUD.bit.GPIO22 = 0; // Enable pull-up on GPIO22 (MCLKXA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 3; // Asynch input GPIO20 (MDXA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 3; // Asynch input GPIO21 (MDRA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO22 = 3; // Asynch input GPIO22 (MCLKXA)
//Configure GPIO49 as RESET
// GpioCtrlRegs.GPBPUD.bit.GPIO49 = 0;// Enable pullup
// GpioDataRegs.GPBSET.bit.GPIO49 = 1; // Load output latch
// GpioCtrlRegs.GPBMUX2.bit.GPIO49 = 0; //
// GpioCtrlRegs.GPBDIR.bit.GPIO49 = 1; // GPIO49 = output
GpioCtrlRegs.GPAPUD.bit.GPIO25 = 0;// Enable pullup
GpioDataRegs.GPASET.bit.GPIO25 = 1; // Load output latch
GpioCtrlRegs.GPAMUX2.bit.GPIO25 = 0; //
GpioCtrlRegs.GPADIR.bit.GPIO25 = 1; // GPIO49 = output
//Configure GPIO23 as SPISTEA
// GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0;// Enable pullup
// GpioDataRegs.GPASET.bit.GPIO23 = 1; // Load output latch
// GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 0; //
// GpioCtrlRegs.GPADIR.bit.GPIO23 = 1; // GPIO27 = output
GpioCtrlRegs.GPAPUD.bit.GPIO24 = 0;// Enable pullup
GpioDataRegs.GPASET.bit.GPIO24 = 1; // Load output latch
GpioCtrlRegs.GPAMUX2.bit.GPIO24 = 0; //
GpioCtrlRegs.GPADIR.bit.GPIO24 = 1; // GPIO27 = output
// GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 2; // GPIO23 is MFSXA pin
// GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0; // Enable pull-up on GPIO23 (MFSXA)
// GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 3; // Asynch input GPIO23 (MFSXA)
EDIS;
}
// w5500外部复位 根据自己的需求修改
void MCBSP_Reset_W5500(void)
{
GpioDataRegs.GPADAT.bit.GPIO25 = 0;
DELAY_US(510);
GpioDataRegs.GPADAT.bit.GPIO25 = 1;
DELAY_US(510);
}
void init_mcbsp_reg(void)
{
// McBSP-A register settings
McbspaRegs.SPCR2.all=0x0000; // Reset FS generator, sample rate generator & transmitter
McbspaRegs.SPCR1.all=0x0000; // Reset Receiver, Right justify word, Digital loopback dis.
McbspaRegs.PCR.all=0x0F08; //(CLKXM=CLKRM=FSXM=FSRM= 1, FSXP = 1)
// McbspaRegs.PCR.bit.FSXM = 0;
// McbspaRegs.SPCR1.bit.DLB = 1;
McbspaRegs.SPCR1.bit.CLKSTP = 2; // Together with CLKXP/CLKRP determines clocking scheme
McbspaRegs.PCR.bit.CLKXP = 1; // CPOL = 0, CPHA = 1 rising edge have delay
McbspaRegs.PCR.bit.CLKRP = 1;
McbspaRegs.RCR2.bit.RDATDLY=0; // FSX setup time 0 in master mode. 0 for slave mode (Receive)
McbspaRegs.XCR2.bit.XDATDLY=0; // FSX setup time 0 in master mode. 0 for slave mode (Transmit)
McbspaRegs.RCR1.bit.RWDLEN1=0; // 8-bit word
McbspaRegs.XCR1.bit.XWDLEN1=0; // 8-bit word
McbspaRegs.SRGR2.all=0x2000; // CLKSM=1, FPER = 1 CLKG periods
McbspaRegs.SRGR1.all= 0x000F; // Frame Width = 1 CLKG period, CLKGDV=16
McbspaRegs.SPCR1.bit.DXENA=1;
// McbspaRegs.XCR1.bit.XFRLEN1 = 1;
// McbspaRegs.SRGR2.bit.GSYNC = 1;
// McbspaRegs.SRGR2.bit.FSGM = 1;
// McbspaRegs.SRGR2.bit.FPER = 7;
// McbspaRegs.SRGR1.bit.FWID=0;
McbspaRegs.SPCR2.bit.GRST=1; // Enable the sample rate generator
delay_loopa(); // Wait at least 2 SRG clock cycles
McbspaRegs.SPCR2.bit.XRST=1; // Release TX from Reset
McbspaRegs.SPCR1.bit.RRST=1; // Release RX from Reset
McbspaRegs.SPCR2.bit.FRST=1; // Frame Sync Generator reset
}
// 设置片选信号
void WIZ_MCBSP_CS(uint8 val)
{
if (val == 0)
{
GpioDataRegs.GPADAT.bit.GPIO24 = 0;
}
else if (val == 1)
{
GpioDataRegs.GPADAT.bit.GPIO24 = 1;
}
}
// 设置MCBSP 的发送数据
uint8 MCBSP_SendByte(uint8 byte)
{
uint8 SPIRXD;
McbspaRegs.DXR1.all= byte;
while( McbspaRegs.SPCR1.bit.RRDY == 0 ) {}
SPIRXD = McbspaRegs.DRR1.all;
return SPIRXD;
}
驱动代码中的RESET、SPISTE引脚的 GPIO配置可以按照我的样式根据自己的需求修改
//Configure GPIO49 as RESET
// GpioCtrlRegs.GPBPUD.bit.GPIO49 = 0;// Enable pullup
// GpioDataRegs.GPBSET.bit.GPIO49 = 1; // Load output latch
// GpioCtrlRegs.GPBMUX2.bit.GPIO49 = 0; //
// GpioCtrlRegs.GPBDIR.bit.GPIO49 = 1; // GPIO49 = output
GpioCtrlRegs.GPAPUD.bit.GPIO25 = 0;// Enable pullup
GpioDataRegs.GPASET.bit.GPIO25 = 1; // Load output latch
GpioCtrlRegs.GPAMUX2.bit.GPIO25 = 0; //
GpioCtrlRegs.GPADIR.bit.GPIO25 = 1; // GPIO49 = output
//Configure GPIO23 as SPISTEA
// GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0;// Enable pullup
// GpioDataRegs.GPASET.bit.GPIO23 = 1; // Load output latch
// GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 0; //
// GpioCtrlRegs.GPADIR.bit.GPIO23 = 1; // GPIO27 = output
GpioCtrlRegs.GPAPUD.bit.GPIO24 = 0;// Enable pullup
GpioDataRegs.GPASET.bit.GPIO24 = 1; // Load output latch
GpioCtrlRegs.GPAMUX2.bit.GPIO24 = 0; //
GpioCtrlRegs.GPADIR.bit.GPIO24 = 1; // GPIO27 = output
// GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 2; // GPIO23 is MFSXA pin
// GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0; // Enable pull-up on GPIO23 (MFSXA)
// GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 3; // Asynch input GPIO23 (MFSXA)
以下是连续SPI数据传输的示例代码,可以在使用WIZ_mcbsp_init函数初始化完成端口并短接DX和DR数据输入输出接口后循环调用下面代码查看数据波形检查数据正确性
int aaa = 66;
WIZ_MCBSP_CS(0);
aaa = MCBSP_SendByte(2);
aaa = MCBSP_SendByte(4);
aaa = MCBSP_SendByte();
WIZ_MCBSP_CS(1);
DELAY_US(8);