[其他]

华大HC32L110全是坑

[复制链接]
17497|96
手机看帖
扫描二维码
随时随地手机跟帖
Q80351951|  楼主 | 2019-5-26 12:10 | 显示全部楼层 |阅读模式
有个低功耗项目,本来想用新塘新品ML51,为了支持国产,看到华大HC32L110也可以,画了块板,谁知这个货一步一个坑,手册写的也不严谨,历程不全且不细致,现在问题ADC单次采集外部通道一切正常,但采集内部温度传感器和1/3VCC就是不行,有关这2路也已经按照手册进行了设置,另外若完全按手册ADC设置流程配置保准都不行,白白浪费我好多天时间,再不行只能放弃。
函数库写的很复杂,一个小小的单片机搞这么复杂干嘛,想不用函数库或用部分函数,部分这届寄存器,但发现好多具体问题,连个中断函数都搞成回调,改了吧又怕和官方不兼容。

使用特权

评论回复
评论
cooldog123pp 2019-5-28 09:03 回复TA
国产IC直接找他们FAE啊,可以直接帮你方案做好了给你,量产就行了。 
smartpower| | 2019-5-26 14:21 | 显示全部楼层
请留下联系方式,会有FAE跟进解决。

使用特权

评论回复
smartpower| | 2019-5-26 14:24 | 显示全部楼层
根据据你的描述,可能是没有打开ADC内的BUFEN.
-----------------------------
寄存器中关于采样1/3VCC及温度传器器的说明如下。
0101:选择通道5输入P3.5
0110:选择通道6输入P3.6
0111:选择通道7输入P0.1
1000:选择通道8输入P0.2
1001:1/3VCC 注:ADC_CR0.BUFEN必须为1
1010:内置温度传感器输出电压 注:ADC_CR0.BUFEN必须为1
1011:内部基准1.2V输出电压 注:ADC_CR0.BUFEN必须为1

使用特权

评论回复
martinhu| | 2019-5-26 14:39 | 显示全部楼层
开启buff之后,也有注意采用速率,ADC_Clk   /(采样时间(4~12clk)+转换时间16个clk),不得超过200K。

使用特权

评论回复
Q80351951|  楼主 | 2019-5-26 14:46 | 显示全部楼层
smartpower 发表于 2019-5-26 14:24
根据据你的描述,可能是没有打开ADC内的BUFEN.
-----------------------------
寄存器中关于采样1/3VCC及温 ...

开了

使用特权

评论回复
martinhu| | 2019-5-26 14:59 | 显示全部楼层

能否把你的代码贴上来看看?

使用特权

评论回复
Q80351951|  楼主 | 2019-5-26 15:02 | 显示全部楼层
本帖最后由 Q80351951 于 2019-5-26 15:14 编辑
martinhu 发表于 2019-5-26 14:59
能否把你的代码贴上来看看?

uint32_t init_adc(void)
{
/*
        DDL_ZERO_STRUCT(stcAdcCfg);
        DDL_ZERO_STRUCT(stcAdcContCfg);
        DDL_ZERO_STRUCT(stcAdcIrq);
        DDL_ZERO_STRUCT(stcAdcIrqCalbaks);
        //ADC配置
        Adc_Enable();
        M0P_BGR->CR_f.BGR_EN = 0x1u;  //BGR必须使能
        M0P_BGR->CR_f.TS_EN = 0x1u;   //内置温度传感器,视使用需求
        delay100us(1);

        stcAdcCfg.bAdcInBufEn = 1;
        stcAdcCfg.enAdcOpMode = AdcNormalMode;                //连续采样模式
        stcAdcCfg.enAdcClkSel = AdcClkSysTDiv2;             //PCLK
        stcAdcCfg.enAdcSampTimeSel = AdcSampTime4Clk;       //8个采样时钟
        stcAdcCfg.enAdcRefVolSel = RefVolSelInBgr2p5;    //参考电压:内部2.5V(avdd>3V,SPS<=200kHz)
   //stcAdcCfg.enAdcRefVolSel = RefVolSelAVDD;           //参考电压:AVDD
   stcAdcCfg.bAdcInBufEn = TRUE;
         //stcAdcCfg.bAdcInBufEn = FALSE;                      //电压跟随器如果使能,SPS采样速率 <=200K
        stcAdcCfg.enAdcTrig0Sel = AdcTrigDisable;           //ADC转换自动触发设置
        stcAdcCfg.enAdcTrig1Sel = AdcTrigDisable;
        Adc_Init(&stcAdcCfg);

        stcAdcIrq.bAdcIrq = TRUE;                            //转换完成中断函数入口配置使能
        stcAdcIrq.bAdcRegCmp = FALSE;
        stcAdcIrq.bAdcHhtCmp = FALSE;
        stcAdcIrq.bAdcLltCmp = FALSE;
        stcAdcIrqCalbaks.pfnAdcContIrq = AdcContIrqCallback; //转换完成中断入口函数
        Adc_ConfigIrq(&stcAdcIrq, &stcAdcIrqCalbaks);        //转换中断入口函数配置
        Adc_EnableIrq();                                     //中断使能
        Adc_CmpCfg(&stcAdcIrq);                              //结果比较中断使能/禁止配置


        stcAdcContCfg.enAdcContModeCh = AdcExInputCH4;      //通道0 P24
//        stcAdcContCfg.enAdcContModeCh = ADCIN_VCC;      //通道0 P24
        stcAdcContCfg.u8AdcSampCnt = 0x00u;                 //P24 连续累加次数(次数 = 0x09+1)
        stcAdcContCfg.bAdcResultAccEn = FALSE;               //累加使能
        Adc_ConfigContMode(&stcAdcCfg, &stcAdcContCfg);

*/


M0P_ADC->CR0_f.ADCEN = 1u;
        M0P_BGR->CR_f.BGR_EN = 0x1u;  //BGR必须使能
        M0P_BGR->CR_f.TS_EN = 0x1u;   //内置温度传感器,视使用需求
        delay100us(1);
        
    M0P_ADC->CR0_f.SEL = ADCIN_temp;
    M0P_ADC->CR0_f.ADCEN = 1u;
    M0P_ADC->CR0_f.CLKSEL = AdcClkSysTDiv2;//pstcAdcConfig->enAdcClkSel;
    M0P_ADC->CR0_f.SAM = AdcSampTime4Clk;//pstcAdcConfig->enAdcSampTimeSel;
    M0P_ADC->CR0_f.SREF = RefVolSelInBgr2p5;//pstcAdcConfig->enAdcRefVolSel;
    M0P_ADC->CR1_f.CT = 0u;
    M0P_ADC->CR0_f.BUFEN = TRUE;//pstcAdcConfig->bAdcInBufEn;
               
    M0P_ADC->CR0_f.IE = 1u;
    M0P_ADC->CR1_f.REGCMP = 0u;
    M0P_ADC->CR1_f.HTCMP = 0u;
    M0P_ADC->CR1_f.LTCMP = 0u;
                M0P_ADC->CR1_f.RACC_EN = 0u;
                M0P_ADC->CR1_f.TRIGS0 = 0u;
                M0P_ADC->CR1_f.TRIGS1 = 0u;
                M0P_ADC->CR2_f.ADCCNT = 0u;
                M0P_ADC->CR2_f.CH0EN = 0u;
                M0P_ADC->CR2_f.CH1EN = 0u;
                M0P_ADC->CR2_f.CH2EN  = 0u;
                M0P_ADC->CR2_f.CH3EN  = 0u;
                M0P_ADC->CR2_f.CH4EN  = 0u;
                M0P_ADC->CR2_f.CH5EN  = 0u;
                M0P_ADC->CR2_f.CH6EN  = 0u;
                M0P_ADC->CR2_f.CH7EN  = 0u;  
               
        EnableNvic(ADC_IRQn, 3, TRUE);   
               
        return Ok;
}

void ADC_IRQHandler(void)
{
  M0P_ADC->ICLR_f.CONT_INTC = 0u;  
        adc_count++;
  AD.ch++;
        switch (AD.ch)
        {
        case 1:
                M0P_ADC->CR0_f.SEL = ADCIN_300v;
                AD.temp += M0P_ADC->RESULT_f.RESULT;//取温度AD数据  
    M0P_ADC->CR0_f.START = 1u;
                break;
        case 2:
                M0P_ADC->CR0_f.SEL = ADCIN_bright;
                AD.R3 += M0P_ADC->RESULT_f.RESULT;//取电阻AD数据   
    M0P_ADC->CR0_f.START = 1u;
                break;
        case 3:
                M0P_ADC->CR0_f.SEL = ADCIN_batt;
                AD.bright += M0P_ADC->RESULT_f.RESULT;                        //取光敏AD数据  
    M0P_ADC->CR0_f.START = 1u;
                break;
        case 4:
                M0P_ADC->CR0_f.SEL = ADCIN_temp;
                AD.batt += M0P_ADC->RESULT_f.RESULT;                        //取光敏AD数据  
                break;
        }
}

SCS_SETENA 01008040
SCS_IPR0 00000000
SCS_IPR1 00C00000
SCS_IPR2 00000000
SCS_IPR3 C0000000
SCS_IPR4 00000000
SCS_IPR5 00000000
SCS_IPR6 000000C0
SCS_IPR7 00000000
ADC_CR0 4565
ADC_CR1 0000
ADC_CR2 0000
ADC_IFR 0000
ADC_ICLR 000F

使用特权

评论回复
martinhu| | 2019-5-26 15:39 | 显示全部楼层
Q80351951 发表于 2019-5-26 15:02
uint32_t init_adc(void)
{
/*

你这样配置,ADC中断是有问题的,因为单次转换原本是靠查询,不会产生中断的,手册的步骤也只写了查询。
如果想要使用中断功能,可以借助区间比较的中断功能

使用特权

评论回复
Q80351951|  楼主 | 2019-5-26 15:53 | 显示全部楼层
martinhu 发表于 2019-5-26 15:39
你这样配置,ADC中断是有问题的,因为单次转换原本是靠查询,不会产生中断的,手册的步骤也只写了查询。
...

你意思是, ADC单次转换不能中断?这不就成半残废了?奇葩。

使用特权

评论回复
martinhu| | 2019-5-26 16:26 | 显示全部楼层
本帖最后由 martinhu 于 2019-5-27 09:36 编辑

你没看明白我的意思,我是说,可以通过区间比较中断的方式用中断处理。因为这里面就是两个中断,一个是连续转换的中断,一个是区间比较的中断,你不能用单次转换来使用连续转换的中断吧?
看你的代码是用寄存器写的,我刚刚也写了一下,分别是用单次采样的查询和中断两种方式采样1/3Vcc和内部温度传感器,
请参考:
这个是查询方式(main.c文件)
int32_t main(void)
{
    M0P_CLOCK->PERI_CLKEN_f.ADC = 1;
    M0P_CLOCK->PERI_CLKEN_f.GPIO = 1;
   
    M0P_ADC->CR0_f.ADCEN = 1u;
    M0P_BGR->CR_f.BGR_EN = 0x1u;  //BGR enable
    M0P_BGR->CR_f.TS_EN = 0x1u;
   
    delay100us(1);
   
    M0P_ADC->CR1_f.CT = 0;
    M0P_ADC->CR0_f.SREF = 1;    //2.5V
    M0P_ADC->CR0_f.CLKSEL = 0;  //0:PCLK,
    M0P_ADC->CR0_f.SAM = 3;     //3:12 clk,
    M0P_ADC->CR0_f.BUFEN = 1;
   
    /*
    When System clk is 4MHz, ADC SPS  = 4MHz / (12+ 16) = 143K.
   
    If the BUFEN is set as enable, the ADC SPS must be set less than 200K
    */
   
    while (1)
    {
        M0P_ADC->CR0_f.SEL = 9;  //1/3Vcc
        M0P_ADC->CR0_f.START = 1;
        while(1 == M0P_ADC->CR0_f.START);
        u16AdcVal01 = M0P_ADC->RESULT_f.RESULT;
        
        M0P_ADC->CR0_f.SEL = 10;  //temprature
        M0P_ADC->CR0_f.START = 1;
        while(1 == M0P_ADC->CR0_f.START);
        u16AdcVal02 = M0P_ADC->RESULT_f.RESULT;
    }
}

这个是中断方式:

(main.c文件)
void Adc_Int(void)   
{
    if(1 == M0P_ADC->IFR_f.HHT_INTF)
    {
        if(9 == u8FlagChannel)
        {
            u16AdcVal01 = M0P_ADC->RESULT_f.RESULT;
        }
        else if( 10 == u8FlagChannel)
        {
            u16AdcVal02 = M0P_ADC->RESULT_f.RESULT;
        }
        else
        {
        }

        M0P_ADC->ICLR_f.HHT_INTC = 0;
    }
}

int32_t main(void)
{
    M0P_CLOCK->PERI_CLKEN_f.ADC = 1;
    M0P_CLOCK->PERI_CLKEN_f.GPIO = 1;

    M0P_ADC->CR0_f.ADCEN = 1u;
    M0P_BGR->CR_f.BGR_EN = 0x1u;  //BGR enable
    M0P_BGR->CR_f.TS_EN = 0x1u;

    delay100us(1);

    M0P_ADC->CR1_f.CT = 0;
    M0P_ADC->CR0_f.SREF = 1;    //2.5V
    M0P_ADC->CR0_f.CLKSEL = 0;  //0:PCLK,
    M0P_ADC->CR0_f.SAM = 3;     //3:12 clk,
    M0P_ADC->CR0_f.BUFEN = 1;

    /*
    When System clk is 4MHz, ADC SPS  = 4MHz / (12+ 16) = 143K.

    If the BUFEN is set as enable, the ADC SPS must be set less than 200K
    */
    M0P_ADC->HT_f.HT = 0;
    //M0P_ADC->LT_f.LT = 0;
    //M0P_ADC->CR1_f.REGCMP = 1;
    M0P_ADC->CR1_f.HTCMP = 1;
    //M0P_ADC->CR1_f.LTCMP = 1;
    M0P_ADC->CR0_f.IE = 1;
    EnableNvic(ADC_IRQn,3,TRUE);

    while (1)
    {
        M0P_ADC->CR0_f.SEL = 9;  //1/3Vcc
        u8FlagChannel = 9;
        M0P_ADC->CR0_f.START = 1;

        delay100us(1);

        M0P_ADC->CR0_f.SEL = 10;  //temprature
        u8FlagChannel = 10;
        M0P_ADC->CR0_f.START = 1;

        delay100us(1);
    }
}

(interrupts_hc32l110.c文件):
void ADC_IRQHandler(void)
{
    //Adc_IRQHandler(0);
    Adc_Int();
   
}

(interrupts_hc32l110.h文件):
extern void Adc_Int(void);


HC32L110_DDL_Rev1.0.2_ADC_Single_Polling.zip

302.66 KB

HC32L110_DDL_Rev1.0.2_ADC_Single_Int.zip

296.45 KB

使用特权

评论回复
congfenglong| | 2019-5-27 07:03 | 显示全部楼层
全身坑啊全是坑

使用特权

评论回复
评论
HDSCMCU 2019-5-27 09:13 回复TA
有写的不好或不便的地方,欢迎提出,我们一定即时修改相关手册,让各位有更便捷的使用体验^_^ 
HDSCMCU 2019-5-27 09:02 回复TA
您要是认为有什么问题,可以提出来沟通,咱FAE会第一时间解疑答惑^_^ 
p8s| | 2019-5-27 08:41 | 显示全部楼层
有个项目刚用了110,低功耗非常好,1000uf电容工作15分钟没问题,但没用AD,效果还不错,有问题找FAE基本都能解决,目前用了这么多单 片机,华大的FAE还是很不错的,希望工程师们大力支持,都用国内芯片。

使用特权

评论回复
zhiyonghe| | 2019-5-27 09:07 | 显示全部楼层
台湾新唐也算国产货吧?

使用特权

评论回复
评论
traveo 2020-5-29 17:31 回复TA
@戈卫东 :认识! 
戈卫东 2019-5-28 08:09 回复TA
不知道新唐的人认不认 
WOFY| | 2019-5-27 11:52 | 显示全部楼层
用国产芯片千万别用库,千万别用库,宁愿自己多折腾一下程序,也别用他们的库。看数据手册是考验你语文功底了,并且一定要看最新的数据手册!不然可能你调试一直有问题的某功能在最新的数据手册里该已经被删除了。我不是国产黑,以上只是我使用几款国产芯片之后的真实体验和衷心提醒。这是现阶段国产芯片普遍存在的问题,希望今后越来越好!

使用特权

评论回复
评论
tianqi911 2020-5-15 11:59 回复TA
只能慢慢来。刚开始接触华大的arm 
WOFY 2019-5-29 15:34 回复TA
@wh6ic :嗯,最怕的就是库函数有问题,这种情况FAE都会懵逼,我有经历过因为库函数BUG而浪费两天时间的事,后面就养成了能不用库就不用库的习惯。慢慢地发现直接调用寄存器也挺爽。 
wh6ic 2019-5-29 11:51 回复TA
正常,很早以前用 Ti 的 ADS8345,也是一堆坑,它的FAE也解决不了,惊动了白皮,也没有下文。后来是无意中,写错了代码,反而成功读出来了 
qcliu| | 2019-5-27 11:54 | 显示全部楼层
应该不是坑 为了开发方便而已

使用特权

评论回复
tfqi| | 2019-5-27 11:56 | 显示全部楼层
我觉得每个厂家的都是这样啊  没啥坑不坑的说法吧

使用特权

评论回复
zljiu| | 2019-5-27 12:42 | 显示全部楼层
只能说明楼主代码读的还比较少

使用特权

评论回复
coshi| | 2019-5-27 12:48 | 显示全部楼层
以前我刚接触st的时候 也有这种感觉 不过看多了 也就习惯了 楼主也慢慢适应吧

使用特权

评论回复
Q80351951|  楼主 | 2019-5-27 12:52 | 显示全部楼层
martinhu 发表于 2019-5-26 16:26
你没看明白我的意思,我是说,可以通过区间比较中断的方式用中断处理。因为这里面就是两个中断,一个是连续 ...

多谢已经搞定了,问题出在不知道AD单次竟然不会中断,表示这个设计很奇葩,之前能用原因是我自己都没注意是开着连续转换,好在还有变通的方法,昨天就已经搞定了。

使用特权

评论回复
Q80351951|  楼主 | 2019-5-27 13:02 | 显示全部楼层
本帖最后由 Q80351951 于 2019-5-27 13:04 编辑

本来就使用的一个新的芯片有些寄存器不了解,用库也是顺藤摸瓜,但库搞的太复杂那这根藤就有点太长了,不出问题很快,出了问题还得一点一点查找反而浪费时间,库可以有,也应该有,也很有用但不要搞那么复杂,太复杂没意义,毕竟有时还会遇到空间不够的时候,当你用一款芯片用久了,就不再用库了,节省资源。用过几款带库的,我基本上就是越用调用库函数越少。

使用特权

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

本版积分规则

43

主题

253

帖子

5

粉丝