找回密码
 立即注册
查看: 89|回复: 3

32G12k128和8G1K08使用SPI互为主从通讯失败

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-04-24 14:32:54
已绑定手机

1

主题

2

回帖

17

积分

新手上路

积分
17
发表于 2025-4-23 14:53:59 | 显示全部楼层 |阅读模式
两个单片机SPI都使用的P32,P33,P34,P35四个IO口,串口都用的uart1(P30,P31),主频都是22.1184MHz:

8G1K08配置如下:

void SPI_PS_init(void)
{
        SPI_InitTypeDef                SPI_InitStructure;
        COMx_InitDefine                COMx_InitStructure;                                        //结构定义
        
        COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;        //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
        COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;                        //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
        COMx_InitStructure.UART_BaudRate  = 115200ul;                        //波特率, 一般 110 ~ 115200
        COMx_InitStructure.UART_RxEnable  = ENABLE;                                //接收允许,   ENABLE或DISABLE
        COMx_InitStructure.BaudRateDouble = DISABLE;                        //波特率加倍, ENABLE或DISABLE
        UART_Configuration(UART1, &COMx_InitStructure);                //初始化串口1 UART1,UART2,UART3,UART4
        NVIC_UART1_Init(ENABLE,Priority_1);                //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3

        SPI_InitStructure.SPI_Enable    = ENABLE;                                //SPI启动    ENABLE, DISABLE
        SPI_InitStructure.SPI_SSIG      = DISABLE;                                //片选位     ENABLE, DISABLE
        SPI_InitStructure.SPI_FirstBit  = SPI_MSB;                                //移位方向   SPI_MSB, SPI_LSB
        SPI_InitStructure.SPI_Mode      = SPI_Mode_Slave;                //主从选择   SPI_Mode_Master, SPI_Mode_Slave
        SPI_InitStructure.SPI_CPOL      = SPI_CPOL_Low;                        //时钟相位   SPI_CPOL_High,   SPI_CPOL_Low
        SPI_InitStructure.SPI_CPHA      = SPI_CPHA_2Edge;                //数据边沿   SPI_CPHA_1Edge,  SPI_CPHA_2Edge
        SPI_InitStructure.SPI_Speed     = SPI_Speed_4;                        //SPI速度    SPI_Speed_4, SPI_Speed_8, SPI_Speed_16, SPI_Speed_2/SPI_Speed_32
        SPI_Init(&SPI_InitStructure);
        NVIC_SPI_Init(ENABLE,Priority_3);                //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
        P3_MODE_IO_PU(GPIO_Pin_All);
        SPI_SW(SPI_P35_P34_P33_P32);        
        SPI_SS_4 = 1;
}

void Sample_SPI_PS(void)
{
        u8 i;
        
        if(COM1.RX_TimeOut > 0)
        {
                if(--COM1.RX_TimeOut == 0)
                {
                        if(COM1.RX_Cnt > 0)
                        {
                                UartReceived = 1;   //设置串口接收标志
                        }
                }
        }
        if((UartReceived) && (SPI_SS_4))
        {
                SPI_SetMode(SPI_Mode_Master);
                SPI_SS_4 = 0;     //拉低从机 SS 管脚
                delay_ms(1);
                for(i=0;i<COM1.RX_Cnt;i++)
                {
                        SPI_WriteByte(RX1_Buffer); //发送串口数据
                        
                }
                SPI_SS_4 = 1;    //拉高从机的 SS 管脚
                SPI_SetMode(SPI_Mode_Slave);
                COM1.RX_Cnt = 0;
                UartReceived = 0;
        }
        
        if(SPI_RxTimerOut > 0)
        {
                if(--SPI_RxTimerOut == 0)
                {
                        printf("spi[%d]:",SPI_RxCnt);
                        if(SPI_RxCnt > 0)
                        {
                                for(i=0; i<SPI_RxCnt; i++)        TX1_write2buff(SPI_RxBuffer);
                        }
                        SPI_RxCnt = 0;
                }
        }
}


STC32G12K128配置如下:

/****************  SPI初始化函数 *****************/
void SPI_config(void)
{
        SPI_InitTypeDef                SPI_InitStructure;
        SPI_InitStructure.SPI_Enable    = ENABLE;                                //SPI启动    ENABLE, DISABLE
        SPI_InitStructure.SPI_SSIG      = DISABLE;                                //片选位     ENABLE, DISABLE
        SPI_InitStructure.SPI_FirstBit  = SPI_MSB;                                //移位方向   SPI_MSB, SPI_LSB
        SPI_InitStructure.SPI_Mode      = SPI_Mode_Slave;                //主从选择   SPI_Mode_Master, SPI_Mode_Slave
        SPI_InitStructure.SPI_CPOL      = SPI_CPOL_Low;                        //时钟相位   SPI_CPOL_High,   SPI_CPOL_Low
        SPI_InitStructure.SPI_CPHA      = SPI_CPHA_2Edge;                //数据边沿   SPI_CPHA_1Edge,  SPI_CPHA_2Edge
        SPI_InitStructure.SPI_Speed     = SPI_Speed_4;                        //SPI速度    SPI_Speed_4, SPI_Speed_16, SPI_Speed_64, SPI_Speed_128
        SPI_Init(&SPI_InitStructure);
        NVIC_SPI_Init(ENABLE,Priority_3);                //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
        P3_MODE_IO_PU(GPIO_Pin_All);
        
        SPI_SW(SPI_P35_P34_P33_P32);                       //SPI_P54_P13_P14_P15,SPI_P22_P23_P24_P25,SPI_P54_P40_P41_P43,SPI_P35_P34_P33_P32
        SPI_SS_4 = 1;
}
/**********************************************/
void main(void)
{
        u8        i;
        u16 cnt=0;
        WTST = 0;                //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
        EAXSFR();                //扩展SFR(XFR)访问使能
        CKCON = 0;      //提高访问XRAM速度

        GPIO_config();
        UART_config();
        SPI_config();
        EA = 1;

        printf("STC32G_SPI_TEST\r\n");                //UART发送一个字符串

        while (1)
        {
                delay_ms(1);
                if(cnt++%250==0)        P46 = !P46;
                if(COM1.RX_TimeOut > 0)
                {
                        if(--COM1.RX_TimeOut == 0)
                        {
                                if(COM1.RX_Cnt > 0)
                                {
                                        UartReceived = 1;   ////设置串口接收标志
                                }
                        }
                }
                if((UartReceived) && (SPI_SS_4))
                {
                        SPI_SetMode(SPI_Mode_Master);        //SPI设置主机模式,开始发送数据
                        SPI_SS_4 = 0;     //拉低从机 SS 管脚
                        delay_ms(1);
                        for(i=0;i<COM1.RX_Cnt;i++)
                        {
                                SPI_WriteByte(RX1_Buffer); //发送串口数据
                        }
                        SPI_SS_4 = 1;    //拉高从机的 SS 管脚
                        SPI_SetMode(SPI_Mode_Slave);                //SPI设置从机模式,进入接收状态
                        COM1.RX_Cnt = 0;
                        UartReceived = 0;
                }
               
                if(SPI_RxTimerOut > 0)
                {
                        if(--SPI_RxTimerOut == 0)        //SPI超时计数器每1ms减1,并判断是否为0
                        {
                                printf("SPI[%d]",SPI_RxCnt);
                                if(SPI_RxCnt > 0)        //SPI接收超时后判断SPI接收数据长度是否非零
                                {
                                        for(i=0; i<SPI_RxCnt; i++)        TX1_write2buff(SPI_RxBuffer);        //通过串口输出数据
                                }
                                SPI_RxCnt = 0;        //清除SPI已接收数据长度
                        }
                }
        }
}

有没有大佬帮忙分析一下无法通讯的原因呀?
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-04-24 14:32:54
已绑定手机

1

主题

2

回帖

17

积分

新手上路

积分
17
发表于 2025-4-23 14:57:29 | 显示全部楼层
STC8G1K08的main函数
截图202504231456462042.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-04-24 14:32:54
已绑定手机

1

主题

2

回帖

17

积分

新手上路

积分
17
发表于 2025-4-23 14:59:02 | 显示全部楼层
两个程序都是参考例程改的,但是通讯没反应
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-4-23 16:25:00 | 显示全部楼层
请直接下载例程测试,试验成功后再修改
请上传原理图及逻辑分析仪或示波器测量结果
以下为AI生成内容:

根据提供的代码和问题描述,STC32G12K128 与 STC8G1K08 的 SPI 互为主从通讯失败可能由以下原因导致,需逐一排查:​


一、SPI 引脚配置与复用问题​
  • 引脚功能映射错误​

  • 两者均使用 SPI_P35_P34_P33_P32 映射引脚,对应关系为:​

  • P3.2(SCLK)、P3.3(MOSI)、P3.4(MISO)、P3.5(SS)。​

  • 关键检查:​

  • 确认两单片机的 SPI 引脚是否支持该复用功能(参考数据手册外设映射表)。​

  • STC8G1K08 的 SPI 默认引脚是否需通过 P_SW1 或 P_SW2 寄存器切换(如文档中提到的功能脚切换寄存器)。​

  • 确保引脚方向正确(主机:SCLK/MOSI/SS 输出,MISO 输入;从机:SCLK/MOSI 输入,MISO/SS 输入)。​

  • 片选信号(SS)控制错误​

  • 问题:从机的 SS 引脚应由主机控制,而不是从机自身。​

  • 当前代码中,从机模式下 SPI_SS_4 = 1 可能错误地将 SS 置为输入或内部拉高,导致从机未被选中。​

  • 修正:主机负责拉低从机的 SS 引脚,从机的 SS 引脚应设为输入模式,不主动控制。​

二、主从模式与时序配置不匹配​
  • 主从模式切换逻辑​

  • 代码行为:两单片机在检测到串口数据时切换为 SPI_Mode_Master 发送数据,理论上允许互为主从(分时主从),但需确保:​

  • 同一时刻仅一方为主机,另一方为从机。​

  • 切换模式后需等待时钟稳定,避免时序混乱。​

  • 时钟相位与极性(CPOL/CPHA)​

  • 两者均配置为 SPI_CPOL_Low 和 SPI_CPHA_2Edge(模式 3),理论一致。但需确认:​

  • 主机和从机的时钟极性和相位是否完全匹配(示波器抓波形验证)。​

  • 是否存在时钟频率过高导致时序不兼容(22.1184MHz 下 SPI 速度 SPI_Speed_4 对应分频因子是否合理)。​

三、SPI 速度与时钟配置​
  • 分频系数不一致​

  • STC8G1K08:SPI_Speed_4 通常对应 Fosc/4(如文档中提到 SPI 速度可选 Fosc/2、Fosc/4 等)。​

  • STC32G12K128:SPI_Speed_4 可能定义不同(如 Fosc/64),需查阅两者数据手册确认分频因子。​

  • 建议:统一设置为较低速度(如 Fosc/16),排除时钟过快导致的时序问题。​

  • 主频确认​

  • 确保两单片机均正确配置为 22.1184MHz(检查时钟寄存器 CLKSEL 或外部晶振配置)。​

四、软件逻辑问题​
  • 片选信号时序​

  • 主机发送数据时,需在数据传输前拉低 SS,传输完成后拉高。当前代码中 delay_ms(1) 可能过长,导致 SPI 超时。​

  • 优化:使用更精确的延时(如 10μs),或直接操作寄存器避免不必要的延时。​

  • 中断与缓冲区处理​

  • SPI 接收中断是否正确启用(两机均调用 NVIC_SPI_Init(ENABLE, Priority_3),但需确认中断服务函数是否正确处理接收数据)。​

  • 串口接收标志 UartReceived 是否在处理后正确清零,避免重复触发发送。​

  • 主从角色混淆​

  • 确保通讯时明确主从角色(如固定某一为主机,另一为从机),避免同时切换模式导致总线竞争。​

五、硬件连接与电气特性​
  • 接线错误​

  • 检查接线:SCLK-MOSI-MISO-SS 需一一对应,共地是否可靠。​

  • 从机的 SS 引脚是否浮空(需由主机驱动,不可悬空)。​

  • 上拉电阻配置​

  • SPI 引脚在高阻状态时需外部上拉(尤其 MISO),除非内部上拉已启用(代码中 P3_MODE_IO_PU(GPIO_Pin_All) 已使能上拉,可确认)。​

六、调试建议​
  • 分步测试​

  • 固定一方为主机,另一方为从机,单向通讯测试(如主机发从机收,反之亦然)。​

  • 使用示波器抓取 SCLK、MOSI、MISO 波形,确认时序是否匹配。​

  • 简化代码​

  • 暂时移除串口相关逻辑,直接通过 SPI 发送固定数据(如主机发送 0x55,从机接收后返回 0xAA),定位问题是否在串口触发逻辑。​

  • 寄存器检查​

  • 打印两机的 SPI 控制寄存器(如 SPCTL、SPSTAT),确认配置一致。​

总结可能原因​
  • 片选信号由从机自身控制,而非主机驱动,导致从机未正确选中。​

  • SPI 速度分频系数在两型号中定义不同,导致时钟不匹配。​

  • 引脚复用或方向配置错误,如从机的 MOSI/MISO 未设为输入。​

  • 主从模式切换时的时序延迟过长,或未正确等待时钟稳定。​

通过逐行对比寄存器配置、抓波形分析时序、简化测试流程,可快速定位问题。



DebugLab
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 01:50 , Processed in 0.133969 second(s), 66 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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