stm32多个ADC redings错误
stm32 multiple ADC redings error
我是用cubemx启动项目的,我用的单片机是stm32L053C6。为此,我有 2 个传感器和 2 个晶体管连接到 adc 输入。下面的代码显示了我如何从第一个温度传感器获取输入值、电压。然后我对每个要读取的值使用相同的代码。这里的问题是我读到的第一个值总是错误的,它给了我 2048,而且是 12 位分辨率,所以...
我想知道如何解决这个问题?
//Start ADC reading
if(HAL_ADC_Start(&hadc) != HAL_OK){
while(1) {}
}
//Wait for EOC (end of conversion)
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
//Read ADC value
//Repeat for all channels.
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].temperature += hadc.Instance->DR;
printf("\n ex0 i rolling %d\n", experiments[0+index].temperature);
读取2个温度传感器和晶体管电压值的代码如下。我读取这些值 16 次并计算平均值。但正如我所说,我读到的第一个值是 2048。
void readRollingADC(int index){
HAL_Delay(1);
//Start ADC reading
if(HAL_ADC_Start(&hadc) != HAL_OK){
while(1) {}
}
//Wait for EOC (end of conversion)
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
//Read ADC value
*
> ****//Repeat for all channels. while(!(hadc.Instance->ISR & ADC_ISR_EOC)){} experiments[0+index].temperature +=
> hadc.Instance->DR; printf("\n ex0 i rolling %d\n",
> experiments[0+index].temperature);****
*
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].ube += hadc.Instance->DR;
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].vrb += hadc.Instance->DR;
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].vrc += hadc.Instance->DR;
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[1+index].temperature += hadc.Instance->DR;
printf("\n ex1 i rolling %d\n", experiments[1+index].temperature);
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[1+index].ube += hadc.Instance->DR;
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[1+index].vrb += hadc.Instance->DR;
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[1+index].vrc += hadc.Instance->DR;
}
我该如何解决这个问题?是不是跟code或者adc的启动有关系?我能做的是读取第一个值而不是保存它,但我认为这不是正确的方法:)
void MX_ADC_Init(void)
{
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = ENABLE;
hadc.Init.LowPowerFrequencyMode = ENABLE;
hadc.Init.LowPowerAutoPowerOff = ENABLE;
HAL_ADC_Init(&hadc);
sConfigAdc.Channel = ADC_CHANNEL_0;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_1;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_2;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_3;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_5;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_6;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_7;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_8;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
/*
sConfigAdc.Channel = ADC_CHANNEL_9;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
} */
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hadc->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_ADC1_CLK_ENABLE();
/**ADC GPIO Configuration
PA0 ------> ADC_IN0
PA1 ------> ADC_IN1
PA2 ------> ADC_IN2
PA3 ------> ADC_IN3
PA5 ------> ADC_IN5
PA6 ------> ADC_IN6
PA7 ------> ADC_IN7
PB0 ------> ADC_IN8
PB1 ------> ADC_IN9
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspDeInit 0 */
/* USER CODE END ADC1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ADC1_CLK_DISABLE();
/**ADC GPIO Configuration
PA0 ------> ADC_IN0
PA1 ------> ADC_IN1
PA2 ------> ADC_IN2
PA3 ------> ADC_IN3
PA5 ------> ADC_IN5
PA6 ------> ADC_IN6
PA7 ------> ADC_IN7
PB0 ------> ADC_IN8
PB1 ------> ADC_IN9
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_0|GPIO_PIN_1);
}
/* USER CODE BEGIN ADC1_MspDeInit 1 */
/* USER CODE END ADC1_MspDeInit 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
问题是,我想读取值 temp1,transistor_1 电压(ube1,vrb1,vrc1),temp2 transistor_2 电压(ube2,vrb2,vrc2)
16次取平均码:
HAL_Delay(2);
/* Set DAC at voltage level 1 (3.1v 0xF07)*/
setDAC(0xF07); //
printf("\n***************************\n");
HAL_Delay(2);
for(int i = 0; i < 16; i++){
readRollingADC(0); // read All inputs 16 times.
void shiftAverages(){
for(int i = 0; i < 8; i++){
experiments[i].temperature = (experiments[i].temperature >> 4);
experiments[i].ube = (experiments[i].ube >> 4);
experiments[i].vrb = (experiments[i].vrb >> 4);
experiments[i].vrc = (experiments[i].vrc >> 4);
}
}
我为不同的 setDAC 值做了这些事情,然后我进入函数 readRollingADC()
但每次我进入函数时,第一次读取总是 2048 然后它工作正常。
当我读取第一个值时,它似乎以某种方式让我高,是自动存储在 ADC 寄存器中的东西吗?
//Start ADC reading
if(HAL_ADC_Start(&hadc) != HAL_OK){
while(1) {}
}
//Wait for EOC (end of conversion)
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].temperature += hadc.Instance->DR;
printf("\n ex0 i rolling %d\n", experiments[0+index].temperature);
HAL_ADC_Stop(&hadc);
HAL_Delay(20);
HAL_ADC_Start(&hadc);
HAL_Delay(20);
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].ube += hadc.Instance->DR;
printf("\n ube si %d\n", experiments[0+index].ube);
HAL_ADC_Stop(&hadc);
HAL_Delay(20);
HAL_ADC_Start(&hadc);
HAL_Delay(20);
我确实喜欢这个,但这给了我所有频道相同的价值,这是你提到的还是我应该写点别的?
您有 hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV
和 hadc.Init.ContinuousConvMode = DISABLE
。我猜你需要在每个通道转换后重新启动 ADC。因此,在每次转换之间,您需要先调用 HAL_ADC_Stop
,然后再调用 HAL_ADC_Start
。您甚至不在转换之间清除 ISR_EOC 标志,您必须手动执行此操作,这就是为什么最好调用 HAL_ADC_PollForConversions
来清除它。并且您需要调用 HAL_ADC_Start
与配置的通道完全相同的计数,即。 9 在您的设置中,否则 ADC 通道选择将错过您期望读取的通道。
对于超过 5 个通道,我建议使用 DMA,其缓冲区的字数与通道配置和设置 hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV
的字数完全相同。这样,使用单个 HAL_ADC_Start_DMA
即可获得所有通道字节。少于 5 个通道,一个常规通道 + 其余带自动注入的注入通道即可完成工作。
请记住将读取的 ADC 值 __LL_ADC_CALC_TEMPERATURE
转换为温度,将 __LL_ADC_CALC_DATA_TO_VOLTAGE
转换为电压,从 stm32l0_ll_adc.h.
您可以阅读有关 stm32l0 hal 驱动程序的信息 here.
我是用cubemx启动项目的,我用的单片机是stm32L053C6。为此,我有 2 个传感器和 2 个晶体管连接到 adc 输入。下面的代码显示了我如何从第一个温度传感器获取输入值、电压。然后我对每个要读取的值使用相同的代码。这里的问题是我读到的第一个值总是错误的,它给了我 2048,而且是 12 位分辨率,所以...
我想知道如何解决这个问题?
//Start ADC reading
if(HAL_ADC_Start(&hadc) != HAL_OK){
while(1) {}
}
//Wait for EOC (end of conversion)
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
//Read ADC value
//Repeat for all channels.
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].temperature += hadc.Instance->DR;
printf("\n ex0 i rolling %d\n", experiments[0+index].temperature);
读取2个温度传感器和晶体管电压值的代码如下。我读取这些值 16 次并计算平均值。但正如我所说,我读到的第一个值是 2048。
void readRollingADC(int index){
HAL_Delay(1);
//Start ADC reading
if(HAL_ADC_Start(&hadc) != HAL_OK){
while(1) {}
}
//Wait for EOC (end of conversion)
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
//Read ADC value
*
> ****//Repeat for all channels. while(!(hadc.Instance->ISR & ADC_ISR_EOC)){} experiments[0+index].temperature +=
> hadc.Instance->DR; printf("\n ex0 i rolling %d\n",
> experiments[0+index].temperature);****
*
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].ube += hadc.Instance->DR;
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].vrb += hadc.Instance->DR;
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].vrc += hadc.Instance->DR;
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[1+index].temperature += hadc.Instance->DR;
printf("\n ex1 i rolling %d\n", experiments[1+index].temperature);
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[1+index].ube += hadc.Instance->DR;
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[1+index].vrb += hadc.Instance->DR;
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[1+index].vrc += hadc.Instance->DR;
}
我该如何解决这个问题?是不是跟code或者adc的启动有关系?我能做的是读取第一个值而不是保存它,但我认为这不是正确的方法:)
void MX_ADC_Init(void)
{
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = ENABLE;
hadc.Init.LowPowerFrequencyMode = ENABLE;
hadc.Init.LowPowerAutoPowerOff = ENABLE;
HAL_ADC_Init(&hadc);
sConfigAdc.Channel = ADC_CHANNEL_0;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_1;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_2;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_3;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_5;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_6;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_7;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
sConfigAdc.Channel = ADC_CHANNEL_8;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
}
/*
sConfigAdc.Channel = ADC_CHANNEL_9;
if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
while(1){}
} */
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hadc->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_ADC1_CLK_ENABLE();
/**ADC GPIO Configuration
PA0 ------> ADC_IN0
PA1 ------> ADC_IN1
PA2 ------> ADC_IN2
PA3 ------> ADC_IN3
PA5 ------> ADC_IN5
PA6 ------> ADC_IN6
PA7 ------> ADC_IN7
PB0 ------> ADC_IN8
PB1 ------> ADC_IN9
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspDeInit 0 */
/* USER CODE END ADC1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ADC1_CLK_DISABLE();
/**ADC GPIO Configuration
PA0 ------> ADC_IN0
PA1 ------> ADC_IN1
PA2 ------> ADC_IN2
PA3 ------> ADC_IN3
PA5 ------> ADC_IN5
PA6 ------> ADC_IN6
PA7 ------> ADC_IN7
PB0 ------> ADC_IN8
PB1 ------> ADC_IN9
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_0|GPIO_PIN_1);
}
/* USER CODE BEGIN ADC1_MspDeInit 1 */
/* USER CODE END ADC1_MspDeInit 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
问题是,我想读取值 temp1,transistor_1 电压(ube1,vrb1,vrc1),temp2 transistor_2 电压(ube2,vrb2,vrc2)
16次取平均码:
HAL_Delay(2);
/* Set DAC at voltage level 1 (3.1v 0xF07)*/
setDAC(0xF07); //
printf("\n***************************\n");
HAL_Delay(2);
for(int i = 0; i < 16; i++){
readRollingADC(0); // read All inputs 16 times.
void shiftAverages(){
for(int i = 0; i < 8; i++){
experiments[i].temperature = (experiments[i].temperature >> 4);
experiments[i].ube = (experiments[i].ube >> 4);
experiments[i].vrb = (experiments[i].vrb >> 4);
experiments[i].vrc = (experiments[i].vrc >> 4);
}
}
我为不同的 setDAC 值做了这些事情,然后我进入函数 readRollingADC() 但每次我进入函数时,第一次读取总是 2048 然后它工作正常。
当我读取第一个值时,它似乎以某种方式让我高,是自动存储在 ADC 寄存器中的东西吗?
//Start ADC reading
if(HAL_ADC_Start(&hadc) != HAL_OK){
while(1) {}
}
//Wait for EOC (end of conversion)
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].temperature += hadc.Instance->DR;
printf("\n ex0 i rolling %d\n", experiments[0+index].temperature);
HAL_ADC_Stop(&hadc);
HAL_Delay(20);
HAL_ADC_Start(&hadc);
HAL_Delay(20);
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].ube += hadc.Instance->DR;
printf("\n ube si %d\n", experiments[0+index].ube);
HAL_ADC_Stop(&hadc);
HAL_Delay(20);
HAL_ADC_Start(&hadc);
HAL_Delay(20);
我确实喜欢这个,但这给了我所有频道相同的价值,这是你提到的还是我应该写点别的?
您有 hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV
和 hadc.Init.ContinuousConvMode = DISABLE
。我猜你需要在每个通道转换后重新启动 ADC。因此,在每次转换之间,您需要先调用 HAL_ADC_Stop
,然后再调用 HAL_ADC_Start
。您甚至不在转换之间清除 ISR_EOC 标志,您必须手动执行此操作,这就是为什么最好调用 HAL_ADC_PollForConversions
来清除它。并且您需要调用 HAL_ADC_Start
与配置的通道完全相同的计数,即。 9 在您的设置中,否则 ADC 通道选择将错过您期望读取的通道。
对于超过 5 个通道,我建议使用 DMA,其缓冲区的字数与通道配置和设置 hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV
的字数完全相同。这样,使用单个 HAL_ADC_Start_DMA
即可获得所有通道字节。少于 5 个通道,一个常规通道 + 其余带自动注入的注入通道即可完成工作。
请记住将读取的 ADC 值 __LL_ADC_CALC_TEMPERATURE
转换为温度,将 __LL_ADC_CALC_DATA_TO_VOLTAGE
转换为电压,从 stm32l0_ll_adc.h.
您可以阅读有关 stm32l0 hal 驱动程序的信息 here.