【蓝桥杯嵌入式】ADC模数转换的原理图解析与代码实现(以第十一届省赛为例)——STM32G4

🎊【蓝桥杯嵌入式】专题正在持续更新中,原理图解析✨,各模块分析✨以及历年真题讲解✨都在这儿哦,欢迎大家前往订阅本专题,获取更多详细信息哦🎏🎏🎏

🪔本系列专栏 -  蓝桥杯嵌入式_勾栏听曲_0的博客

🍻欢迎大家  🏹  点赞👍  评论📨  收藏⭐️

📌个人主页 - 勾栏听曲_0的博客📝

🔑希望本文能对你有所帮助,如有不足请指正,共同进步吧🏆

🎇君子之道,暗然而日章;小人之道,明然而日亡。📈

目录

原理图解析

 设置STM32CubeMX

 手搓代码

实例运用


原理图解析

        从图中可以看出,模拟输出的引脚分别为PB15和PB12。

 设置STM32CubeMX

        打开STM32CubeMX后,找到PB15和PB12,并把他们设置为ADC输入模式。PB15的为ADC2_IN15,PB12的为ADC1_IN11。

         然后在左侧的Analog中设置ADC,如我们设置刚刚配置给PB12的ADC1,通道为IN11设置为slingle ended,PB15的ADC2的通道IN15前打勾。这样ADC在STM32CubeMX的设置就完成了。

 手搓代码

        利用STM32CubeMX生成号代码后,我们新建两个文件来单独写ADC的代码,但是要注意的是,新文件不能命名为adc.c和adc.h,因为用STM32CubeMX会生成adc.c和adc.h的库文件,为例使命名不冲突,就想要命名为其他名字。

        如下所示,ADC的有效代码只有4行,而且也没什么难点,等一下我们直接以十一届省赛左例子来使用一下,这里我们来讨论一下这四行代码中的最后一句,这个算式为什么这样写呢。

        我们通过HAL_ADC_GetValue();这个函数获取的是一个电压值,而存储这个电压值是12位的空间,也就是说这个函数理论上取出来的电压值在0~4095之间。3.3是这个电位器的实际最大电压为3.3。因此我们除以4096再乘3.3就知道这个电压值对应的真实电压数值是多少啦。

double getADC(ADC_HandleTypeDef *pin)
{
	uint adc;
	HAL_ADC_Start(pin);
	adc = HAL_ADC_GetValue(pin);
	return adc*3.3/4096;
}

实例运用

题目

        这里要求使用PB0来检测电位器R37的电压信号,我们在STM32CubeMX上的PB0接口选择ADC_IN15就可以啦,这里我们改一下题目,将两个电位器都测一下

        使用STM32微控制器ADC通道(PB15和PB12)分别测量竞赛板电位器R37与R38输出的模拟电压信号。并在LCD屏中显示出来。

代码实现

aadc.c中依旧是我们上面提到的获取ADC的函数

double getADC(ADC_HandleTypeDef *pin)
{
	uint adc;
	HAL_ADC_Start(pin);
	adc = HAL_ADC_GetValue(pin);
	return adc*3.3/4096;
}

        在lcd.c中调用getADC并显示,getADC(&hadc1)获取的是R38电位器的模拟电压信号,getADC(&hadc2)获取的是R37电位器的模拟电压信号。

void disp_proc()
{
	char text[30];
	sprintf(text,"      Para   ");
	LCD_DisplayStringLine(Line4, (uint8_t *)text);

	sprintf(text,"    V: %.2f",getADC(&hadc1));
	LCD_DisplayStringLine(Line6, (uint8_t *)text);
	sprintf(text,"    V: %.2f",getADC(&hadc2));
	LCD_DisplayStringLine(Line7, (uint8_t *)text);
}

  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
#include "bflb_adc.h" #include "bflb_mtimer.h" #include "board.h" struct bflb_device_s adc; #define TEST_ADC_CHANNELS 2 #define TEST_COUNT 10 struct bflb_adc_channel_s chan[] = { { .pos_chan = ADC_CHANNEL_2, .neg_chan = ADC_CHANNEL_GND }, { .pos_chan = ADC_CHANNEL_GND, .neg_chan = ADC_CHANNEL_3 }, }; int main(void) { board_init(); board_adc_gpio_init(); adc = bflb_device_get_by_name("adc"); / adc clock = XCLK / 2 / 32 */ 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 = true; cfg.resolution = ADC_RESOLUTION_16B; cfg.vref = ADC_VREF_3P2V; bflb_adc_init(adc, &cfg); bflb_adc_channel_config(adc, chan, TEST_ADC_CHANNELS); for (uint32_t i = 0; i < TEST_COUNT; i++) { bflb_adc_start_conversion(adc); while (bflb_adc_get_count(adc) < TEST_ADC_CHANNELS) { bflb_mtimer_delay_ms(1); } for (size_t j = 0; j < TEST_ADC_CHANNELS; j++) { struct bflb_adc_result_s result; uint32_t raw_data = bflb_adc_read_raw(adc); printf("raw data:%08x\r\n", raw_data); bflb_adc_parse_result(adc, &raw_data, &result, 1); printf("pos chan %d,neg chan %d,%d mv \r\n", result.pos_chan, result.neg_chan, result.millivolt); } bflb_adc_stop_conversion(adc); bflb_mtimer_delay_ms(100); } while (1) { } }根据以上代码对bl618程序的编写对以下stm32中代码#include "stm32f10x.h" #include "delay.h" #include "FSR.h" #include "usart.h" #include "adc.h" #define PRESS_MIN 20 #define PRESS_MAX 6000 #define VOLTAGE_MIN 150 #define VOLTAGE_MAX 3300 u8 state = 0; u16 val = 0; u16 value_AD = 0; long PRESS_AO = 0; int VOLTAGE_AO = 0; long map(long x, long in_min, long in_max, long out_min, long out_max); int main(void) { delay_init(); NVIC_Configuration(); uart_init(9600); Adc_Init(); delay_ms(1000); printf("Test start\r\n"); while(1) { value_AD = Get_Adc_Average(1,10); VOLTAGE_AO = map(value_AD, 0, 4095, 0, 3300); if(VOLTAGE_AO < VOLTAGE_MIN) { PRESS_AO = 0; } else if(VOLTAGE_AO > VOLTAGE_MAX) { PRESS_AO = PRESS_MAX; } else { PRESS_AO = map(VOLTAGE_AO, VOLTAGE_MIN, VOLTAGE_MAX, PRESS_MIN, PRESS_MAX); } printf("ADÖµ = %d,µçѹ = %d mv,ѹÁ¦ = %ld g\r\n",value_AD,VOLTAGE_AO,PRESS_AO); delay_ms(500); } } long map(long x, long in_min, long in_max, long out_min, long out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; }移植到bl618进行改写
05-12
以下是将上述STM32代码移植到BL618进行改写后的代码: ```c #include "bl602.h" #include "bl_adc.h" #include "bl_gpio.h" #include "bl_mtimer.h" #include "stdio.h" #define PRESS_MIN 20 #define PRESS_MAX 6000 #define VOLTAGE_MIN 150 #define VOLTAGE_MAX 3300 #define ADC_CHANNEL 0 #define ADC_CLK_DIV 5 #define ADC_RESOLUTION ADC_RESOLUTION_12B #define ADC_VREF ADC_VREF_3V3 long map(long x, long in_min, long in_max, long out_min, long out_max); int main(void) { bl_mtimer_init(); bl_gpio_enable_output(PIN_11, 1); bl_adc_init(); bl_adc_config_t cfg = { .inputMode = ADC_INPUT_SINGLE_END_MODE, .input = ADC_INPUT_CH0, .clkDiv = ADC_CLK_DIV, .resolution = ADC_RESOLUTION, .refSel = ADC_VREF, }; bl_adc_channel_config(ADC_CHANNEL, &cfg); printf("Test start\r\n"); while (1) { bl_adc_start(); while (!bl_adc_fifo_data_count()) { bl_mtimer_delay_us(100); } uint16_t value_AD = bl_adc_read_fifo_data(); int VOLTAGE_AO = map(value_AD, 0, 4095, 0, 3300); long PRESS_AO = 0; if (VOLTAGE_AO < VOLTAGE_MIN) { PRESS_AO = 0; } else if (VOLTAGE_AO > VOLTAGE_MAX) { PRESS_AO = PRESS_MAX; } else { PRESS_AO = map(VOLTAGE_AO, VOLTAGE_MIN, VOLTAGE_MAX, PRESS_MIN, PRESS_MAX); } printf("AD value = %d, voltage = %d mV, pressure = %ld g\r\n", value_AD, VOLTAGE_AO, PRESS_AO); bl_mtimer_delay_us(500000); } } long map(long x, long in_min, long in_max, long out_min, long out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } ``` 在BL618中,需要使用`bl_adc_init()`进行ADC块的初始化,并通过`bl_adc_channel_config()`配置ADC通道。需要注意的是,BL618的ADC块不支持差分,因此需要将原来的差分改为单端。在进行ADC转换时,可以使用`bl_adc_start()`触发转换,并通过`bl_adc_fifo_data_count()`和`bl_adc_read_fifo_data()`获取转换结果。此外,由于BL618中没有提供延时函数,需要使用`bl_mtimer_delay_us()`进行延时。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

勾栏听曲_0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值