打印
[技术问答]

新人求助,华大单片机怎么用ADC单通道采集电压呀?

[复制链接]
2390|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Intelligence|  楼主 | 2020-11-10 16:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
新人求助呀,现在俺卡在这里了,用的是华大HC32L110C6PA芯片,我想用P2.6脚的ADC单通道来采集电压,P2.6连接可调直流电源,用调节电压强弱的模拟量的大小变化从而来对GPIO的LED灯进行亮灭控制,比如当调到10V时3个LED灯亮,调到5V时2个LED灯亮,以此类推,我应该怎么采集和配置呀,求各位英雄好汉路见不平拔刀相助呀!!

使用特权

评论回复
沙发
数码小叶| | 2020-11-11 11:03 | 只看该作者
这个修改下自带的例程就可以搞定了啊。P2.6不应该连接可调直流电源,连接到分压电阻上,10V和5V对应到3.3内的两个电压。

使用特权

评论回复
板凳
tyw| | 2020-11-11 11:35 | 只看该作者
HC32L110系列用户手册Rev2.3 587页 8.6M.pdf (8.49 MB)

使用特权

评论回复
地板
Intelligence|  楼主 | 2020-11-11 13:39 | 只看该作者
数码小叶 发表于 2020-11-11 11:03
这个修改下自带的例程就可以搞定了啊。P2.6不应该连接可调直流电源,连接到分压电阻上,10V和5V对应到3.3内 ...

毕业设计要求是直接用可调直流电源调节控制LED灯的状态,最大采样范围是30V,然后每调低百分之20就熄灭一个LED灯,一直调到全部LED灯都灭,这个行不行呀,求大侠指导呀。

使用特权

评论回复
5
Intelligence|  楼主 | 2020-11-11 13:41 | 只看该作者

看过啦这个手册,但是AD那部分感觉配置说明没看懂呢

使用特权

评论回复
6
Intelligence|  楼主 | 2020-11-11 13:52 | 只看该作者
本帖最后由 Intelligence 于 2020-11-11 13:54 编辑
数码小叶 发表于 2020-11-11 11:03
这个修改下自带的例程就可以搞定了啊。P2.6不应该连接可调直流电源,连接到分压电阻上,10V和5V对应到3.3内 ...

我的主程序是这样写的,
#include "adc.h"
#include "gpio.h"
/*实现功能:3个指示灯显示,
30V下指示灯均亮,调到80%熄灭1个指示灯,
调到60%再熄灭1个指示灯,40%以此类推……
/*****************************************/
/*****************************************/
/*****************************************/
static uint32_t u32AdcResultAcc;
/*****************************************/
/*****************************************/
/*****************************************/
uint16_t Get_Adc_Average(uint8_t ch,uint8_t times)
{
        uint32_t temp_val=0;
        uint8_t t;
        for(t=0;t<times;t++)
        {
                temp_val+=u32AdcResultAcc;
                delay1ms(5);
        }
        return temp_val/times;
}
/*****************************************/
/*****************************************/
/*****************************************/
int32_t main(void)
{
        int16_t adcx;
        float temp;
        stc_adc_cfg_t       stcAdcCfg;
        stc_adc_cont_cfg_t  stcAdcContCfg;
        DDL_ZERO_STRUCT(stcAdcCfg);
        DDL_ZERO_STRUCT(stcAdcContCfg);
        Clk_SwitchTo(ClkRCL);
        Clk_SetRCHFreq(ClkFreq24Mhz);
        Clk_SwitchTo(ClkRCH);
        Clk_SetPeripheralGate(ClkPeripheralGpio, TRUE);              //GPIO 外设时钟使能
        if (Ok != Clk_SetPeripheralGate(ClkPeripheralAdcBgr, TRUE))  //ADCBGR 外设时钟使能
        {
                        return Error;
        }  
        Gpio_SetAnalog(2, 6, TRUE);
        Adc_Enable();
        M0P_BGR->CR_f.BGR_EN = 0x1u;  //BGR使能
        M0P_BGR->CR_f.TS_EN = 0x1u;   //内置温度传感器使能
        delay100us(1);
        stcAdcCfg.enAdcOpMode = AdcContMode;                //连续采样模式
        stcAdcCfg.enAdcClkSel = AdcClkSysTDiv1;             //PCLK
        stcAdcCfg.enAdcSampTimeSel = AdcSampTime12Clk;      //12个采样时钟
        stcAdcCfg.enAdcRefVolSel = RefVolSelAVDD;           //参考电压:AVDD
        stcAdcCfg.bAdcInBufEn = FALSE;                      //电压跟随器如果使能,SPS采样速率 <=200K
        stcAdcCfg.enAdcTrig0Sel = AdcTrigDisable;           //ADC转换自动触发设置
        stcAdcCfg.enAdcTrig1Sel = AdcTrigDisable;
        Adc_Init(&stcAdcCfg);   
        stcAdcContCfg.enAdcContModeCh = AdcExInputCH1;      //通道1 P26
        stcAdcContCfg.u8AdcSampCnt = 0xf9u;                 //连续累加次数
        stcAdcContCfg.bAdcResultAccEn = TRUE;               //累加使能
        Adc_ConfigContMode(&stcAdcCfg, &stcAdcContCfg);
/*****************************************/
/*****************************************/
/*****************************************/
        //GPIO控制输出程序
        //初始化外部GPIO 选择输出、上拉、开漏,3个端口连接LED灯
        Gpio_InitIOExt(1, 4, GpioDirOut, FALSE, FALSE, FALSE, TRUE);
        Gpio_InitIOExt(1, 5, GpioDirOut, FALSE, FALSE, FALSE, TRUE);
        Gpio_InitIOExt(2, 3, GpioDirOut, FALSE, FALSE, FALSE, TRUE);
/*****************************************/
/*****************************************/
/*****************************************/
        //输出低电平,3个LED灯全亮
        Gpio_SetIO(1, 4, FALSE);
        Gpio_SetIO(1, 5, FALSE);
        Gpio_SetIO(2, 3, FALSE);
        while (1)
        {
                Adc_Start();//ADC开始转换
                adcx=Get_Adc_Average(AdcExInputCH1,10);
                u32AdcResultAcc=(float)adcx*(3.3/4096);
                u32AdcResultAcc-=adcx;
                u32AdcResultAcc*=1000;
                adcx=u32AdcResultAcc;
                if(adcx<=3000 && TRUE != M0P_ADC->IFR_f.CONT_INTF)  //等待转换完成
                {
                        Gpio_SetIO(1, 4, TRUE);//输出高电平,熄灭1个LED亮(24v状态=调低百分之20)
                        delay1ms(1000);
                        Gpio_SetIO(1, 4, FALSE);
/*****************************************/
/*****************************************/
/*****************************************/
                        M0P_ADC->ICLR_f.CONT_INTC = 0;     //清除转换完成标志位
                        Adc_GetAccResult(&u32AdcResultAcc);//获取累加采样值
                        Adc_ClrAccResult();//清零累加采样值
                        delay1ms(1000);
                }
                else if(u32AdcResultAcc <=2500 && FALSE != M0P_ADC->IFR_f.CONT_INTF)  //等待转换完成
                {
                        Gpio_SetIO(1, 5, TRUE);//输出高电平,熄灭2个LED亮(18v状态=调低百分之20)
/*****************************************/
/*****************************************/
/*****************************************/
                        M0P_ADC->ICLR_f.CONT_INTC = 0;             //清除转换完成标志位
                        Adc_GetAccResult(&u32AdcResultAcc);//获取累加采样值
                        Adc_ClrAccResult();//清零累加采样值
                        delay1ms(1000);
                }
                else if(u32AdcResultAcc <=2000 && FALSE != M0P_ADC->IFR_f.CONT_INTF)  //等待转换完成
                {
                        Gpio_SetIO(2, 3, TRUE);//输出高电平,熄灭3个LED亮(12v状态=调低百分之20)
/*****************************************/
/*****************************************/
/*****************************************/
                        M0P_ADC->ICLR_f.CONT_INTC = 0;             //清除转换完成标志位
                        Adc_GetAccResult(&u32AdcResultAcc);//获取累加采样值
                        Adc_ClrAccResult();//清零累加采样值
                        delay1ms(1000);
                }
   }
}

使用特权

评论回复
7
Intelligence|  楼主 | 2020-11-11 13:55 | 只看该作者

使用特权

评论回复
8
tyw| | 2020-11-11 14:30 | 只看该作者
Intelligence 发表于 2020-11-11 13:39
毕业设计要求是直接用可调直流电源调节控制LED灯的状态,最大采样范围是30V,然后每调低百分之20就熄灭一 ...

数字电位器.rar (21.9 MB)

直接用数字电位器调电压简单些

使用特权

评论回复
9
Intelligence|  楼主 | 2020-11-11 14:48 | 只看该作者
本帖最后由 Intelligence 于 2020-11-11 14:52 编辑
tyw 发表于 2020-11-11 14:30
直接用数字电位器调电压简单些
还是得回到这个问题解决它才行,因为学校要求必须通过这个,嗷嗷嗷!

使用特权

评论回复
10
Intelligence|  楼主 | 2020-11-11 14:53 | 只看该作者

使用特权

评论回复
11
前功尽弃| | 2020-11-11 15:40 | 只看该作者
首先你输入的电压需要分压,电压太高把芯片搞挂了,还有就是配置的问题,这个是我用130系列芯片配置单通道转换的底层程序,你可以做个参考看看

unsigned short int adc_channle_7;
/*******************************************************************************************
函数  名:adc_con
功能描述:
形参输入:无
返回  值:无
*******************************************************************************************/
void adc_con(void)
{
    unsigned int cnt = 700;
   
    M0P_GPIO->PAADS_f.PA07 = 1;                 //配置成模拟口  
        
    M0P_BGR->CR_f.BGR_EN = 1;                   //使能BRG模块
    M0P_ADC->CR0_f.EN = 1;                      //使能adc模块  
    while(--cnt)                                //延迟20us,等待模块启动完成
    {
        ;
    }
    M0P_ADC->CR0_f.BUF = 0;                    //关闭放大器
        M0P_ADC->CR1_f.MODE = 0;                   //单次转换模式
        
    M0P_ADC->CR0_f.INREFEN = 0;                //禁用内部参考电压
    M0P_ADC->CR0_f.REF = 3;                    //参考电压为AVCC
    M0P_ADC->CR0_f.CLKDIV = 3;                 //1/8分频
    M0P_ADC->CR0_f.SAM = 3;                    //采样周期为12个转换周期
  
    M0P_ADC->CR0_f.SGLMUX = 7;    //转换AN7(PA07)
        
    M0P_ADC->CR1_f.ALIGN = 0;                  //转换结果16位右对齐
    M0P_ADC->ICR_f.SGLIC = 0;                  //清除转换完成标志位   
    M0P_ADC->CR0_f.IE = 1;                     //使能adc中断
    NVIC_EnableIRQ(ADC_IRQn);         
   
    M0P_ADC->SGLSTART_f.START = 0;             //关闭adc转换
   

    adc_channle_7 = 0;
}


/*******************************************************************************************
函数  名:adc_channle_7_get
功能描述:供上层调用读取
形参输入:无
返回  值:adc_channle_7 -> 7通道ad值
*******************************************************************************************/
unsigned int adc_channle_7_get(void)
{
    return adc_channle_7;
}


/*******************************************************************************************
函数  名:adc_on
功能描述:开启adc转换
形参输入:无
返回  值:无
*******************************************************************************************/
void adc_on(void)
{
    M0P_ADC->SGLSTART_f.START = 1;             //开启adc转换
}


/*******************************************************************************************
函数  名:adc_off
功能描述:关闭adc转换
形参输入:无
返回  值:无
*******************************************************************************************/
void adc_off(void)
{
    M0P_ADC->SGLSTART_f.START = 0;             //关闭adc转换
}



/*******************************************************************************************
函数  名:ADC_IRQHandler
功能描述:adc中断处理,将转换完成的ad值赋值给缓存值
形参输入:无
返回  值:无
*******************************************************************************************/
void ADC_IRQHandler(void)
{            if(M0P_ADC ->IFR_f.SGLIF)        
        {
                M0P_ADC->ICR_f.SGLIC = 0;
                adc_channle_7 = M0P_ADC ->RESULT;
        }
}

使用特权

评论回复
12
数码小叶| | 2020-11-11 15:48 | 只看该作者
Intelligence 发表于 2020-11-11 13:52
我的主程序是这样写的,
#include "adc.h"
#include "gpio.h"

整体逻辑没问题,搞不懂这个在干嘛
  adcx=Get_Adc_Average(AdcExInputCH1,10);
                u32AdcResultAcc=(float)adcx*(3.3/4096);
                u32AdcResultAcc-=adcx;
                u32AdcResultAcc*=1000;
                adcx=u32AdcResultAcc;

获取采样值,转化成电压,后面就看不懂了

使用特权

评论回复
13
数码小叶| | 2020-11-11 15:49 | 只看该作者
Intelligence 发表于 2020-11-11 13:39
毕业设计要求是直接用可调直流电源调节控制LED灯的状态,最大采样范围是30V,然后每调低百分之20就熄灭一 ...

你都可以来个附加的,增大20%就再亮一个都没问题

使用特权

评论回复
14
Intelligence|  楼主 | 2020-11-11 15:53 | 只看该作者
数码小叶 发表于 2020-11-11 15:48
整体逻辑没问题,搞不懂这个在干嘛

获取采样值,转化成电压,后面就看不懂了 ...

就是这里我希望把采集到的数据 放在adcx里面 然后再通过分支判断语句来控制GPIO点灯

使用特权

评论回复
15
数码小叶| | 2020-11-11 15:55 | 只看该作者
Intelligence 发表于 2020-11-11 15:53
就是这里我希望把采集到的数据 放在adcx里面 然后再通过分支判断语句来控制GPIO点灯 ...

你要这么说的话,adcx=Get_Adc_Average(AdcExInputCH1,10);这一句不就够了。。。。。

使用特权

评论回复
评论
Intelligence 2020-11-12 13:46 回复TA
谢谢大侠指出,确实是呀,我把没用的删除了,只要这句都可以呢,哈哈哈。 
16
数码小叶| | 2020-11-11 15:56 | 只看该作者
Intelligence 发表于 2020-11-11 15:53
就是这里我希望把采集到的数据 放在adcx里面 然后再通过分支判断语句来控制GPIO点灯 ...

还有你的分压比呢,你直接接接进去,有多少单片机就烧多少个单片机

使用特权

评论回复
17
Intelligence|  楼主 | 2020-11-11 15:57 | 只看该作者
Intelligence 发表于 2020-11-11 15:53
就是这里我希望把采集到的数据 放在adcx里面 然后再通过分支判断语句来控制GPIO点灯 ...

uint16_t Get_Adc_Average(uint8_t ch,uint8_t times)
{
        uint32_t temp_val=0;
        uint8_t t;
        for(t=0;t<times;t++)
        {
                temp_val+=u32AdcResultAcc;
                delay1ms(5);
        }
        return temp_val/times;
}
【Get_Adc_Average】这是定义的一个采集函数

使用特权

评论回复
18
Intelligence|  楼主 | 2020-11-11 16:01 | 只看该作者
数码小叶 发表于 2020-11-11 15:48
整体逻辑没问题,搞不懂这个在干嘛

获取采样值,转化成电压,后面就看不懂了 ...

                Adc_Start();//ADC开始转换
                Adc_SetVref(adcx);//设置ADC参考电压
                adcx=Get_Adc_Average(AdcExInputCH1,10);//设置通道1
                u32AdcResultAcc=(float)adcx*(3.3/4095);//设置参考电压的参考值采集范围-3.3V/4095
                u32AdcResultAcc-=adcx;//对采集到的电压进行运算
                u32AdcResultAcc*=1000;//对采集到的电压进行运算
                adcx=u32AdcResultAcc;//将采集电压的变量赋予adcx
                Adc_GetAccResult(&u32AdcResultAcc);//获取累加采样值
就是这里我也不知道这样写是不是正确的,就是不知道采集的方法和配置是不是这样操作,我处于一个懵逼状态呢,求求大侠帮帮俺吧,让今后更多用国产芯片的小白也可以得到帮助!

使用特权

评论回复
19
Intelligence|  楼主 | 2020-11-11 16:02 | 只看该作者

使用特权

评论回复
20
Intelligence|  楼主 | 2020-11-11 16:04 | 只看该作者
数码小叶 发表于 2020-11-11 15:49
你都可以来个附加的,增大20%就再亮一个都没问题

可以呀,我想的也是通过控制输入电压来点灯呢,调到30V就全部点亮,降到24V就熄灭一个,在升30V又开始亮,哈哈哈!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

20

帖子

0

粉丝