我在 Nucleo F401RE 上有一个带两个通道的 ADC:一个通道读取热敏电阻的值(通道 8,等级 1),另一个通道读取电位计的值(通道 1,等级 2)。按微控制器上的按钮应该可以在通道之间切换,但我只能从通道 8 切换到通道 1
我试图改变他们的等级或给予他们相同的等级,但没有效果。
void change_channel(uint32_t channel, uint32_t rank)
{ ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = channel;
sConfig.Rank = rank;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
global_channel=sConfig.Channel;
global_rank= sConfig.Rank;
}
我也尝试禁用其他通道,但仍然不起作用。(它只会从电位器读取值)。当我尝试给出 sConfig.Rank = 2 时,当我禁用通道时,我读取了电阻的约 1310 的值,但我不知道它来自哪里。
void change_channel(uint32_t channel, uint32_t rank)
{
ADC_ChannelConfTypeDef sConfig = {0};
// Disable all channels
for (uint32_t ch = ADC_CHANNEL_0; ch <= ADC_CHANNEL_10; ch++) // Adjust range based on your MCU's ADC channels
{
sConfig.Channel = ch;
sConfig.Rank = 0; // Set rank to 0 to disable the channel (no valid rank)
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
// Enable the desired channel
sConfig.Channel = channel;
sConfig.Rank = rank; // Explicitly set the desired rank
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
// Store the global variables for tracking
global_channel = sConfig.Channel;
global_rank = sConfig.Rank;
}
我在第二个任务中读取了这些值(mod 是一个变量,当我按下按钮时,它会在 0 和 1 之间变化,以帮助我选择频道,0 表示自动模式,1 表示手动模式)文本
void StartTask02(void *argument)
{
/* USER CODE BEGIN StartTask02 */
float readValue;
float voltage;
float d=3.3;
int mod1;
/* Infinite loop */
for(;;)
{osMessageQueueGet (mod_for_ADCHandle, &mod1, 0, 0);
if(mod1==0)//
{
change_channel(8,1);
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1,1000)==HAL_OK){
readValue=HAL_ADC_GetValue(&hadc1);
voltage=(float)readValue/(float)4095*d;
globalvoltage= voltage;
globalreadValue=readValue;
}
HAL_ADC_Stop(&hadc1);
osMessageQueuePut (queque_voltageHandle, &voltage, 0, 0);
osDelay(100);
}
if(mod1==1)//
{
change_channel(1,2);
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1,1000)==HAL_OK){
readValue=HAL_ADC_GetValue(&hadc1);
voltage=(float)readValue/(float)4095*d;
globalvoltage= voltage;
globalreadValue=readValue;
}
HAL_ADC_Stop(&hadc1);
osMessageQueuePut (queque_voltageHandle, &voltage, 0, 0);
osDelay(100);
}
}
/* USER CODE END StartTask02 */
}
ADC 配置
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Rank = 2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
我认为您误解了 ADC 扫描转换模式的工作原理。
设置
ScanConvMode
为 ENABLE 并NbrOfConversion
设置为 2,则在您调用 后,ADC 将对两个通道执行转换HAL_ADC_Start()
。首先,ADC 将选择、采样和转换 Rank 1 通道。然后,ADC 将选择、采样和转换 Rank 2 通道。您的代码应在调用 后等待并获取两次转换的结果HAL_ADC_Start()
。但现在您的代码仅读取一次转换,即第一次或 Rank 1。您无需更改 ADC 配置即可通过按下按钮“切换”通道。每次调用 时,ADC 都会对两个通道进行采样和转换
HAL_ADC_Start()
。如果您确实只想输出一个通道并通过按下按钮切换该通道,则只需更改输出的两个转换中的哪一个。但您仍应等待并从 ADC 获取两个转换。如果您确实希望一次只执行一次转换并通过按下按钮切换通道,那么您应该将其设置
NbrOfConversion
为 1,禁用ScanConvMode
,然后在调用之前重新配置哪个通道是等级 1HAL_ADC_Start()
。