|
|
功能需求:希望能够在尽量高的ADC采样频率下,通过SPI主机读取同步两个SPI从机的数据,每组数据不重复,我需要怎么配置和修改处理逻辑
问题:SPI主机同步读取两个SPI从机数据,从机数据来自于ADC采样处理后数据,读取后的数据有多个重复点。之前以为是ADC采样频率过低,但是提升采样率以后重复点数据依旧保持不变。
希望可以看一下配置是否存在问题,或者处理是否符合逻辑,最下面部分是我尝试的三个方案,但是效果都不好。
/***************************************************************SPI主机部分的配置和逻辑**************************************************************************/
主机SPI配置:
void SPI4_Config_Init(void)
{
hspi4.Instance = SPI4;
hspi4.Init.Mode = SPI_MODE_MASTER;
hspi4.Init.Direction = SPI_DIRECTION_2LINES;
hspi4.Init.DataSize = SPI_DATASIZE_8BIT;
hspi4.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi4.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi4.Init.NSS = SPI_NSS_HARD_OUTPUT;
hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi4.Init.TIMode = SPI_TIMODE_DISABLE;
hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi4.Init.CRCPolynomial = 0x0;
hspi4.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi4.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi4.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi4.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi4.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi4.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_01CYCLE;
hspi4.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_01CYCLE;
hspi4.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi4.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
hspi4.Init.IOSwap = SPI_IO_SWAP_DISABLE;
HAL_SPI_Init(&hspi4);
}
void SPI6_Config_Init(void)
{
hspi6.Instance = SPI6;
hspi6.Init.Mode = SPI_MODE_MASTER;
hspi6.Init.Direction = SPI_DIRECTION_2LINES;
hspi6.Init.DataSize = SPI_DATASIZE_8BIT;
hspi6.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi6.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi6.Init.NSS = SPI_NSS_HARD_OUTPUT;
hspi6.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi6.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi6.Init.TIMode = SPI_TIMODE_DISABLE;
hspi6.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi6.Init.CRCPolynomial = 0x0;
hspi6.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi6.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi6.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi6.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi6.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi6.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_01CYCLE;
hspi6.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_01CYCLE;
hspi6.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi6.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
hspi6.Init.IOSwap = SPI_IO_SWAP_DISABLE;
HAL_SPI_Init(&hspi6);
}
主函数中的逻辑:
通过把数据读到以后写入缓冲区,缓冲区满了以后再统一做输出
while (1)
{
wIdx = Get_FifoBuff_Widx(&g_fifoBuff);
if(RINGBUFF_LEN == wIdx && 0 == readFlag)
{
readFlag = 1;
HAL_Delay(8 * 1000);
}
if(0 == readFlag)
{
ret = HAL_SPI_TransmitReceive(&hspi4, tnsSPI4Buff, rcvSPI4Buff, TRANS_DATA_LEN, 0x1);
ret = HAL_SPI_TransmitReceive(&hspi6, tnsSPI6Buff, rcvSPI6Buff, TRANS_DATA_LEN, 0x1);
if(HAL_OK == ret)
{
if(0x81 == rcvSPI4Buff[0] && 0x81 == rcvSPI6Buff[0])
{
checksum4_b8 = rcvSPI4Buff[0] + rcvSPI4Buff[1] + rcvSPI4Buff[2] + rcvSPI4Buff[3];
checksum6_b8 = rcvSPI6Buff[0] + rcvSPI6Buff[1] + rcvSPI6Buff[2] + rcvSPI6Buff[3];
if(checksum4_b8 == rcvSPI4Buff[TRANS_DATA_LEN - 1] && checksum6_b8 == rcvSPI6Buff[TRANS_DATA_LEN - 1])
{
angleWrite[0] = rcvSPI4Buff[1] << 16 | rcvSPI4Buff[2] << 8 | rcvSPI4Buff[3];
angleWrite[1] = rcvSPI6Buff[1] << 16 | rcvSPI6Buff[2] << 8 | rcvSPI6Buff[3];
Write_fifoBuff(&g_fifoBuff, angleWrite, 2);
}
}
}
}
if(1 == readFlag)
{
rIdx = Get_FifoBuff_Ridx(&g_fifoBuff);
if(RINGBUFF_LEN == rIdx)
{
continue;
}
Read_fifoBuff(&g_fifoBuff, angleRead, 2);
printf("%d,%d\r\n",angleRead[0],angleRead[1]);
}
}
/***************************************************************两个SPI从机部分的配置和逻辑**************************************************************************/
void SPI4_Config_Init(void)
{
hspi4.Instance = SPI4;
hspi4.Init.Mode = SPI_MODE_SLAVE;
hspi4.Init.Direction = SPI_DIRECTION_2LINES;
hspi4.Init.DataSize = SPI_DATASIZE_8BIT;
hspi4.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi4.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi4.Init.NSS = SPI_NSS_HARD_INPUT;
hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi4.Init.TIMode = SPI_TIMODE_DISABLE;
hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi4.Init.CRCPolynomial = 0x0;
hspi4.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi4.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi4.Init.FifoThreshold = SPI_FIFO_THRESHOLD_02DATA;
hspi4.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi4.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi4.Init.IOSwap = SPI_IO_SWAP_DISABLE;
HAL_SPI_Init(&hspi4);
}
ADC中断的处理逻辑:
void DMA1_Stream1_IRQHandler(void)
{
// 相关中断标识处理逻辑
....
// dTempData 是通过对 ADC 采样的数据处理后的结果
....
Write_SpiBuff(dTempData);
bReady = 1;
}
主逻辑处理方法:
// 从机通过SPI发送 24bit 数据的帧格式
void TransmitData(uint32_t Data)
{
uint32_t sum_check = 0;
uint8_t SndByte[5] = {0};
uint8_t byteCount = 0;
uint8_t andFlag = 0xFF;
// frame head
SndByte[0] = 0x81;
sum_check += SndByte[0];
byteCount++;
for(uint8_t i = 0; i < 3; i++)
{
// shift 0 <-> low, sheft 8 <-> middle, sheft 16 <-> high
SndByte[byteCount] = (Data>> (2 - i) * 8) & andFlag;
sum_check += SndByte[byteCount];
byteCount++;
}
SndByte[byteCount] = sum_check & andFlag;
HAL_SPI_Transmit(&hspi4, SndByte, 5, 0x1);
return;
}
主循环:
while(1)
{
spiData = Read_SpiBuff();
TransmitData(spiData );
}
读出的数据一直有重复点。

做过的尝试的方案,尝试的现象不太理解,希望如果理解的朋友给一些回复:
1、考虑是ADC采样后中断处理速率比较慢,SPI传输速率比较快,导致出现的重复点问题。当我不断的提升采样中断频率,读出的重复点数基本保持不变,这点就不是很理解;但是降低采样频率以后,重复点数增加,这里是正常的。
2、在ADC采样的DMA中断中增加处理完成标识 bReady ,在主函数中对标识判断和设置
在SPI从机中设置的逻辑为:
while(1)
{
if(1 == bReady)
{
spiData = Read_SpiAngBuff();
TransmitData(spiData );
bReady = 0;
}
}
这样设置以后,在主机读取后的数据更加异常,还是存在重复点,或者直接丢失一段数据
3、考虑直接把传输数据部分放入到中断中,数据完全异常,感觉这个方案也不是很合理,但是不太肯定。
希望有遇到相关问题的朋友给一些建议,谢谢!
|
|