硬汉嵌入式论坛

 找回密码
 立即注册
查看: 238|回复: 2
收起左侧

SPI通讯偶发的接收异常

[复制链接]

1

主题

0

回帖

3

积分

新手上路

积分
3
发表于 2025-10-14 09:49:58 | 显示全部楼层 |阅读模式
使用STM32F429和GD32F470进行SPI通讯,使用DMA模式,STM32作为主机,GD32作为从机,偶尔会出现,从机能接收到主机的命令,但是发送回复数据时,DMA的计数一直没有清零,导致主机一直接收不到完整的数据内容,此时需要复位从机才能恢复正常,试过发送前强制清零计数也不行,大佬们帮忙分析下{        uint32_t  ulSendLen, ulOffset = 0, SubpackConut = 0, WriteLen = 0;
        uint32_t ulTimeoutTick;
        SubToMasterHead SubPackHead;
        SubFrameHead    SubFrame = {0};
       
        if (slen == 0)     return;
       
        if (st_SpiSlaveInfo.ucSendFlag)
        {
                gpio_bit_set(SUBHANDSHAKE_PORT, SUBHANDSHAKE_PIN); //初始化将握手IO置为高
                delay_ms(5);
        }
        st_SpiSlaveInfo.ucSendFlag = 0;         //置发送完成标记
        SUB_PRINT("\n\rMDACH3计数:%04x\n\r",DMA_CHCNT(DMA1,DMA_CH3));
        //首包头部
        strncpy((char*)SubPackHead.ucHeadFlag, HEAD_FLAG, strlen(HEAD_FLAG));
        SubPackHead.ulFrameNumber = (st_SpiSlaveInfo.ulSendLenght+SPISEND_LEN_MAX)/SPISEND_LEN_MAX;
        SubPackHead.ulTotalLength = st_SpiSlaveInfo.ulSendLenght;
        SubPackHead.ulCRC32 = crc32((INT8U*)&SubPackHead, sizeof(SubPackHead)-sizeof(SubPackHead.ulCRC32));
       
        //SUB_HEX("发送数据:", (uint8_t*)pSendBuf, st_SpiSlaveInfo.ulSendLenght>32?32:st_SpiSlaveInfo.ulSendLenght);
        //printf("%02x\r\n", pSendBuf[st_SpiSlaveInfo.ulSendLenght-1]);
        ulTimeoutTick = GD32_GetTick();
#if SUB_SPI_DMA       
        while(1)
        {
                //加入5超时,避免包体过大长时间未发送完而长时间循环
                if ( GD32_GetTick() > (ulTimeoutTick+5000)) break;
                       
                if (st_SpiSlaveInfo.ucSendFlag == 1) continue;
               
                if (st_SpiSlaveInfo.ulSendLenght > SPISEND_LEN_MAX) ulSendLen = SPISEND_LEN_MAX;    //需要分包发送
                else                      ulSendLen = st_SpiSlaveInfo.ulSendLenght;
               
                WriteLen = 0;
                //首帧加上包头
                if (!SubpackConut)
                {
                        memcpy(&SendMasterBuffer[WriteLen], (INT8U*)&SubPackHead, sizeof(SubPackHead));
                        WriteLen = sizeof(SubPackHead);
                }
               
                //printf("长%d第%d次分包\r\n", st_SpiSlaveInfo.ulSendLenght,SubpackConut);
                strncpy((char*)SubFrame.ucFrameFlag, SUBPACKET_BEGIN, strlen(SUBPACKET_BEGIN));
                SubFrame.ulFrameNo = SubpackConut;
                SubFrame.ulFrameLength = ulSendLen;
               
                WriteLen += CRC8LEN;
                memcpy(&SendMasterBuffer[WriteLen], &pSendBuf[ulOffset], ulSendLen);
                WriteLen += ulSendLen;
               
                memcpy(&SendMasterBuffer[WriteLen], (uint8_t*)&SubFrame, sizeof(SubFrame));
                WriteLen += sizeof(SubFrame);
               
                if (SubpackConut)
                    SendMasterBuffer[0] = crc8(0, SendMasterBuffer, WriteLen-1);
                else
                        SendMasterBuffer[sizeof(SubPackHead)] = crc8(0, &SendMasterBuffer[sizeof(SubPackHead)], WriteLen-sizeof(SubPackHead)-1);
               
               
                SubpackConut++;
               
                dma_channel_disable(DMA1, DMA_CH3);   //禁用DMA_CH3
               
                //数据发送中先禁用接收DMA,避免接收缓冲数据量过大导致检包浪费时间
                dma_channel_disable(DMA1, DMA_CH2);
                                st_SpiSlaveInfo.ulReadOffset = SLAVE_BUFFER_SIZE-dma_transfer_number_get(DMA1, DMA_CH2);  //重置读索引


            st_SpiSlaveInfo.ucSendFlag = 1;    //正在发送中
            dma_memory_address_config(DMA1, DMA_CH3, DMA_MEMORY_0, (uint32_t)SendMasterBuffer);//(uint32_t)&pSendBuf[ulOffset]);
            dma_transfer_number_config(DMA1, DMA_CH3, WriteLen);        //设置发送缓冲长度


                dma_channel_enable(DMA1, DMA_CH3);  //使能DMA_CH3
               
                st_SpiSlaveInfo.ulSendLenght -= ulSendLen;
                ulOffset     += ulSendLen;
               
                gpio_bit_reset(SUBHANDSHAKE_PORT, SUBHANDSHAKE_PIN);  //准备好发送置为低
                SUB_HEX("发送数据:", (uint8_t*)SendMasterBuffer, WriteLen>32?32:WriteLen);
                if (st_SpiSlaveInfo.ulSendLenght <= 0)  break;
        }


回复

使用道具 举报

1

主题

0

回帖

3

积分

新手上路

积分
3
 楼主| 发表于 2025-10-14 09:57:30 | 显示全部楼层
16:16:25.538    MDACH3计数:003C
16:16:25.538   
16:16:25.538    发送数据::
16:16:25.538     48 45 41 44 01 00 00 00
16:16:25.538     1e 00 00 00 6b ac cf 64
16:16:25.540     29 4c 41 aa aa e0 39 9c
16:16:25.548     00 00 00 52 00 0d 00 00
16:16:25.549   
16:16:25.722   
16:16:25.723    接收到数据::
16:16:25.723     4c 41 55 55 e1 39 9c 00
16:16:25.723     00 00 53 00 00 00 00 00
16:16:25.723     e5
16:16:25.723   
16:16:25.723   
16:16:25.724    MDACH3计数:003C
16:16:25.724   
16:16:25.731    发送数据::
16:16:25.759     48 45 41 44 01 00 00 00
16:16:25.759     12 00 00 00 d3 13 19 2e
16:16:25.759     68 4c 41 aa aa e1 39 9c
16:16:25.759     00 00 00 53 00 01 00 00
16:16:25.760   
16:16:25.951   
16:16:25.954    接收到数据::
16:16:25.954     4c 41 55 55 e2 39 9c 00
16:16:25.955     00 00 53 00 00 00 00 00
16:16:25.956     e6
16:16:25.956   
16:16:25.956   
16:16:25.957    MDACH3计数:003C
16:16:25.957   
16:16:25.966    发送数据::
16:16:25.985     48 45 41 44 01 00 00 00
16:16:25.985     12 00 00 00 d3 13 19 2e
16:16:25.985     c8 4c 41 aa aa e2 39 9c
16:16:25.985     00 00 00 53 00 01 00 00
16:16:25.987   
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
119429
QQ
发表于 2025-10-15 11:32:17 | 显示全部楼层
从机接收完毕,要判断DMA完成,如果没有完成要调用终止API。

还有就是推荐使用硬件片选,如果是软件片选容易出现数据同步问题

回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-11-21 23:08 , Processed in 0.055818 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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