找回密码
 立即注册
查看: 870|回复: 4

SPI+DMA每帧数据的时间间隔问题

[复制链接]

该用户从未签到

1

主题

5

回帖

555

积分

高级会员

积分
555
发表于 2023-5-27 11:47:45 | 显示全部楼层 |阅读模式
硬件:屠龙刀。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[256]; //_at_ DMA_TX_ADDR;
u8 xdata DmaRxBuffer[256]; //_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[i] = 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;
       
}


CS到SCLK启动时间

CS到SCLK启动时间

每帧数据的间隔时间

每帧数据的间隔时间
回复 送花

使用道具 举报

该用户从未签到

0

主题

1

回帖

64

积分

注册会员

积分
64
发表于 2023-5-30 22:48:44 | 显示全部楼层
是不是有一种被欺骗的感觉,没错,硬件SPI就是这个速度,如果不用DMA,我用软件模拟都比它快。
回复 支持 反对 送花

使用道具 举报

  • TA的每日心情
    奋斗
    昨天 08:59
  • 签到天数: 143 天

    [LV.7]常住居民III

    27

    主题

    1343

    回帖

    4187

    积分

    论坛元老

    积分
    4187
    发表于 2023-5-31 16:08:46 | 显示全部楼层
    开启高速SPI的FIFO模式使能,并减少高速SPI的HOLD时间与SETUP时间。

    1.png

    这些参数对普通SPI+DAM通信也是有效的。
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    1

    主题

    5

    回帖

    555

    积分

    高级会员

    积分
    555
     楼主| 发表于 2023-5-31 23:59:36 | 显示全部楼层
    本帖最后由 leitong 于 2023-6-1 00:01 编辑

    看手册上的HSSPI章节的范例程序,没有使能FIFOEN,所以程序里没写。使能FIFOEN,是有所改善,还是不太理想。SS_HLD和SS_SETUP和SS_DACT参数设成0x33~0x00,是一个结果,最短时间570ns,0x44~0x77是一个结果,900ns,0x88是1.24us
    每帧数据的间隔时间2.png
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    11

    主题

    331

    回帖

    886

    积分

    荣誉版主

    积分
    886
    发表于 2023-7-11 21:21:43 | 显示全部楼层
    DMA模式开启FIFO,CLK脚不连续最小间隔1.5T的CLK时钟

    1. void DMA_Config(void)
    2. {
    3.         DMA_SPI_STA = 0x00;
    4.         DMA_SPI_CFG = 0xE0;                //bit7 1:Enable Interrupt
    5.         DMA_SPI_AMT = 0xff;                //设置传输总字节数:n+1
    6.         DMA_SPI_TXAH = (u8)((u16)&DmaTxBuffer >> 8);        //SPI发送数据存储地址
    7.         DMA_SPI_TXAL = (u8)((u16)&DmaTxBuffer);
    8.         DMA_SPI_RXAH = (u8)((u16)&DmaRxBuffer >> 8);        //SPI接收数据存储地址
    9.         DMA_SPI_RXAL = (u8)((u16)&DmaRxBuffer);
    10.         DMA_SPI_CFG2 = 0x01;        //01:P2.2
    11.         DMA_SPI_CR = 0x80;                //bit7 1:使能 SPI_DMA, bit6 1:开始 SPI_DMA 主机模式, bit0 1:清除 SPI_DMA FIFO
    12.    
    13.     HSSPI_CFG = 0x00;  //高速模式时SS 控制信号的HOLD 和SETUP 时间设置0,CLK最小间隔1.5T
    14.     HSSPI_CFG2 = 0x00; //高速模式时SS 控制信号的DEACTIVE 时间设置0,CLK最小间隔1.5T
    15.     HSSPI_CFG2 |= 1<<5;         //使能SPI高速模式
    16. }
    复制代码
    SPI通讯,普通模式和DMA模式混用的时候一定要注意FIFO的禁用和使能。
    普通模式,必须禁用FIFO,否则死机。
    1. void SPI_WriteByte(u8 out)
    2. {
    3.     HSSPI_CFG2 &= ~0x10;        //禁止FIFO,不然普通模式死机
    4.     SPDAT = out;
    5.     SPIF = 1;   //清SPIF标志,防止DMA混用出问题,DMA最后完成,标志位会置位的。
    6.     while(SPIF == 0);
    7.     SPIF = 1;   //清SPIF标志
    8.     WCOL = 1;   //清WCOL标志
    9. }
    复制代码



    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-18 21:40 , Processed in 0.063226 second(s), 47 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表