英文:
STM32L073RZ ADC Channel switching not working?
问题
在使用三个通道6、7和8读取每个通道100个样本的数据后,无法使用连续模式来读取数据。必须在读取一个通道的100个样本后切换通道。为简单起见,将样本减少为1,并编写了以下代码。
MX_ADC_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start(&htim2);
select_adc_channel(6);
HAL_ADC_Start_IT(&hadc);
HAL_Delay(250);
uint8_t adc = HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop_IT(&hadc);
select_adc_channel(7);
HAL_ADC_Start_IT(&hadc);
HAL_Delay(250);
adc = HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop_IT(&hadc);
select_adc_channel(8);
HAL_ADC_Start_IT(&hadc);
HAL_Delay(250);
adc = HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop_IT(&hadc);
MX_ADC_Init() 代码如下:
static void MX_ADC_Init(void)
{
/* USER CODE BEGIN ADC_Init 0 */
/* USER CODE END ADC_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC_Init 1 */
/* USER CODE END ADC_Init 1 */
/** 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_8B;
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_RISING;
hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
}
select_adc_channel() 代码如下:
void select_adc_channel(uint8_t channel)
{
ADC_ChannelConfTypeDef sConfig = {0};
switch(channel)
{
case 0: sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
break;
case 6: sConfig.Channel = ADC_CHANNEL_6;
sConfig.Rank = 1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
break;
case 7: sConfig.Channel = ADC_CHANNEL_7;
sConfig.Rank = 1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
break;
case 8: sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
break;
case 9: sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = 1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
break;
}
}
根据电路设计,6、7和8通道应分别读取78、130和190的ADC值。但是上面的代码只给出了所有3个通道的值为78。
然后将读取顺序更改为7、6和8,因此读取变为130、78和78。
在选择通道6之后发生了什么?
英文:
I have used three channels 6,7,8 to read data of 100 samples each. Hence I cannot use sequence continuous mode to read data. I have to switch the channel after reading 100 samples of one channel. For simplicity, I just reduced the sample to 1 and written the following code.
MX_ADC_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start(&htim2);
select_adc_channel(6);
HAL_ADC_Start_IT(&hadc);
HAL_Delay(250);
uint8_t adc=HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop_IT(&hadc);
select_adc_channel(7);
HAL_ADC_Start_IT(&hadc);
HAL_Delay(250);
adc=HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop_IT(&hadc);
select_adc_channel(8);
HAL_ADC_Start_IT(&hadc);
HAL_Delay(250);
adc=HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop_IT(&hadc);
MX_ADC_Init() code
static void MX_ADC_Init(void)
{
/* USER CODE BEGIN ADC_Init 0 */
/* USER CODE END ADC_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC_Init 1 */
/* USER CODE END ADC_Init 1 */
/** 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_8B;
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_RISING;
hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
}
select_adc_channel() code
void select_adc_channel(uint8_t channel)
{
ADC_ChannelConfTypeDef sConfig = {0};
switch(channel)
{
case 0: sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
break;
case 6: sConfig.Channel = ADC_CHANNEL_6;
sConfig.Rank = 1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
break;
case 7: sConfig.Channel = ADC_CHANNEL_7;
sConfig.Rank = 1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
break;
case 8: sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
break;
case 9: sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = 1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
break;
}
}
As per the circuit, 6, 7, and 8th channels should read 78, 130, 190 adc values.But the above code, only gives 78 value for all 3 channels.
Then changed the reading order to 7, 6, and 8. so the reading become 130, 78, and 78.
what is happening after channel 6 is selected?
答案1
得分: 0
每当你切换ADC通道时,你需要配置'旧'通道为ADC_RANK_NONE
,否则它仍然会被视为有效的启用通道。
以下是我曾经完成的一个项目中的一些代码,用于在两个通道之间切换ADC:
static void configure_channel_as(uint32_t channel, uint32_t rank)
{
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = channel;
sConfig.Rank = rank;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
dprintf("配置通道6失败\r\n");
}
}
void adc_configure_for_head(void)
{
configure_channel_as(ADC_CHANNEL_0, ADC_RANK_CHANNEL_NUMBER);
configure_channel_as(ADC_CHANNEL_6, ADC_RANK_NONE);
}
void adc_configure_for_voltage(void)
{
configure_channel_as(ADC_CHANNEL_6, ADC_RANK_CHANNEL_NUMBER);
configure_channel_as(ADC_CHANNEL_0, ADC_RANK_NONE);
}
每当你切换时,你需要对'旧'通道执行类似的操作。
英文:
Whenever you switch ADC channels, you'll need to configure the 'old' channel to have ADC_RANK_NONE
, otherwise it will still be considered a valid, enabled channel.
Here's some code from a project I did which switched the ADC between two channels:
static void configure_channel_as( uint32_t channel, uint32_t rank )
{
ADC_ChannelConfTypeDef sConfig = { 0 };
sConfig.Channel = channel;
sConfig.Rank = rank;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
if ( HAL_ADC_ConfigChannel ( &hadc, &sConfig ) != HAL_OK )
{
dprintf ( "Failed to configure channel 6\r\n" );
}
}
void adc_configure_for_head( void )
{
configure_channel_as ( ADC_CHANNEL_0, ADC_RANK_CHANNEL_NUMBER );
configure_channel_as ( ADC_CHANNEL_6, ADC_RANK_NONE );
}
void adc_configure_for_voltage( void )
{
configure_channel_as ( ADC_CHANNEL_6, ADC_RANK_CHANNEL_NUMBER );
configure_channel_as ( ADC_CHANNEL_0, ADC_RANK_NONE );
}
You'll need to do something similar for the 'old' channel whenever you switch.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论