使用STM32U083的ADC下面是我例的步骤,下面是一个简化的STM32U083 ADC使用步骤概述: - 时钟设置:
- 首先,需要配置和使能ADC的时钟源。通常涉及选择一个合适的时钟源,主时钟源或外部时钟源,不过我看了一下板载上是没有连接,改内部时钟。
- 配置ADC时钟分频器,确保时钟频率满足ADC的工作要求。
- 使能ADC的时钟。
- ADC基本配置:
- 选择合适ADC模式。STM32U083支持单次转换模式和连续转换模式。单次转换模式适用于只需要一次转换的应用场景,而连续转换模式适用于需要连续监视信号的应用,个人理解的。
- 设置采样时间。采样时间的选择取决于输入信号的特性和所需的采样速率。较长的采样时间通常可以提高精度,但会降低转换速度。
- 配置ADC的分辨率。STM32U083的ADC通常支持多种分辨率设置,8位、10位或12位。较高的分辨率会增加转换精度,但可能也会增加转换时间。
- 通道选择:
- 在进行ADC转换之前,需要选择要转换的ADC通道。通常涉及到将特定GPIO(通用输入输出)引脚配置为模拟输入,我这里是ADC1。
- 触发源设置:
- 根据需要通过外部触发源或软件触发来启动ADC转换。外部触发源可以是定时器、外部中断等,而软件触发则是通过编程控制ADC的启动,我这略过。
- 开始转换并读取结果:
- 启动ADC转换。这可以通过软件命令或外部触发来完成。
- 等待转换完成。这通常涉及到检查ADC的状态位,以确定转换是否完成。
- 读取转换结果。一旦转换完成,就可以从ADC的寄存器中读取转换后的数字值。
- 我好像还有一个停止转换,好像没用上,下面开始进行。
先上图:
在MX里面ADC的配置:
KEIL平台重要代码截图:
代码:
while (1)
{
// 定义一个8位无符号整数变量i,但在当前代码段中,变量i并未被使用
uint8_t i;
/*## Step 1: ADC过采样初始设置 ##########*/
/* 开始ADC的正则组转换 */
// 启动hadc1这个ADC句柄所代表的ADC转换
if (HAL_ADC_Start(&hadc1) != HAL_OK)
{
/* ADC转换启动错误 */
// 如果启动ADC转换失败,则调用错误处理函数
Error_Handler();
}
/* 等待ADC转换完成 */
// 等待hadc1这个ADC句柄所代表的ADC转换完成,超时时间为10ms
if (HAL_ADC_PollForConversion(&hadc1, 10) != HAL_OK)
{
/* 转换完成标志未按时设置 */
// 如果在10ms内没有检测到转换完成标志,则调用错误处理函数
Error_Handler();
}
/* 检索ADC转换数据 */
// 检索hadc1这个ADC句柄所代表的ADC的转换结果
// (使用过采样比率16和右移4位来缩放数据,相当于ADC分辨率为:12位)
// 变量uhADCxConvertedData_OVS_ratio16_shift4存储了ADC的转换结果
uhADCxConvertedData_OVS_ratio16_shift4 = HAL_ADC_GetValue(&hadc1);
// 注意:代码段中并没有显示uhADCxConvertedData_OVS_ratio16_shift4的声明和定义,
// 假定它在其他地方已经被定义为一个合适的变量来存储ADC转换结果。
// 此while循环没有终止条件,将无限循环执行ADC的转换和读取操作。
// 在实际应用中,可能需要根据具体需求添加其他逻辑或条件来跳出循环。
}
下面给一个将ADC的值转成电压的代码示例:
#include "stm32u0xx_hal.h"
ADC_HandleTypeDef hadc1;
// ADC参考电压,通常这取决于你的微控制器供电电压和ADC的配置
#define ADC_VREF 3.3f // 单位:伏特
// 假设ADC是12位的
#define ADC_BITS 12
// 计算ADC的最大值
#define ADC_MAX_VALUE ((1 << ADC_BITS) - 1)
// ADC通道配置
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
/**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; // 设置ADC时钟分频
hadc1.Init.Resolution = ADC_RESOLUTION_12B; // 设置ADC分辨率为12位
hadc1.Init.ScanConvMode = DISABLE; // 禁止扫描模式
hadc1.Init.ContinuousConvMode = ENABLE; // 使能连续转换模式
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 = 1; // 设置规则序列中转换的数量
hadc1.Init.DMAContinuousRequests = DISABLE; // 禁止DMA连续请求
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV; // 设置EOC选择
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_0; // 假设我们使用ADC通道0
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5; // 设置采样时间
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
// 通道配置错误处理
Error_Handler();
}
}
// ADC值转换为电压的函数
float ADC_Value_To_Voltage(uint32_t adc_value)
{
float voltage_step = ADC_VREF / (float)ADC_MAX_VALUE; // 每个ADC值的电压增量
float voltage = adc_value * voltage_step; // 计算电压
return voltage;
}
int main(void)
{
HAL_Init(); // 初始化HAL库
SystemClock_Config(); // 配置系统时钟,这个函数需要你自己根据硬件手册实现
MX_ADC1_Init(); // 初始化ADC
while (1)
{
HAL_ADC_Start(&hadc1); // 开始ADC转换
// 等待转换完成,你可以使用轮询或者中断的方式
HAL_ADC_PollForConversion(&hadc1, 1000); // 等待1000ms超时
uint32_t adc_value = HAL_ADC_GetValue(&hadc1); // 读取ADC转换结果
float voltage = ADC_Value_To_Voltage(adc_value); // 将ADC值转换为电压
// 在这里你可以使用转换后的电压值,比如通过串口打印出来
// ...
HAL_Delay(1000); // 延时1秒,然后再次读取ADC值
}
}
|