|
求助各位硬汉:
本人最近想使用SPI+DMA完成对AD7606电压信号的采集,设计方案如下:
1.使用定时器控制AD7606采样率,采样率50K;
2.外部中断感知AD7606下降沿信号,外部中断处理函数中设置标志位或者直接读取数据;
现在的问题是,使用SPI可以采集到准确的AD数据,但是加入DMA后,使用HAL_SPI_TransmitReceive_DMA(&hspi2,Tx_Buffer,Rx_Buffer,16)读取数据,问题就来了,若是DMA配置为DMA_NORMAL模式,则DMA只能使用一次,不论是DMA中断还是查询处理程序中都无法重启使用DMA,但是使用串口的话没问题,可以重启;我之前也浏览过很多相关资料,说单次模式下需要在中断处理函数中清标志位,重置传输数量,但是H7的HAL中应该是完成了相应操作的,看串口+DMA的例子中也只是进行了清传输完成标志位,我也试过在DMA中断中进行过类似操作,死马当活马医嘛,但是没有起到任何作用,且仿真界面注意到DMA的发送数据流置位了FIFO错误标志位,这就很奇怪了,我明明失能了FIFO模式,SPI中也没有配置,找了很久也不明白问题出在哪里;这是单次模式的情况
若是使用DMA_CIRCULAR模式,霍那就不得了,根本停不下来,同样的也在发送数据流中发现了FIFO错误,但是循环模式可以一直不停的跑,暂且没有理会,看能不能采集到正确的数据嘛,如果可以采到那就不管了。但是问题也来了,循环模式只要调用了HAL_SPI_TransmitReceive_DMA(&hspi2,Tx_Buffer,Rx_Buffer,16)这个HAL库函数后,用逻辑分析仪抓SPI的SCK引脚,根本停不下来,没法控制脉冲时序的话采集的数据肯定是错的,后来想了想,主函数中调用一次HAL_SPI_TransmitReceive_DMA函数,在DMA接收完成中断中我停止DMA传输,外部中断中恢复DMA传输,这样大致就可以控制时钟脉冲时序,理论上可行,说干就干,尴尬的是并没有用,就感觉我对整个DMA失去了控制权。
啰嗦了这么多,请教各位:
1.DMA_NORMAL模式应该怎么再次重新启用DMA;
2.DMA_CIRCULAR模式下是如何控制通信时序的;
3.HAL_SPI_TransmitReceive_DMA这个函数是否就是一个坑、自己重写发送接收函数比较好;
补充:DCache我是失能了的;
源码如下,希望各位指正:
SPI和DMA配置如下
void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 0x0;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
// hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_16DATA;
hspi2.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi2.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(spiHandle->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspInit 0 */
/* USER CODE END SPI2_MspInit 0 */
/* SPI2 clock enable */
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI2 GPIO Configuration
PB13 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
GPIO_InitStruct.Pin = SPI2_SCK_Pin|SPI2_MISO_Pin|SPI2_MOSI_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* SPI2 DMA Init */
/* SPI2_RX Init */
hdma_spi2_rx.Instance = DMA1_Stream0;
hdma_spi2_rx.Init.Request = DMA_REQUEST_SPI2_RX;
hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_rx.Init.Mode = DMA_NORMAL;
hdma_spi2_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(spiHandle,hdmarx,hdma_spi2_rx);
/* SPI2_TX Init */
hdma_spi2_tx.Instance = DMA1_Stream1;
hdma_spi2_tx.Init.Request = DMA_REQUEST_SPI2_TX;
hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_tx.Init.Mode = DMA_NORMAL;
hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(spiHandle,hdmatx,hdma_spi2_tx);
/* SPI2 interrupt Init */
HAL_NVIC_SetPriority(SPI2_IRQn, 4, 0);
HAL_NVIC_EnableIRQ(SPI2_IRQn);
/* USER CODE BEGIN SPI2_MspInit 1 */
/* USER CODE END SPI2_MspInit 1 */
}
}
void DMA1_Stream0_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream0_IRQn 0 */
static uint8_t K=0;
uint8_t i=0;
if(__HAL_DMA_GET_FLAG(&hdma_spi2_rx,DMA_FLAG_TCIF0_4)!=RESET) //êy¾Y½óêÕíê3é
{
__HAL_DMA_CLEAR_FLAG(&hdma_spi2_rx,DMA_FLAG_TCIF0_4);
DATA_OK=1;
}
/* USER CODE END DMA1_Stream0_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_spi2_rx);
/* USER CODE BEGIN DMA1_Stream0_IRQn 1 */
/* USER CODE END DMA1_Stream0_IRQn 1 */
}
void DMA1_Stream1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream1_IRQn 0 */
if(__HAL_DMA_GET_FLAG(&hdma_spi2_rx,DMA_FLAG_TCIF1_5)!=RESET) //êy¾Y½óêÕíê3é
{
__HAL_DMA_CLEAR_FLAG(&hdma_spi2_tx,DMA_FLAG_TCIF1_5);
}
/* USER CODE END DMA1_Stream1_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_spi2_tx);
/* USER CODE BEGIN DMA1_Stream1_IRQn 1 */
/* USER CODE END DMA1_Stream1_IRQn 1 */
}
void EXTI15_10_IRQHandler(void)
{
/* USER CODE BEGIN EXTI15_10_IRQn 0 */
static uint8_t K=0;
uint8_t i,data;
uint8_t Free_data=0xff;
if(ADC_Complete==0) //′«êäíê3éÖ®oóÔù×öà-¸ß¸üDÂ′|àí
{
AD_CS_0();
HAL_SPI_TransmitReceive_DMA(&hspi2,Tx_Buffer,Rx_Buffer,16); //还是希望外部中断中控制DMA通信
}
/* USER CODE END EXTI15_10_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10);
/* USER CODE BEGIN EXTI15_10_IRQn 1 */
/* USER CODE END EXTI15_10_IRQn 1 */
}
|
|