工具/软件:Code Composer Studio
您好!
我正在尝试使用 DMA 从外部器件连续读取 Rx SPIB 数据并输出到 SCIA。
我能够通过组合"spi_loopback _dma_cpu01"和"sci_echoback_cpu01"示例来创建工作代码。
但是、我发现我只能读取一次数据。 DMA "local_D_INTCH6_ISR"回调仅触发一次。
每次传输时、外部器件重复发送 SPI 数据115、200字节。 我打算以较小的块(例如1024字节)读取传入数据、输出到 SCI、然后重构数据。
我不确定需要进行哪些更改才能连续读取 Rx SPI-DMA。
你能提供建议吗? 非常感谢。
以下是我的代码:
//
//包含的文件
//
#include "F28x_Project.h"
//
//定义
//
#define MEM_buffer_size 1024
#define BURST (FIFO_LVL-1)//突发大小应小于8
#define 传输(MEM_BACK_SIZE /FIFO_LVL)-1 //[(MEM_BACK_SIZE /FIFO_LVL)-1]
#define FIFO_LVL 8 // FIFO 中断级别
#if CPU_FRQ_200MHz
#define SPI_BRR ((200E6/4)/500E3)- 1.
#endif
#if CPU_FRQ_150MHz
#define SPI_BRR ((150E6/4)/500E3)- 1.
#endif
#if CPU_FRQ_120MHz
#define SPI_BRR ((120E6/4)/500E3)- 1.
#endif
//
//全局
//
#pragma DATA_SECTION (sdata、"ramgs0");//将 TX 数据映射到存储器
#pragma DATA_SECTION (RDATA、"ramgs1");//将 RX 数据映射到存储器
uint16 sdata[MEM_buffer_size];//发送数据缓冲区
uint16 RDATA[MEM_buffer_size];//接收数据缓冲区
uint16 gData[MEM_buffer_size];
uint16 RDATA_POINT;//跟踪我们的位置
//在数据流中检查接收到的数据
易失性 uint16 * DMADest;
易失性 uint16 * DMASSOURCE;
易失性 uint16完成;
//
//函数原型
//
_interrupt void local_D_INTCH5_ISR (void);
_interrupt void local_D_INTCH6_ISR (void);
void delay_loop (void);
void InitSpibGpio (void);
void dma_init (void);
void SPI_Fifo_init (void);
void InitSpiB (void);
void error();
void scia_echoback_init (void);
void scia_fifo_init (void);
void scia_xmit (int a);
void scia_msg (char * msg);
//
//主函
//
void main (void)
{
uint16 i;
//
//步骤1. 初始化系统控制:
// PLL、安全装置、启用外设时钟
//此示例函数位于 F2837xD_SYSCTRL.c 文件中。
//
InitSysCtrl();
//
//步骤2. 初始化 GPIO:
//此示例函数位于 F2837xD_GPIO.c 文件和中
//说明了如何将 GPIO 设置为其默认状态。
//仅为 SPI-B 功能设置 GP I/O
//
InitGpio();
GPIO_SetupPinMux (43、GPIO_MUX_CPU1、15);
GPIO_SetupPinOptions (43、GPIO_INPUT、GPIO_PushPull);
GPIO_SetupPinMux (42、GPIO_MUX_CPU1、15);
GPIO_SetupPinOptions (42、GPIO_output、GPIO_Async);
InitSpibGpio();
//
//步骤3. 初始化 PIE 矢量表:
//禁用并清除所有 CPU 中断
//
Dint;
IER = 0x0000;
IFR = 0x0000;
//
//将 PIE 控制寄存器初始化为默认状态:
//此函数位于 F2837xD_PIECTRL.c 文件中。
//
InitPieCtrl();
//
//使用指向 shell 中断的指针初始化 PIE 矢量表
//服务例程(ISR)。
//这将填充整个表,即使是中断也是如此
//在本例中未使用。 这对于调试很有用。
//可以在 F2837xD_DefaultIsr.c 中找到 shell ISR 例程
//此函数可在 F2837xD_PieVect.c 中找到
//
InitPieVectTable();
scia_fifo_init();//初始化 SCI FIFO
scia_echoback_init ();//初始化用于 echoback 的 SCI
//
//此示例中使用的中断被重新映射到
//此文件中的 ISR 函数。
//
EALLOW;//这是写入 EALLOW 受保护寄存器所必需的
PieVectTable.DMA_CH5_INT=&LOCAL_D_INTCH5_ISR;
PieVectTable.DMA_CH6_INT=&LOCAL_D_INTCH6_ISR;
EDIS;//这是禁止写入 EALLOW 受保护寄存器所必需的
//
//步骤4. 初始化器件外设:
//
dma_init ();//为 SPI 配置设置 DMA
SPI_Fifo_init();//仅初始化 SPI
//
//确保 DMA 连接到外设帧2桥接器(EALLOW 受保护)
//
EALLOW;
CpuSysRegs.SECMSEL.bit.PF2SEL = 1;
EDIS;
//
//步骤5. 特定于用户的代码、启用中断:
//
//
//初始化数据缓冲区
//
for (i=0;<MEM_BUFFER_SIZE; i++)
{
sdata[i]= i;
RDATA[i]= 0;
gData[i]= 0;
}
RDATA_POINT = 0;
//
//启用此示例所需的中断
//
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;//启用 PIE 块
PieCtrlRegs.PIEIER7.bit.INTx5 = 1;//启用 PIE 组7、INT 1 (DMA CH1)
PieCtrlRegs.PIEIER7.bit.INTx6 = 1;//启用 PIE 组7、INT 2 (DMA CH2)
IER = M_INT7;//启用 CPU INT6
EINT;//启用全局中断
char *msg;
MSG ="\r\n\n\nHello World!\0";
scia_msg (msg);
ESTOP0;
StartDMACH6 ();//启动 SPI RX DMA 通道
StartDMACH5 ();//启动 SPI TX DMA 通道
while (1)
{
DONE = 0;//测试尚未完成
while (!done);//等待 DMA 传输完成
//完成
对于(I = 0;I < MEM_BUFFER_SIZE;+I)
{
scia_xmit (gData[i]);
}
// StartDMACH6 ();//启动 SPI RX DMA 通道
// StartDMACH5 ();//启动 SPI TX DMA 通道
// SpibRegs.SPIFFTX.bit.TXFIFO = 0;
// SpibRegs.SPIFFTX.bit.TXFIFO = 1;
// SpibRegs.SPIFFRX.bit.RXFIFORESET = 0;
// SpibRegs.SPIFFRX.bit.RXFIFORESET = 1;
//
// DMA 传输完成后,程序将在此处停止
//
// ESTOP0;
};
}
//
// delay_loop -添加延迟的函数
//
void delay_loop ()
{
长 I;
对于(i = 0;i < 1000000;i++){}
}
//
//错误-收到错误时停止调试器
//
空错误(空)
{
asm (" ESTOP0");//测试失败!!! 停下来!
适用于(;);
}
//
// InitSpibGpio -初始化 SPIB GPIO
//
空 InitSpibGpio()
{
EALLOW;
//
//为所选引脚启用内部上拉
//
//用户可以启用或禁用上拉。
//这将启用指定引脚的上拉电阻。
//注释掉其他不需要的行。
//
GpioCtrlRegs.GPBPUD.bit.GPIO63 = 0;//启用 GPIO16上的上拉电阻器(SPISIMOA)
GpioCtrlRegs.GPCPUD.bit.GPIO64 = 0;//启用 GPIO17上的上拉电阻器(SPISOMIA)
GpioCtrlRegs.GPCPUD.bit.GPIO65 = 0;//启用 GPIO18上的上拉电阻器(SPICLKA)
GpioCtrlRegs.GPCPUD.bit.GPIO66 = 0;//启用 GPIO19上的上拉电阻器(SPISTEA)
//
//仅将所选引脚的限定条件设置为异步
//
//这将为所选引脚选择异步(无限定条件)。
//注释掉其他不需要的行。
//
GpioCtrlRegs.GPBQSEL2.bit.GPIO63 = 3;//异步输入 GPIO16 (SPISIMOA)
GpioCtrlRegs.GPCQSEL1.bit.GPIO64 = 3;//异步输入 GPIO17 (SPISOMIA)
GpioCtrlRegs.GPCQSEL1.bit.GPIO65 = 3;//异步输入 GPIO18 (SPICLKA)
GpioCtrlRegs.GPCQSEL1.bit.GPIO66 = 3;//异步输入 GPIO19 (SPISTEA)
//
//使用 GPIO 寄存器配置 SPI-A 引脚
//
//这指定哪些可能的 GPIO 引脚将是 SPI 功能
//引脚。
//注释掉其他不需要的行。
//
GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 3;//将 GPIO63配置为 SPISIMOB
GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 3;//将 GPIO64配置为 SPISOMIB
GpioCtrlRegs.GPCMUX1.bit.GPIO65=3;//将 GPIO65配置为 SPICLKB
GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 3;//将 GPIO66配置为 SPISTEB
GpioCtrlRegs.GPBGMUX2.bit.GPIO63 = 3;//将 GPIO63配置为 SPISIMOB
GpioCtrlRegs.GPCGMUX1.bit.GPIO64 = 3;//将 GPIO64配置为 SPISOMIB
GpioCtrlRegs.GPCGMUX1.bit.GPIO65=3;//将 GPIO65配置为 SPICLKB
GpioCtrlRegs.GPCGMUX1.bit.GPIO66 = 3;//将 GPIO66配置为 SPISTEB
EDIS;
}
//
// SPI_Fifo_init -初始化 SPIB FIFO
//
void SPI_Fifo_init()
{
/*
//
//初始化 SPI FIFO 寄存器
//
SpiaRegs.SPIFFRX.All=0x2040;//启用 RX FIFO、清除 FIFO 内部
SpiaRegs.SPIFFRX.bit.RXFFIL = FIFO_LVL;//设置 RX FIFO 电平
SpiaRegs.SPIFFTX.All=0xE040;// FIFO 被启用、TX FIFO 被释放、
SpiaRegs.SPIFFTX.bit.TXFFIL = FIFO_LVL;//设置 TX FIFO 电平
*
SpibRegs.SPIFFRX.All=0x2040;//启用 RX FIFO、清除 FIFO 内部
SpibRegs.SPIFFRX.bit.RXFFIL = FIFO_LVL;//设置 RX FIFO 电平
// SpibRegs.SPIFFRX.bit.RXFFIENA=1;//设置 RX FIFO 电平
SpibRegs.SPIFFTX.All=0xE040;// FIFO 被启用、TX FIFO 被释放、
SpibRegs.SPIFFTX.bit.TXFFIL = FIFO_LVL;//设置 TX FIFO 级别*/
// SpibRegs.SPIFFTX.bit.TXFFIENA=1;//设置 TX FIFO 级别*/
/*
0 0 1 00000 0 1 0 00000
struct SPIFFRX_bits{// bits description
UINT16 RXFFIL:5;// 4:0 RXFIFO 中断级别
UINT16 RXFFIENA:1;// 5 RXFIFO 中断使能
UINT16 RXFFINTCLR:1;// 6 RXFIFO 中断清零
UINT16 RXFFINT:1;// 7 RXFIFO 中断标志
UINT16 RXFFST:5;// 12:8接收 FIFO 状态
UINT16 RXFIFORESET:1;// 13 RXFIFO 复位
UINT16 RXFFOVFCLR:1;// 14接收 FIFO 上溢清零
UINT16 RXFFOVF:1;// 15接收 FIFO 上溢标志
};
struct SPIFFTX_bits{// bits description
UINT16 TXFFIL:5;// 4:0 TXFIFO 中断级别
UINT16 TXFFIENA:1;// 5 TXFIFO 中断使能
UINT16 TXFFINTCLR:1;// 6 TXFIFO 中断清除
UINT16 TXFFINT:1;// 7 TXFIFO 中断标志
UINT16 TXFFST:5;// 12:8发送 FIFO 状态
UINT16 TXFIFO:1;// 13 TXFIFO 复位
UINT16 SPIFFENA:1;// 14 FIFO 增强使能
UINT16 SPIRST:1;// 15 SPI 复位
};
*
//
//初始化内核 SPI 寄存器
//
InitSpiB();
}
空 InitSpiB (空)
{
//初始化 SPI-A
//在配置更改之前将 RESET 设置为低电平
//时钟极性(0 =上升、1 =下降)
// 16位字符
SpibRegs.SPICCR.bit.SPISWRESET = 0;
SpibRegs.SPICCR.bit.CLKPOLARITY = 0;
// SpibRegs.SPICCR.bit.SPICHAR =(16-1);
SpibRegs.SPICCR.bit.SPICHAR =(8-1);
//启用环回
SpibRegs.SPICCR.bit.SPILBK = 0;
//启用主设备(0 =从设备,1 =主设备)
//启用传输(TALK)
//时钟相位(0 =正常、1 =延迟)
//禁用 SPI 中断
SpibRegs.SPICTL.bit.MASTER_SLAVE = 0;
SpibRegs.SPICTL.bit.TALK = 1;
SpibRegs.SPICTL.bit.CLK_PHASE = 0;
SpibRegs.SPICTL.bit.SPIINTENA=0;
//设置波特率
SpibRegs.SPIBRR.bit.SPI_BIT_RATE = SPI_BRR;
//设置空闲位
//在断点上停止不会停止 SPI
SpibRegs.SPIPRI.bit.FREE = 1;
//解除 SPI 复位
SpibRegs.SPICCR.bit.SPISWRESET = 1;
}
//
// dma_init - TX 和 RX 通道的 DMA 设置。
//
void dma_init()
{
//
//初始化 DMA
//
DMAInitialize();
DMASource =(volatile UINT16 *) sdata;
DMADest =(易失性 UINT16 *) RDATA;
/*
//
//为 TX 配置 DMACH5
//
DMACH5AddrConfig (SpiaRegs.SPITXBUF、DMASource);
DMACH5BurstConfig (burst、1、0);// burst size、src step、dest step
DMACH5TransferConfig (transfer、1、0);//传输大小、src 阶跃、dest 阶跃
DMACH5ModeConfig (DMA_SPIATX、PERINT_ENABLE、OneShot_disable、CONT_disable、
SYNC_DISABLE、SYNC_SRC、OVRFLOW_DISABLE、十六位、
Chint_end、CHINT_ENABLE);
//
//为 RX 配置 DMA CH2
//
DMACH6AddrConfig (DMADest、SpiaRegs.SPIRXBUF);
DMACH6BurstConfig (突发、0、1);
DMACH6TransferConfig (传输、0、1);
DMACH6ModeConfig (DMA_SPIARX、PERINT_ENABLE、OneShot_disable、CONT_disable、
SYNC_DISABLE、SYNC_SRC、OVRFLOW_DISABLE、十六位、
Chint_end、CHINT_ENABLE);
*
//
//为 TX 配置 DMACH5
//
DMACH5AddrConfig (SpibRegs.SPITXBUF、DMASource);
DMACH5BurstConfig (burst、1、0);// burst size、src step、dest step
DMACH5TransferConfig (transfer、1、0);//传输大小、src 阶跃、dest 阶跃
DMACH5ModeConfig (DMA_SPIBTX、PERINT_ENABLE、OneShot_disable、CONT_disable、
// DMACH5ModeConfig (DMA_SPIBTX、PERINT_ENABLE、OneShot_disable、CONT_ENABLE、
SYNC_DISABLE、SYNC_SRC、OVRFLOW_DISABLE、十六位、
Chint_end、CHINT_ENABLE);
//
//为 RX 配置 DMA CH2
//
DMACH6AddrConfig (DMADest、SpibRegs.SPIRXBUF);
DMACH6BurstConfig (突发、0、1);
DMACH6TransferConfig (传输、0、1);
DMACH6ModeConfig (DMA_SPIBRX、PERINT_ENABLE、OneShot_disable、CONT_disable、
// DMACH6ModeConfig (DMA_SPIBRX、PERINT_ENABLE、OneShot_disable、CONT_ENABLE、
SYNC_DISABLE、SYNC_SRC、OVRFLOW_DISABLE、十六位、
Chint_end、CHINT_ENABLE);
}
//
// local_D_INTCH5_ISR - DMA 通道5 ISR
//
_interrupt void local_D_INTCH5_ISR (void)
{
EALLOW;//需要在 ISR 内执行 EALLOW!!!
DMARegs.CH5.CONTL.BIT.HALT=1;
// DmaRegs.ch5.control.bit.TRANSFERSTS = 1;
// DmaRegs.ch5.control.bit.run = 1;
PieCtrlRegs.PIEACK.all = PIEACK_group7;// ACK 以接收更多中断
//来自此 PIE 组
// DmaRegs.ch6.control.bit.halt = 0;
EDIS;
返回;
}
//
// local_D_INTCH6_ISR - DMA 通道6 ISR
//
_interrupt void local_D_INTCH6_ISR (void)
{
uint16 i;
EALLOW;//需要在 ISR 内执行 EALLOW!!!
DmaRegs.ch6.control.bit.halt = 1;
PieCtrlRegs.PIEACK.all = PIEACK_group7;// ACK 以接收更多中断
//来自此 PIE 组
对于(I = 0;I < MEM_BUFFER_SIZE;+I)
{
gData[i]= RDATA[i]和0x00FF;
// scia_xmit (RDATA[i]& 0x00FF);
}
// DmaRegs.ch5.control.bit.TRANSFERSTS = 1;
// DmaRegs.ch5.control.bit.run = 1;
DONE = 1;//测试完成。
// DmaRegs.ch6.control.bit.halt = 0;
EDIS;
返回;
}
//
// scia_echoback_init -测试1、SCIA DLB、8位字、波特率0x000F、
//默认,1个停止位,无奇偶校验
//
void scia_echoback_init ()
{
//
//注意:SCIA 外设的时钟被打开
//在 InitSysCtrl()函数中
//
SciaRegs.SCICCR.all = 0x0007;// 1停止位,无回路
//无奇偶校验,8个字符位,
//异步模式,空闲线协议
SciaRegs.SCICTL1.all = 0x0003;//启用 TX、RX、内部 SCICLK、
//禁用 RX ERR、睡眠、TXWAKE
SciaRegs.SCICTL2.all = 0x0003;
SciaRegs.SCICTL2.bit.TXINTENA=1;
SciaRegs.SCICTL2.bit.RXBKINTENA=1;
//
// SCIA 为9600波特
//@LSPCLK = 50MHz (200MHz SYSCLK) HBAUD = 0x02且 LBAUD = 0x8B。
//@LSPCLK = 30MHz (120MHz SYSCLK) HBAUD = 0x01且 LBAUD = 0x86。
//
// SciaRegs.SCIHBAUD.ALL = 0x0002;
// SciaRegs.SCILBAUD.ALL = 0x008B;
SciaRegs.SCIHBAUD.ALL = 0x0000;
SciaRegs.SCILBAUD.ALL = 0x0002;
SciaRegs.SCICTL1.all = 0x0023;//从复位中撤回 SCI
}
//
// scia_xmit -从 SCI 发送一个字符
//
void scia_xmit (int a)
{
while (SciaRegs.SCIFFTX.bit.TXFFST!= 0){}
SciaRegs.SCITXBUF.ALL =A;
}
//
// scia_msg -通过 SCIA 发送消息
//
void scia_msg (char * msg)
{
int i;
I = 0;
while (msg[i]!='\0')
{
scia_xmit (msg[i]);
i++;
}
}
//
// scia_fifo_init -初始化 SCI FIFO
//
void scia_fifo_init()
{
SciaRegs.SCIFFTX.ALL = 0xE040;
SciaRegs.SCIFFRX.ALL = 0x2044;
SciaRegs.SCIFFCT.all = 0x0;
}
//
//文件结束
//