这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» 国产MCU» 灵动微MM32G0001A6T的ADC转换---任意通道单次周期转换模式

共4条 1/1 1 跳转至

灵动微MM32G0001A6T的ADC转换---任意通道单次周期转换模式

专家
2024-01-13 19:04:28 被打赏50分(兑奖) 打赏

在单周期扫描模式下,A/D 转换通道依软件配置执行一遍,具体流程如下:

1、软件设置寄存器 ADC_ANY_CFG,ADC_CHANY0,ADC_CHANY1,将需要转换的通道、数量设置好,然后置位 CHANY_MDEN。

2、通过软件、外部触发置位 ADCR 寄存器的 ADST,外部触发可软件配置触发延时,A/D 转换方向从CHANY_SEL0 到 CHANY_SEL8 转换通道数量由 CHANY_NUM 配置, 且 CHANY_SEL0 到CHANY_SEL8 是任意配置的,可以完全相同,或完全不相同。

3、每路 A/D 转换完成时,A/D 转换的数据值将有序装载到相应通道的数据寄存器中,ADIF 转换结束标志被设置,若此时控制寄存器 ADCR 的 ADIE 位置 1,将产生 AD 转换结束中断请求。

4、A/D 转换结束后,ADST 位自动清 0,A/D 转换器进入空闲模式。

若在 A/D 转换过程中,软件更新 ADC_ANY_CFG, ADC_CHANY0, ADC_CHANY1,硬件不会立即更新这些配置,只会在当前设置的通道都转换结束时更新,然后等待下一次软件软件置位 ADST。

1.png按照以上说明,我们使用库函数模式,编程测试这种模式下的ADC处理。使用PA3作为ADC的输入,设置ADC中断。每次转换完成后,通过OLED显示,并输出给串口2。根据功能服用,需要设置PA3用于ADC输入通道。

2.png引脚说明:

图片1.png为此在设置ADC时,需要设置ADC1的通道2,并使PA3作为输入口:

主要代码如下:


// 初始化ADC设备,此处只使用PA3作为输入通道 void ADC_Configure(void) { ADC_InitTypeDef ADC_InitStruct; GPIO_InitTypeDef GPIO_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; // 允许时钟 RCC_APB1PeriphClockCmd(RCC_APB1ENR_ADC1, ENABLE); ADC_StructInit(&ADC_InitStruct); ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b; // 设置分辨率 ADC_InitStruct.ADC_PRESCARE = ADC_PCLK1_PRESCARE_16; // 时钟分频 ADC_InitStruct.ADC_Mode = ADC_Mode_Scan; // 模式:单次周期 ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐 ADC_Init(ADC1, &ADC_InitStruct); ADC_SampleTimeConfig(ADC1, ADC_Samctl_240_5); ADC_ClearFlag(ADC1, ADC_FLAG_EOC); // 清除比较标志 ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); // 允许转换中断 RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE); /* 配置输入通道:PA3(通道2) */ GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置ADC中断 NVIC_InitStruct.NVIC_IRQChannel = ADC1_IRQn; NVIC_InitStruct.NVIC_IRQChannelPriority = 0x01; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); // 使能ADEN位,即使能ADC转换 ADC_Cmd(ADC1, ENABLE); } // 获取ADC通道数据。ADC完成后会产生中断 float ADC_GetChannelVoltage(ADCCHANNEL_TypeDef Channel) { uint16_t Value = 0; float Voltage; ADC_ANY_NUM_Config(ADC1, 0); ADC_ANY_CH_Config(ADC1, 0, Channel); ADC_ANY_Cmd(ADC1, ENABLE); // 清除中断标志 ADC_InterruptFlag = 0; // 启动转换 ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 等待ADC转换完成后产生的中断标志 while (0 == ADC_InterruptFlag) { } // 取得转换结果 Value = ADC_GetConversionValue(ADC1); adc_result = Value; // 禁止中断 ADC_ANY_Cmd(ADC1, DISABLE); // 转换为电压值 Voltage = (float)Value / (float)4096 * (float)3.3; return (Voltage); }

中断处理:


void ADC1_IRQHandler(void) { if (RESET != ADC_GetITStatus(ADC1, ADC_IT_EOC)) { // 设置中断标志 ADC_InterruptFlag = 1; // 清除状态标志:转换完成的中断标志 ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); } }


测试结果:


感觉误差还有稍微有点大,不知道是不是和我的测试环境有关。

程序源码:

adc.zip





关键词: 菜鸟学单片机 MM32G0001A6T ADC

高工
2024-01-13 20:22:21 打赏
2楼

学习了


专家
2024-01-14 00:35:23 打赏
3楼

为了调试串口,自己又开始作,把SWCLK配置成串口输出。然后这个片子就彻底挂了,不能再烧录程序,无论如何也恢复不了了。唉,厂家也是,明明有这个问题,就应该有解决办法,比如预留一个BOOT管脚。不知道设计的时候,是咋想的。


专家
2024-01-22 03:21:38 打赏
4楼

学习了,谢谢分享!


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]