stm32 - STM32L4 ADC 不工作(多通道无 DMA)
问题描述
我正在尝试运行一段时间前在这里找到的代码,它允许从几个通道中选择一个 ADC 通道,并在必要时单独读取它。不涉及 DMA。我使用STM32L4R5。我的想法只是通过打开和关闭状态 LED 来确认正确的 ADC 读数,如果某个级别可用并且到目前为止它根本不工作(状态 LED 始终为 ON)。对于输入信号源,我使用一个设置为高电平的 GPIO 引脚,它通过一个 1k 电阻和一个 LED,因此电压约为 0.7V。我打电话给 __HAL_RCC_ADC_CLK_ENABLE(); 和 __HAL_RCC_GPIOC_CLK_ENABLE(); 在 HAL_ADC_MspInit() 中。status_led() 函数没有显示,但我经常使用它,没问题。
其余代码如下:
uint32_t pdlvl=0;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM1_Init();
// Test ADC reading voltage input
//
while(1){
pdlvl=read_ADC_channel(ADC_CHANNEL_13);
if(pdlvl<10){
status_led(4,1);
status_led(3,0);
}
if(pdlvl>10){
status_led(3,1);
status_led(4,0);
}
}
} // end of main
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_13;
sConfig.Rank = ADC_RANK_NONE;
sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_14;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
引脚初始化
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = ROUT1_Pin|ROUT2_Pin; // ADC_CHANNEL_13 and ADC_CHANNEL_14
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
现在是通道预配置的棘手部分:
void config_ADC_channel(uint32_t channel, uint8_t val)
{
ADC_ChannelConfTypeDef sConfig;
sConfig.Channel = channel;
sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
if(val==1){
sConfig.Rank = 1;
}
else{
sConfig.Rank = ADC_RANK_NONE;
}
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}
和阅读功能
uint32_t read_ADC_channel(uint32_t channel)
{
uint32_t digital_result;
config_ADC_channel(channel, 1);
// HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1000);
digital_result = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
config_ADC_channel(channel, 0);
return digital_result;
}
有什么想法我错了吗?
谢谢!
解决方案
我发现了问题。我没有正确设置外围时钟源(最初由 CubeMX 生成,后来由我修改):
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1;
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE;
PeriphClkInit.PLLSAI1.PLLSAI1M = 6;
PeriphClkInit.PLLSAI1.PLLSAI1N = 20;
PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_ADC1CLK;
推荐阅读
- angularjs - 使用 ng-click 单击视频时,使用 angularjs 禁用视频并打开窗口
- android - Android Studio + conan 原生代码调试
- android - 绘制完成后的OpenGL后处理
- javascript - Google 表格 - 将 pdf 上传到驱动器并发送电子邮件
- objective-c - macOS 暗模式和 NSAboutPanelOptionCredits
- c# - Build abstract filter function filled from json array in c#
- c# - 我如何将 EditValueChanged 事件与 lookupedit 一起使用
- opencv - 在哪里下载 OpenCv contrib for windows?
- api - 在同一个屏幕中调用 2 个 API
- oracle - 根据 IN 子句 -Oracle 中相同的值顺序从数据库中选择值