int Get_Adc(char ch) { ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5); ADC_SoftwareStartConvCmd(ADC1,ENABLE); while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); return ADC_GetConversionValue(ADC1); }
时间: 2024-04-27 09:20:39 浏览: 158
这是一个用于获取ADC采样值的函数。具体实现步骤如下:
1. 调用ADC_RegularChannelConfig函数,配置ADC1的转换通道ch,采样顺序为第1次,采样时间为239.5个周期。
2. 启动ADC1的软件转换,调用ADC_SoftwareStartConvCmd函数。
3. 进入while循环,等待ADC1的转换完成。当ADC1转换完成时,相应的标志位ADC_FLAG_EOC会被置位。
4. 返回ADC1的转换结果,调用ADC_GetConversionValue函数。
此函数的作用是获取ADC1模块对应通道的采样值,并返回给调用函数。
相关问题
stm32f103R6hal库ADC多路采样
### STM32F103R6 使用 HAL 库实现 ADC 多路同时采样
为了实现 STM32F103R6 的多路 ADC 同时采样,可以按照如下方式配置并编写代码:
#### GPIO 和 ADC 初始化设置
首先需要初始化用于 ADC 输入的 GPIO 引脚以及 ADC 自身的相关参数。
```c
// 定义使用的ADC通道号数组
uint8_t adc_channels[] = {ADC_CHANNEL_0, ADC_CHANNEL_1, ADC_CHANNEL_2, ADC_CHANNEL_3};
static void MX_GPIO_Init(void){
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
/* 配置PA0~PA3作为模拟输入 */
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
}
static void MX_ADC_Init(void){
ADC_ChannelConfTypeDef sConfig;
hadc.Instance=ADC1;
hadc.Init.ScanConvMode = ENABLE; // 开启扫描模式支持多个通道转换
hadc.Init.ContinuousConvMode = DISABLE;// 单次转换模式
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.NbrOfConversion = sizeof(adc_channels)/sizeof(uint8_t); // 设置要转换的数量等于定义好的channel数量
if (HAL_ADC_Init(&hadc)!= HAL_OK){Error_Handler();}
for(int i=0;i<hadc.Init.NbrOfConversion;i++){
sConfig.Channel = adc_channels[i];
sConfig.Rank=i+1;
sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
if(HAL_ADC_ConfigChannel(&hadc,&sConfig) != HAL_OK){ Error_Handler();}
}
}
```
上述代码完成了对四个不同引脚(PA0 至 PA3)对应的 ADC 通道进行初始化,并指定了相应的采样时间和序列位置[^2]。
#### DMA 数据传输配置
为了让 ADC 能够高效地处理来自多个传感器的数据流,推荐采用直接存储器访问(DMA)技术来自动完成数据搬运工作。下面展示如何开启和配置 DMA 功能以便于配合 ADC 工作。
```c
static void MX_DMA_Init(void){
__HAL_RCC_DMA1_CLK_ENABLE();
hdma_adc.Instance=DMA1_Channel1;
hdma_adc.Init.Direction=DMA_PERIPH_TO_MEMORY;
hdma_adc.Init.PeriphInc=DMA_PINC_DISABLE;
hdma_adc.Init.MemInc=DMA_MINC_ENABLE;
hdma_adc.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;
hdma_adc.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;
hdma_adc.Init.Mode=DMA_CIRCULAR;
hdma_adc.Init.Priority=DMA_PRIORITY_HIGH;
if(HAL_DMA_Init(&hdma_adc)!=(HAL_OK)){Error_Handler();}
__HAL_LINKDMA(&hadc,DMA_Handle,hdma_adc);
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn,0,1);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
```
这里设置了循环模式下的 DMA 请求优先级为高,并绑定了中断服务程序以响应可能发生的错误情况或溢出事件[^3]。
#### 中断回调函数与主逻辑控制
最后一步是在应用程序入口处注册必要的中断处理器,并在其中加入实际业务逻辑——即每当有新的有效样本到达时就执行某些操作(比如发送给上位机显示)。以下是简单的框架示意:
```c
extern uint16_t AdcValue[4]; // 声明全局变量保存每次读取到的结果
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc){
static int index=0;
while(__HAL_DMA_GET_FLAG(&hdma_adc,DMA_FLAG_TCIF1)==RESET);
memcpy((void*)AdcValue,(void*)(__HAL_ADC_DMA_GetAddress(hadc)),\
sizeof(uint16_t)*hadc->Init.NbrOfConversion);
char buffer[64]={};
sprintf(buffer,"CH0:%u CH1:%u CH2:%u CH3:%u\r\n", \
AdcValue[index%4],AdcValue[(index+1)%4],\
AdcValue[(index+2)%4],AdcValue[(index+3)%4]);
HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),0xFFFF);
index++;
}
int main(){
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_ADC_Init();
MX_DMA_Init();
HAL_ADC_Start_DMA(&hadc,(uint32_t*)&AdcValue,sizeof(AdcValue)/sizeof(uint32_t));
while(1){}
}
```
这段代码展示了当一次完整的 ADC 扫描结束之后,通过 UART 接口向外输出当前各通道上的最新数值;与此同时还实现了基本的任务调度机制使得整个系统能够持续运行下去而不至于陷入死锁状态[^1]。
阅读全文