|
|
使用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;
}
|
|