本帖最后由 WangChong 于 2023-10-21 23:49 编辑
今天来分享一下我的ADC学习心得,首先说明当前的教程适用于所有的搭载AI-m61或者m62芯片的小安派。
需要的库文件如下
log.h | 用来打印日志 | bflb_gpio.h | 初始化GPIO |
bflb_mtimer.h | 延时 | board.h | 初始化系统 |
重要的方法如下:
/**
* @brief 初始化GPIO端口作为analog
*
* @param [in] dev device handle
* @param [in] pin gpio pin, use @ref GPIO_PIN
* @param [in] cfgset gpio config mask
*/
void bflb_gpio_init(struct bflb_device_s *dev, uint8_t pin, uint32_t cfgset);
/**
* @brief 初始化ADC功能
*
* @param [in] ADC外设
* @param [in] ADC 配置结构体
*/
void bflb_adc_init(struct bflb_device_s *dev, const struct bflb_adc_config_s *config);
/**
* @brief ADC配置结构体
*
* @param clk_div adc时钟频率是否分频,频率越高精度越差,相反精度越高
* @param scan_conv_mode ADC scan mode enable, ADC扫描模式,我不清楚干什么用的
* @param continuous_conv_mode ADC continuous conversion enable ,Adc持续转换,不清楚干嘛额
* @param differential_mode ADC differential mode enable , adc 差异区分模式, 不清楚干嘛的
* @param resolution ADC resolution, use @ref ADC_RESOLUTION adc转换精度
* @param vref ADC reference select, use @ref ADC_VREF adc参考电压
*/
struct bflb_adc_config_s {
uint8_t clk_div;
uint8_t scan_conv_mode;
uint8_t continuous_conv_mode;
uint8_t differential_mode;
uint8_t resolution;
uint8_t vref;
};
/**
* @brief 绑定ADC和对用的通道
*
* @param [in] dev device handle
* @param [in] 所有的通道
* @param [in] 你所要使用的通道
* @return Zero on success; a negated errno value on failure
*/
int bflb_adc_channel_config(struct bflb_device_s *dev, struct bflb_adc_channel_s *chan, uint8_t channels);
这里定义的是所有的ADC通道,我这里只定义了 0 通道,就是gpio20
struct bflb_adc_channel_s chan[] = {
#if TEST_ADC_CHANNEL_0
{.pos_chan = ADC_CHANNEL_0,
.neg_chan = ADC_CHANNEL_GND},
#endif
};
/**
* @brief 开始转换ADC
*
* @param [in] dev device handle
*/
void bflb_adc_start_conversion(struct bflb_device_s *dev);
/**
* @brief 获取ADC转换结果
*
* @param [in] dev device handle
* @return conversion value
*/
uint32_t bflb_adc_read_raw(struct bflb_device_s *dev);
/**
* @brief 结束转换ADC
*
* @param [in] dev device handle
*/
void bflb_adc_stop_conversion(struct bflb_device_s *dev);
/**
* @brief 解析raw adc转换结果到毫伏, 以数字形式展示
*
* @param [in] dev device handle
* @param [in] bflb_adc_read_raw 方法转换的结果
* @param [out] result pointer to save parse result, 转换后保存的结果,需要自己定义
* @param [in] count count to parse。 不清楚干什么用的 传递0 即可
*/
void bflb_adc_parse_result(struct bflb_device_s *dev, uint32_t *buffer, struct bflb_adc_result_s *result, uint16_t count);
代码如下:
- #include "bflb_mtimer.h"
- #include "board.h"
- #include "bflb_adc.h"
- #define DBG_TAG "MAIN"
- #include "log.h"
- #include "bflb_gpio.h"
- struct bflb_device_s *adc;
- struct bflb_device_s *gpio;
- #define TEST_ADC_CHANNEL_0 0
- // 定义所有的adc通道
- struct bflb_adc_channel_s chan[] = {
- #if TEST_ADC_CHANNEL_0
- {.pos_chan = ADC_CHANNEL_0,
- .neg_chan = ADC_CHANNEL_GND},
- #endif
- };
- int main(void)
- {
- board_init();
- gpio = bflb_device_get_by_name("gpio");
- // 初始化IO 20 作为 analog
- bflb_gpio_init(gpio, GPIO_PIN_20, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
- adc = bflb_device_get_by_name("adc");
- // 原始转换数据
- volatile uint32_t raw_data;
- // adc 配置
- struct bflb_adc_config_s cfg;
- // 始终分频, 分频约低速度越快,精度越低。 当前为最高分频,速度最快精度最低
- cfg.clk_div = ADC_CLK_DIV_32;
- // 剩下这三个参数没有搞明白实际作用
- cfg.scan_conv_mode = true;
- cfg.continuous_conv_mode = false;
- cfg.differential_mode = false;
- // 设置adc精度
- cfg.resolution = ADC_RESOLUTION_16B;
- // adc参考电压
- cfg.vref = ADC_VREF_3P2V;
- // 初始化ADC
- bflb_adc_init(adc, &cfg);
- // 绑定ADC通道
- bflb_adc_channel_config(adc, chan, TEST_ADC_CHANNEL_0);
- while (1)
- {
- // 转换
- bflb_adc_start_conversion(adc);
- // 结束转换
- bflb_adc_stop_conversion(adc);
- //获取原生转换结果
- raw_data = bflb_adc_read_raw(adc);
- struct bflb_adc_result_s result;
- printf("raw data:%08x\r\n", raw_data);
- //解析raw 转换结果
- bflb_adc_parse_result(adc, (uint32_t *)&raw_data, &result, 1);
- printf("postive values is %d, negative is : %d mv is %d \r\n", result.pos_chan, result.neg_chan, result.millivolt);
- //适当的延时
- bflb_mtimer_delay_ms(20);
- }
- }
复制代码
转化结果如下图所示:(目前是悬空)
欢迎大佬指正,一起学习
|
|