使用AD7606B采集电压电流波形,采集原理:STM32定时器输出周期950us,占空比为50%的方波作为外部时钟输入给convst,通过检测BUSY下降沿SPI读取ADC数据。 AD7606B配置为软件模式,Dout线数为1,无过采样,±10V范围。 原理图(原理图存在错误,图上引脚用的7606,实际使用7606b,WR为低电平)如下: 测试中发现奇怪现象,对瞬时脉冲信号(每秒10ms高电平)的采集不定时丢失(有时候运行几个小时出现,有时运行几十分钟出现),而稳定信号或者高电平时间较长的脉冲信号未出现。 : 两通道同时输入10ms脉冲信号,不一定哪个通道会出现丢失; 两通道一个10ms脉冲,一个20ms脉冲输入,10ms脉冲会出现丢失;
正常脉冲波形(1s一个10ms高电平) 丢失时波形(隔1s丢失一次10ms高电平) 且丢失前会有一段时间 间隔21s丢一次数据的现象(为什么会间隔21s丢数据, 是否跟950us的convst时钟有关系) 同时刻另一通道的稳定电平信号正常采集 将脉冲信号改为每秒30ms高电平信号,采集波形经过十几分钟缓慢恢复正常。将脉冲信号改为稳定高电平信号,波形立即恢复正常。 使用示波器测量convst信号(下图黄色)和busy信号(下图蓝色),发现busy不连续,但stm32可以每毫秒都能检测到busy下降沿中断,不确定是不是示波器问题。 将stm32定时器改为输出周期1ms的方波后,该现象暂未复现,不理解为什么这个改动会起作用。 示波器测量7606B相关电压: Vvcc : 有效值5.16V,峰值5.28V Vdrive:有效值3.45V,峰值3.52V Vregcap: 有效值1.95V,峰值2.08V SPI通信配置及BUSY下降沿中断读取 [C] 纯文本查看 复制代码 /* SPI1 init function */[/font][/color][/align]
void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
__HAL_SPI_DISABLE(&hspi1);
__HAL_SPI_ENABLE(&hspi1);
/* USER CODE END SPI1_Init 2 */
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(spiHandle->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* SPI1 clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PB5 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = AD_SCLK_Pin|AD_SDI_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = AD_SDO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(AD_SDO_GPIO_Port, &GPIO_InitStruct);
/* SPI1 interrupt Init */
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
/*
*********************************************************************************************************
* 函 数 名: SPI1_Write2Bytes
* 功能说明: 通过SPI1接口发送2字节数据
* 形 参: TxData:要发送的数据
* 返 回 值: SPI接口返回值
*********************************************************************************************************
*/
u16 SPI1_Write2Bytes (u16 TxData)
{
u16 rxdata;
hspi1.Instance->DR = TxData;
/* 等待发送完成 */
while (!( hspi1.Instance->SR & TXE));
hspi1.Instance->DR;
/* 等待接收完成 */
while (hspi1.Instance->SR & (BSY | RXNE))
rxdata = hspi1.Instance->DR;
return rxdata;
}
/*
*********************************************************************************************************
* 函 数 名: SPI1_Read2Bytes
* 功能说明: 通过SPI1接口接收2字节数据
* 形 参: 无
* 返 回 值: 接收数据值
*********************************************************************************************************
*/
u16 SPI1_Read2Bytes (void)
{
u16 rxdata;
hspi1.Instance->DR = 0x0000;
// /* 等待发送完成 */
while (!(hspi1.Instance->SR & TXE));
hspi1.Instance->DR;
/* 等待接收完成 */
while (hspi1.Instance->SR & (BSY | RXNE))
{
rxdata = hspi1.Instance->DR;
}
return rxdata;
//HAL_SPI_TransmitReceive_DMA(&hspi1,(u8*)g_spi1TxBuf, (u8*)g_spi1RxBuf,size);
}
void AD7606_ISR(void) /* 此函数代码按照时序编写 */
{
u8 i,j;
u16 ADC_Value[8];
ADC_CS = 0;
for (i = 0; i < AD_CH_NUM; i++)
{
ADC_Value[i] = SPI1_Read2Bytes(); /* 读16位数据 */
}
ADC_CS = 1;
AD_Errcnt = 0;
#if 1
if((ADC_Data_Flag == 0)&& ADC_DataIndex1 < ADC_100MS_SIZE)
{
for(j=0;j<AD_CH_NUM;j++)
{
if(ADC_Value[j]>50 && ADC_Value[j] <65480 )
ADC_DataBuffer1[j][ADC_DataIndex1] = ADC_Value[j];
else
ADC_DataBuffer1[j][ADC_DataIndex1] = 0;
if(ADC_DataBuffer1[j][ADC_DataIndex1]<0x8000)
ADC_RealValue[j] = ADC_DataBuffer1[j][ADC_DataIndex1];
else
ADC_RealValue[j] = 0xFFFF-ADC_DataBuffer1[j][ADC_DataIndex1];
}
ADC_DataIndex1++;
if(ADC_DataIndex1>= ADC_100MS_SIZE)
{
ADC_DataIndex1 = 0;
ADC_DataFull1 = 1;
ADC_Data_Flag = 1;
Errorcode &=~(1<<2);
AD_timeout = 0;
}
}
else if((ADC_Data_Flag == 1) && ADC_DataIndex2 < ADC_100MS_SIZE)
{
for(j=0;j<AD_CH_NUM;j++)
{
if(ADC_Value[j]>50 && ADC_Value[j] <65480 )
ADC_DataBuffer2[j][ADC_DataIndex2] = ADC_Value[j];
else
ADC_DataBuffer2[j][ADC_DataIndex2] = 0;
if(ADC_DataBuffer2[j][ADC_DataIndex2]<0x8000)
ADC_RealValue[j] = ADC_DataBuffer2[j][ADC_DataIndex2];
else
ADC_RealValue[j] = 0xFFFF-ADC_DataBuffer2[j][ADC_DataIndex2];
}
ADC_DataIndex2++;
if(ADC_DataIndex2>= ADC_100MS_SIZE)
{
ADC_DataIndex2 = 0;
ADC_DataFull2 = 1;
ADC_Data_Flag = 0;
Errorcode &=~(1<<2);
AD_timeout = 0;
}
}
#endif
排查了很久,没找到根本原因,烦请帮忙看下,谢谢!
|