SPI+DMA每帧数据的时间间隔问题
硬件:屠龙刀。SYSCLK=24Mhz,SPICLK=12Mhz。主从模式,开启SPIDMA中断,未开启SPI中断现象:CS和SCLK启动的时间是740ns,每帧数据之间的时间是1.07us。只用SPI不用DMA时间也长。
请教问题:间隔时间不应该这么长吧,效率太低了。是代码问题,还是STC32G硬件问题? 如何修改
主机代码:
#include "stc.h"
#include "stc32g.h"
#include "usb.h"
#include "intrins.h"
sbit SS =P7^4;
volatile u16 i;
void sys_init();
void DMA_Config(void);
//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
u8 xdata DmaTxBuffer; //_at_ DMA_TX_ADDR;
u8 xdata DmaRxBuffer; //_at_ DMA_RX_ADDR;
void delay ()
{
int i;
for (i=0;i<10000;i++);
}
//主函数=================================================================
void main()
{
sys_init();
usb_init();//USB初始化
SS = 1;
//端口设置:01是推挽,10是高阻,11是开漏
P3M1 |= 0x03; P3M0 &= ~0x03; //设为高阻//&是置0,|是置1
// P5M1 &= ~0x10; P5M0 |= 0x10; //P5.4口设为推挽
P5M1 |= 0x10; P5M0 &= ~0x10; //P5.4口设为高阻
P1M1 &= ~0x40; P1M0 |= 0x40; //P1.6口设为推挽
P1SR &= ~0x40; //P1.6口电平转换速度快P293
P1DR &= ~0x40; //P1.6口电流驱动能力强
P25 = 0;
P26 = 0;
P27 = 0;
SPI_S1 = 1; SPI_S0 = 0;//切换到P54/P40/P41/P43
SPCTL = 0xd7; //使能SPI主机模式,默认速度/4
SPSTAT = 0xc0; //清中断标志
HSSPI_CFG2 |=0x20; //速度/2必须开启高速模式
// ESPI = 1; //使能SPI中断
DMA_Config();
EA = 1;
for(i = 0 ;i < 256;i++) // 128个字符
{
DmaTxBuffer = 0x55; // 128个字符,为128个ASCII字符
}
while (1)
{
if (!P32)
{
while (!P32);
SS = 0; //拉低从机SS管脚
DMA_SPI_CR = 0xc1; //启动DMA主机模式操作,接收数据
P20 = ~P20;
}
}
}
void sys_init()
{
WTST = 0x00;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0x00; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //
P1M1 = 0x00; P1M0 = 0x00; //
P2M1 = 0x00; P2M0 = 0x00; //
P3M1 = 0x00; P3M0 = 0x00; //
P4M1 = 0x00; P4M0 = 0x00; //
P5M1 = 0x00; P5M0 = 0x00; //
P6M1 = 0x00; P6M0 = 0x00; //
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
//设置USB使用的时钟源
IRC48MCR = 0x80; //使能内部48M高速IRC
while (!(IRC48MCR & 0x01)); //等待时钟稳定
USBCLK = 0x00; //使用CDC的时候开启这两行代码才行
USBCON = 0x90; //使用CDC的时候开启这两行代码才行
CLKSEL = 0x00; //强制一下把SPI的时钟源变成主时钟MCLK
CLKDIV = 0x00; //主时钟MCLK给SYSCLK的分频,是ISP指定的,所以手动定一个倍数
HSCLKDIV = 0x00; //初始化默认是0x02,就是/2.所以变成1分频
}
//========================================================================
// 函数: void DMA_Config(void)
// 描述: SPI DMA 功能配置.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2021-5-6
//========================================================================
void DMA_Config(void)
{
DMA_SPI_STA = 0x00;
DMA_SPI_CFG = 0xE0; //bit7 1:Enable Interrupt
DMA_SPI_AMT = 0xff; //设置传输总字节数:n+1
DMA_SPI_TXAH = (u8)((u16)&DmaTxBuffer >> 8); //SPI发送数据存储地址
DMA_SPI_TXAL = (u8)((u16)&DmaTxBuffer);
DMA_SPI_RXAH = (u8)((u16)&DmaRxBuffer >> 8); //SPI接收数据存储地址
DMA_SPI_RXAL = (u8)((u16)&DmaRxBuffer);
DMA_SPI_CFG2 = 0x06; //01:P2.2
DMA_SPI_CR = 0x81; //bit7 1:使能 SPI_DMA, bit6 1:开始 SPI_DMA 主机模式, bit0 1:清除 SPI_DMA FIFO
}
//========================================================================
// 函数: void SPI_DMA_Interrupt (void) interrupt 49
// 描述: SPI DMA中断函数
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2021-5-8
// 备注:
//========================================================================
void SPI_DMA_Interrupt(void) interrupt 13
{
SS = 1;
DMA_SPI_STA = 0x00;
P24 = ~P24;
}
是不是有一种被欺骗的感觉,没错,硬件SPI就是这个速度,如果不用DMA,我用软件模拟都比它快。 开启高速SPI的FIFO模式使能,并减少高速SPI的HOLD时间与SETUP时间。
这些参数对普通SPI+DAM通信也是有效的。
本帖最后由 leitong 于 2023-6-1 00:01 编辑
看手册上的HSSPI章节的范例程序,没有使能FIFOEN,所以程序里没写。使能FIFOEN,是有所改善,还是不太理想。SS_HLD和SS_SETUP和SS_DACT参数设成0x33~0x00,是一个结果,最短时间570ns,0x44~0x77是一个结果,900ns,0x88是1.24us DMA模式开启FIFO,CLK脚不连续最小间隔1.5T的CLK时钟
void DMA_Config(void)
{
DMA_SPI_STA = 0x00;
DMA_SPI_CFG = 0xE0; //bit7 1:Enable Interrupt
DMA_SPI_AMT = 0xff; //设置传输总字节数:n+1
DMA_SPI_TXAH = (u8)((u16)&DmaTxBuffer >> 8); //SPI发送数据存储地址
DMA_SPI_TXAL = (u8)((u16)&DmaTxBuffer);
DMA_SPI_RXAH = (u8)((u16)&DmaRxBuffer >> 8); //SPI接收数据存储地址
DMA_SPI_RXAL = (u8)((u16)&DmaRxBuffer);
DMA_SPI_CFG2 = 0x01; //01:P2.2
DMA_SPI_CR = 0x80; //bit7 1:使能 SPI_DMA, bit6 1:开始 SPI_DMA 主机模式, bit0 1:清除 SPI_DMA FIFO
HSSPI_CFG = 0x00;//高速模式时SS 控制信号的HOLD 和SETUP 时间设置0,CLK最小间隔1.5T
HSSPI_CFG2 = 0x00; //高速模式时SS 控制信号的DEACTIVE 时间设置0,CLK最小间隔1.5T
HSSPI_CFG2 |= 1<<5; //使能SPI高速模式
}SPI通讯,普通模式和DMA模式混用的时候一定要注意FIFO的禁用和使能。普通模式,必须禁用FIFO,否则死机。void SPI_WriteByte(u8 out)
{
HSSPI_CFG2 &= ~0x10; //禁止FIFO,不然普通模式死机
SPDAT = out;
SPIF = 1; //清SPIF标志,防止DMA混用出问题,DMA最后完成,标志位会置位的。
while(SPIF == 0);
SPIF = 1; //清SPIF标志
WCOL = 1; //清WCOL标志
}
本帖最后由 BFMIPBWVFP 于 2024-7-18 10:28 编辑
dma传输时打开FIFO,即HSSPI_CFG2=0x30.两个数据间距是可以明显减小,24M主频时要两个周期。
页:
[1]