wuzhengmin 发表于 2026-6-20 18:52:34

AICube 生成的系统,SPI初始化中不能直接位操作?

请教AICube 设置问题:


我在原来的项目中,SPI的初始化是用AICube自动生成:



    SPI_SwitchP3n();                  //选择SPI数据口: SS(P3.5), MOSI(P3.4), MISO(P3.3), SCLK(P3.2)
    SPI_SwapMosiMiso();               //交换MISO和MOSI功能脚

    SPI_MasterMode();                   //设置SPI为主机模式
    SPI_IgnoreSS();                     //忽略SS脚
    SPI_DataMSB();                      //设置SPI数据顺序为MSB (高位在前)
    SPI_SetMode3();                     //设置SPI工作模式3 (CPOL=1, CPHA=1)
    SPI_SetClockDivider4();             //设置SPI时钟分频


//   SPI_Enable();                     //使能SPI功能

    DMA_SPI_AutoSS();                   //使能SPI DMA自动控制SS
    DMA_SPI_SetAutoSSP35();             //DMA自动控制SS (P3.5)
    DMA_SPI_SetAmount(SPI_DMASIZE - 1); //设置SPI DMA发送/接收字节数
    DMA_SPI_SetTxAddress(pu8SPIDMATxBuffer); //设置SPI DMA发送缓冲区地址
    DMA_SPI_SetInterval(SPI_DMAITV);    //设置SPI DMA发送/接收字节间隔时间(系统时钟)
    DMA_SPI_ClearFIFO();                //清空SPI DMA FIFO缓冲区
    DMA_SPI_ClearFlag();                //清除SPI DMA中断标志
    DMA_SPI_EnableTx();               //使能发送数据
    DMA_SPI_DisableRx();                //禁止接收数据
    DMA_SPI_SetBusPriority(0);          //设置总线访问为最低优先级
    DMA_SPI_SetIntPriority(0);          //设置中断为最低优先级
    DMA_SPI_EnableInt();                //使能SPI DMA中断
    DMA_SPI_Enable();                   //使能SPI DMA功能
//DMA_SPI_MasterTrigger();            //触发SPI主机DMA

    //<<AICUBE_USER_SPI_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    HSSPI_CFG= SS_HOLD | SS_SETUP;    // 根据实际需求调整SS_HLD和SS_SETUP值
    HSSPI_CFG2 = SPI_IOSW | HSSPIEN | FIFOEN | SS_DACT;
       
       
    DMA_SPI_ITVH = 0; //SPI DMA 传输间隔时间寄存器
    DMA_SPI_ITVL = 9; // 8--9加大间隔,牺牲一点速度换稳定性8
    //DMA_SPI_CFG = DMA_SPIIE | SPI_ACT_TX;       // 去掉SPI_ACT_RX,只发不收
        SPI_Enable();                     //使能SPI功能
       
        fSPIDMABusy = 0; // 清除DMA传输忙标志
    //<<AICUBE_USER_SPI_INITIAL_END>>


现在系统运行后有卡死现象,有大侠是用寄存器方法初始化,程序如下:

SPI_S1= 1; //00: P1.4 P1.5 P1.6 P1.7, 01: P2.4 P2.5 P2.6 P2.7, 10: P4.0 P4.1 P4.2 P4.3, 11: P3.5 P3.4 P3.3 P3.2
SPI_S0= 1; //SPI显示屏接口选择 11: P3.5 P3.4 P3.3 P3.2

SSIG = 1;//1: 忽略SS脚,由MSTR位决定主机还是从机    0: SS脚用于决定主机还是从机。
SPEN = 1;//1: 允许SPI, 0:禁止SPI,所有SPI管脚均为普通IO
DORD = 0;//1:LSB先发, 0:MSB先发(高位在前)
MSTR = 1;//1:设为主机0:设为从机
CPOL = 1;//1: 空闲时SCLK为高电平,0:空闲时SCLK为低电平
CPHA = 1;//1: 数据在SCLK前沿驱动,后沿采样. 0: 数据在SCLK前沿采样,后沿驱动.
SPCTL = (SPCTL & ~3) | 3; //SPI 时钟频率选择,0:4T,1:8T,2:16T,3:2T
HSCLKDIV   = 1;//HSCLKDIV主时钟分频
SPI_CLKDIV = 1;//SPI_CLKDIV主时钟分频

如果我直接替换,编译就报错:

compiling uart.c...
compiling spi.c...
Sources\spi.c(41): error C100: '=': left operand must be l-value
Sources\spi.c(42): error C100: '=': left operand must be l-value
Sources\spi.c(43): error C100: '=': left operand must be l-value
Sources\spi.c(44): error C100: '=': left operand must be l-value
Sources\spi.c(45): error C100: '=': left operand must be l-value
Sources\spi.c(46): error C100: '=': left operand must be l-value
compiling qspi.c...
Target not created.

换成直接操作寄存器:


        SPCTL = 0xDF;      // SSIG=1, SPEN=1, DORD=0, MSTR=1, CPOL=1, CPHA=1, SPR1=1, SPR0=1
        HSCLKDIV = 1;      // 主时钟分频
        SPI_CLKDIV = 1;      // SPI时钟分频
       
      SPSTAT = 0xC0;// 同时清除 SPIF 和 WCOL,干净利落


可以编译,但烧录后TFT直接黑屏,用原来AiCube生成的不会黑屏,是运行几次后卡死

有大侠知道为什么不能在AIcube 生成的系统中直接位操作,换成寄存器操作能过编译,但也是直接黑屏呢?

梁工 发表于 2026-6-20 22:15:51

什么型号的? 32位的可以位寻址。

狂热主宰 发表于 2026-6-20 23:05:30

梁工 发表于 2026-6-20 22:15
什么型号的? 32位的可以位寻址。

部分寄存器可位操作

神农鼎 发表于 2026-6-21 12:21:19







梁工 发表于 2026-6-21 15:07:03

狂热主宰 发表于 2026-6-20 23:05
部分寄存器可位操作

我是指寄存器地址非0或8结尾的,32位的可以位操作,8位的不能。

wuzhengmin 发表于 2026-6-21 18:11:35

神农鼎 发表于 2026-6-21 12:21


感谢!感谢!我慢慢研究一下!

wuzhengmin 发表于 2026-6-21 18:12:15

梁工 发表于 2026-6-21 15:07
我是指寄存器地址非0或8结尾的,32位的可以位操作,8位的不能。

哦哦,我没有注意的这个差别!感谢感谢!

神农鼎 发表于 2026-6-21 19:57:09












wuzhengmin 发表于 2026-6-22 17:32:28

神农鼎 发表于 2026-6-21 19:57

对,感谢神农鼎大侠的指导!

      
   神农鼎大侠及STC的各位工程师,我现在使用了一段时间的AICube ,有点依赖了,这段时间在折腾TFT彩屏,主要是玩一下桥接:

用QSPI从W25q128 读出图片数据,P2P桥接后直接用SPI给TFT_ILIst7789 240*240

图片直接用冲哥的13张猫和老鼠的图片,然后把浦江一水老师的LCM桥接直接稍作修改,放到SPI桥接上

开始的架子是用AiCube搞的,现在是程序可以跑起来,但是不能精确控制,程序现在一离开主菜单,执行浏览图片后

再回到主菜单就跑飞啦!

尝试在原来的基础上修改打磨,没什么进展,位操作编译也遇到报错.................

重新来,直接操作寄存器,就一切顺利,尝试把位操作换成操作寄存器,编译OK,但是系统直接黑屏...........

当然本身桥接对时序要求很高,精细控制的话,AICube 的使用上我只是照猫画虎,自然问题多多

我把整个系统都放上来,方便的时候看看怎样设置AiCube 才和顺畅运行的程序一一对应?

实验环境:ai8051U 试验箱+7789彩屏(8脚!240*240,不能买7脚的!不能买7脚的!不能买7脚的!会有屛闪+细小亮点问题无法解决)

2个文件中,“项目“是遇到问题的使用AiCube 的,是用串口来操作 Flash 另外一个是浦江一水老师直接操作寄存器的,用来作为标准,要

修改的是“项目“,主要目的是学习如何在AiCube中精密控制寄存器和进行位操作 如何解决位操作编译时候的报错?这些问题目前在大学教

材中是没有答案的,本身这样的桥接技术也是这2年才铺开,所以吸引了我来折腾(TFT的屛也买了5块),也专门打了PCB,无论是LCM环境

(STC32G144K246)和SPI屛实验环境在2种具有桥接功能的芯片(Ai8051U有试验箱,STC32G144K246要自己搞PCB)都搞好了,可以慢慢

透彻的研究,因为AiCube 是解放生产力的好工具,可以大幅降低使用难度,值得好好研究通它的使用方法...........

在职到时候忙,现在有时间可以好好看看怎样设置才是最好的,普中的板子我也操作了一遍,感觉只是入门级别,还不够,但是目前也没有渠道

能找到更多的AiCube相关资料,感觉用这个实验,可以说明STC的2个32位芯片强大的功能和软件AiCube 的方便,本来这是高职院校实验师晋升

高级实验师的绝好论文项目,我自己因为已经退休意义不大,不过先把“项目”调顺畅,打磨好,一定有用到的时候............




wuzhengmin 发表于 2026-6-22 17:52:56

我们自动生成的SPI初始化:



void SPI_Init(void)
{
      
      SPI_SwitchP3n();                  //选择SPI数据口: SS(P3.5), MOSI(P3.4), MISO(P3.3), SCLK(P3.2)
    SPI_SwapMosiMiso();               //交换MISO和MOSI功能脚

    SPI_MasterMode();                   //设置SPI为主机模式
    SPI_IgnoreSS();                     //忽略SS脚
    SPI_DataMSB();                      //设置SPI数据顺序为MSB (高位在前)
    SPI_SetMode3();                     //设置SPI工作模式3 (CPOL=1, CPHA=1)
    SPI_SetClockDivider4();             //设置SPI时钟分频


//   SPI_Enable();                     //使能SPI功能

    DMA_SPI_AutoSS();                   //使能SPI DMA自动控制SS
    DMA_SPI_SetAutoSSP35();             //DMA自动控制SS (P3.5)
    DMA_SPI_SetAmount(SPI_DMASIZE - 1); //设置SPI DMA发送/接收字节数
    DMA_SPI_SetTxAddress(pu8SPIDMATxBuffer); //设置SPI DMA发送缓冲区地址
    DMA_SPI_SetInterval(SPI_DMAITV);    //设置SPI DMA发送/接收字节间隔时间(系统时钟)
    DMA_SPI_ClearFIFO();                //清空SPI DMA FIFO缓冲区
    DMA_SPI_ClearFlag();                //清除SPI DMA中断标志
    DMA_SPI_EnableTx();               //使能发送数据
    DMA_SPI_DisableRx();                //禁止接收数据
    DMA_SPI_SetBusPriority(0);          //设置总线访问为最低优先级
    DMA_SPI_SetIntPriority(0);          //设置中断为最低优先级
    DMA_SPI_EnableInt();                //使能SPI DMA中断
    DMA_SPI_Enable();                   //使能SPI DMA功能
//DMA_SPI_MasterTrigger();            //触发SPI主机DMA

    //<<AICUBE_USER_SPI_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    HSSPI_CFG= SS_HOLD | SS_SETUP;    // 根据实际需求调整SS_HLD和SS_SETUP值
    HSSPI_CFG2 = SPI_IOSW | HSSPIEN | FIFOEN | SS_DACT;
      
      
    DMA_SPI_ITVH = 0; //SPI DMA 传输间隔时间寄存器
    DMA_SPI_ITVL = 9; // 8--9加大间隔,牺牲一点速度换稳定性8
    //DMA_SPI_CFG = DMA_SPIIE | SPI_ACT_TX;       // 去掉SPI_ACT_RX,只发不收
      SPI_Enable();                     //使能SPI功能
      
      fSPIDMABusy = 0; // 清除DMA传输忙标志
    //<<AICUBE_USER_SPI_INITIAL_END>>
      
}

和浦江一水老师的这段:
voidSPI_Init(void)
{
SPI_S1= 1; //00: P1.4 P1.5 P1.6 P1.7, 01: P2.4 P2.5 P2.6 P2.7, 10: P4.0 P4.1 P4.2 P4.3, 11: P3.5 P3.4 P3.3 P3.2
SPI_S0= 1; //SPI显示屏接口选择 11: P3.5 P3.4 P3.3 P3.2
SSIG = 1;//1: 忽略SS脚,由MSTR位决定主机还是从机    0: SS脚用于决定主机还是从机。
SPEN = 1;//1: 允许SPI, 0:禁止SPI,所有SPI管脚均为普通IO
DORD = 0;//1:LSB先发, 0:MSB先发(高位在前)
MSTR = 1;//1:设为主机0:设为从机
CPOL = 1;//1: 空闲时SCLK为高电平,0:空闲时SCLK为低电平
CPHA = 1;//1: 数据在SCLK前沿驱动,后沿采样. 0: 数据在SCLK前沿采样,后沿驱动.
SPCTL = (SPCTL & ~3) | 3; //SPI 时钟频率选择,0:4T,1:8T,2:16T,3:2T
HSCLKDIV   = 1;//HSCLKDIV主时钟分频
SPI_CLKDIV = 1;//SPI_CLKDIV主时钟分频
//高速I/O时钟(HSIOCK)经 HSCLKDIV 分频->高速外设时钟(HSCLK)->经 SPI_CLKDIV分频->SPI实际工作时钟(SPI_CLK)
//SPSTAT = 0xC1; //状态寄存器清0 SPIF和WCOL标志(写1)
SPIF = 1;      //清SPIF标志(设置SPI传输完成标志)
WCOL = 1;      //清WCOL标志(是 SPI 写冲突标志清零)
HSSPI_CFG2 = 0x40; //(HSSPI_CFG2^6=1) 交换MOSI MISO, P3.3是MOSI
P3M1 &= ~0x0C;   //P3.3(MOSI) P3.2(SCLK)设置成推挽输出
P3M0 |=0x0C;
P3SR &= ~0x0C;   //P3.3(MOSI) P3.2(SCLK)设置成高速模式
P3PU |=0x30;   //SPI接口使能上拉电阻
P1PU |=0x02;   //P11接口使能上拉电阻
P4PU |=0x80;   //P47接口使能上拉电阻
HSSPI_CFG = 0;   //禁止高速(QSPI_DMA不需要高速)
//P_SW1 = (P_SW1 & ~0x0C) | ((SPI_IO<<2) & 0x0C);//切换IO
DMA_SPI_ITVH = 0;//间隔为0,DMA_SPI_ITVH 和 DMA_SPI_ITVL 是 AI8051U 中专门
DMA_SPI_ITVL = 0;//用于控制 SPI DMA 数据包之间间隔时间的寄存器
}
基本对应,但是在AICube中不能直接位操作,编译报错,改成对寄存器操作(其实是一样的)


SPCTL = 0xDF;      // SSIG=1, SPEN=1, DORD=0, MSTR=1, CPOL=1, CPHA=1, SPR1=1, SPR0=1
      HSCLKDIV = 1;      // 主时钟分频
      SPI_CLKDIV = 1;      // SPI时钟分频
      
      SPSTAT = 0xC0;// 同时清除 SPIF 和 WCOL,干净利落


可以通过编译,但烧录后TFT直接黑屏,不知道哪里有冲突,而用原来AiCube生成的不会黑屏,是运行几次后卡死

其实这2句是没必要的:

HSSPI_CFG= SS_HOLD | SS_SETUP;    // 根据实际需求调整SS_HLD和SS_SETUP值
HSSPI_CFG2 = SPI_IOSW | HSSPIEN | FIFOEN | SS_DACT;

因为我们没有用到高速SPI ,但是我删除后也是黑屏 ,我把实验现象也放上来:




页: [1] 2
查看完整版本: AICube 生成的系统,SPI初始化中不能直接位操作?