打印
[其他]

【HC32L196PCTA测评】7.ADC+发现一个驱动文件错误+DAC测试

[复制链接]
833|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 yuyy1989 于 2023-8-8 19:17 编辑

#申请原创# @21小跑堂  
7.ADC+发现一个驱动文件错误+DAC测试
7.1ADC测试
ADC(Analog to Digital Converter)模拟量转换为数字量,有些外设输出的是模拟量电压,这时就需要用ADC将模拟量转换为数字量来计算,在低功耗的设备中常用来检测电池电压,HC32L196内部集成了一个12位的ADC,30个输入通道,包括26路外部管脚输入、1路内部温度传感器电压、1路1/3电源电压、1路内建BGR1.2V电压、DAC内部输出

使用ADC时还需要使能BGR控制寄存器

先来测一下内置温度传感器,这个不需要外接其它设备测起来比较方便
初始化ADC模块

void adc_init()
{
    stc_adc_cfg_t              stcAdcCfg;
    DDL_ZERO_STRUCT(stcAdcCfg);
    ///< 开启ADC/BGR外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE);
    Bgr_BgrEnable();
    Bgr_TempSensorEnable();
    ///< ADC 初始化配置
    stcAdcCfg.enAdcMode         = AdcSglMode;               ///<采样模式-单次
    stcAdcCfg.enAdcClkDiv       = AdcMskClkDiv1;            ///<采样分频-1
    stcAdcCfg.enAdcSampCycleSel = AdcMskSampCycle12Clk;     ///<采样周期数-12
    stcAdcCfg.enAdcRefVolSel    = AdcMskRefVolSelInBgr2p5;  ///<参考电压选择-内部2.5V
    stcAdcCfg.enAdcOpBuf        = AdcMskBufEnable;          ///<打开放大器
    stcAdcCfg.enInRef           = AdcMskInRefEnable;        ///<内部参考电压使能-开
    stcAdcCfg.enAdcAlign        = AdcAlignRight;            ///<转换结果对齐方式-右
    Adc_Init(&stcAdcCfg);
    ///< 配置单次采样通道
    Adc_CfgSglChannel(AdcAiTsInput);
    ///< 启动单次一直采样
    Adc_SGL_Always_Start();
}
然后就发现了一个驱动文件的错误:
写完后发现这里一直报错,已经包含了bgr.h

查看bgr.h发现这里居然是CRC,而我工程里正好还包含了crc.h,修改为BGR后问题解决,打开HC32L19x_DDL_Rev1.2.0.zip压缩包内的原始文件也是CRC,1.1那个也是,希 望官方后续修复吧

手册里有温度计算的方法

在主循环里打印adc和温度

int32_t main(void)
{
    float TemF;
    uint16_t adc_trim;
    uint32_t adc_result;
    xth_init();
    //时钟分频设置
    Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
    Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
    flash_init();
    led_init();
    key_init();
    timer0_init();
    uart0_io_init();
    uart0_init();
    adc_init();
    adc_trim = *((unsigned short int *)0x00100C36);
    while(1)
    {
        if(TRUE == Adc_GetIrqStatus(AdcMskIrqSgl))
        {
            ///< 获取采样值
            adc_result = Adc_GetSglResult();
            TemF = 25 + 0.0795 * 2.5 * ( adc_result - adc_trim );
            printf("ADC %04X% 校准值:%04X 温度:%0.1f℃",adc_result,adc_trim,TemF);
            Adc_ClrIrqStatus(AdcMskIrqSgl);
        }
        yuyy_delay_ms(1000);
    }
}
运行效果

接下来测试一下外部输入,用这个游戏手柄的摇杆作为输入,选用PA00和PA01作为XY方向的输入

参考电压选择AVDD,采样通道0和1,初始化IO和ADC模块

void adc_io_init()
{
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
    Gpio_SetAnalogMode(GpioPortA, GpioPin0);        //PA00 (AIN0)
    Gpio_SetAnalogMode(GpioPortA, GpioPin1);        //PA01 (AIN1)
}
void adc_init()
{
    stc_adc_cfg_t              stcAdcCfg;
    stc_adc_sqr_cfg_t          stcAdcSqrCfg;
    DDL_ZERO_STRUCT(stcAdcCfg);
    ///< 开启ADC/BGR外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE);
    Bgr_BgrEnable();
    ///< ADC 初始化配置
    stcAdcCfg.enAdcMode         = AdcScanMode;              ///<采样模式-扫描
    stcAdcCfg.enAdcClkDiv       = AdcMskClkDiv1;            ///<采样分频-1
    stcAdcCfg.enAdcSampCycleSel = AdcMskSampCycle8Clk;      ///<采样周期数-8
    stcAdcCfg.enAdcRefVolSel    = AdcMskRefVolSelAVDD;      ///<参考电压选择-AVDD
    stcAdcCfg.enAdcOpBuf        = AdcMskBufDisable;         ///<打开放大器
    stcAdcCfg.enInRef           = AdcMskInRefDisable;       ///<内部参考电压使能-关
    stcAdcCfg.enAdcAlign        = AdcAlignRight;            ///<转换结果对齐方式-右
    Adc_Init(&stcAdcCfg);
   
    ///< 顺序扫描模式功能及通道配置
    ///< 注意:扫描模式下,当配置转换次数为n时,转换通道的配置范围必须为[SQRCH(0)MUX,SQRCH(n-1)MUX]
    stcAdcSqrCfg.bSqrDmaTrig = FALSE;
    stcAdcSqrCfg.enResultAcc = AdcResultAccDisable;
    stcAdcSqrCfg.u8SqrCnt    = 2;
    Adc_SqrModeCfg(&stcAdcSqrCfg);

    Adc_CfgSqrChannel(AdcSQRCH0MUX, AdcExInputCH0);
    Adc_CfgSqrChannel(AdcSQRCH1MUX, AdcExInputCH1);
   
    ///< 启动顺序扫描采样
    Adc_SQR_Start();
}
在主循环中打印ADC值
int32_t main(void)
{
    uint32_t adcresult0;
    uint32_t adcresult1;
    xth_init();
    //时钟分频设置
    Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
    Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
   
    flash_init();
    led_init();
    key_init();
    uart0_io_init();
    uart0_init();
    adc_io_init();
    adc_init();
    while(1)
    {
        if(TRUE == Adc_GetIrqStatus(AdcMskIrqSqr))
        {
            Adc_ClrIrqStatus(AdcMskIrqSqr);
            adcresult0   = Adc_GetSqrResult(AdcSQRCH0MUX);  //获取顺序扫描通道0
            adcresult1   = Adc_GetSqrResult(AdcSQRCH1MUX);  //获取顺序扫描通道1
            printf("adc0:%d     adc1:%d",adcresult0,adcresult1);
            Adc_SQR_Start();
        }
        yuyy_delay_ms(200);
    }
}
摇动摇杆在串口工具上查看打印的ADC值的变化

7.2DAC
DAC(Digital to Analog Converter)与ADC模数转换相反,是将数字量转换为模拟量输出,HC32L196内部集成了一个12位的单通道DAC,输出IO是PA04

利用DAC输出一些波形,按键切换波形,初始化IO和DAC模块

void dac_io_init()
{
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);    // 使能GPIO模块的外设时钟
    Gpio_SetAnalogMode(GpioPortA, GpioPin4);       //PA04作为DAC的模拟输出
}

void dac_init()
{
    stc_dac_cfg_t  dac_initstruct;
    Sysctrl_SetPeripheralGate(SysctrlPeripheralDac, TRUE);     ///< 使能DAC模块的时钟
    dac_initstruct.boff_t = DacBoffDisable;
    dac_initstruct.ten_t  = DacTenDisable;
    dac_initstruct.sref_t = DacVoltageAvcc;
    dac_initstruct.wave_t = DacWaveDisable;      
    dac_initstruct.mamp_t = DacMenp4095;
    dac_initstruct.tsel_t = DacSwTriger;          ///< 软件触发方式
    dac_initstruct.align  = DacRightAlign;        ///< 右对齐
    dac_initstruct.dhr12  = 0;
    Dac_Init(&dac_initstruct);
    Dac_Cmd(TRUE);
}
生成波形
void proc_dac_wave()
{
    uint8_t changed = 0;
    switch(wavetype)
    {
        case 0:
            if(wavestep > 0)
                wavestep -= 1;
            else
            {
                if(dacvalue == 0)
                    dacvalue = 255;
                else
                    dacvalue = 0;
                changed = 1;
                wavestep = 9;
            }
            break;
        case 1:
            dacvalue+=1;
            changed = 1;
            break;
        case 2:
            if(wavestep > 0)
                wavestep -= 1;
            else
            {
                wavestep = 10;
                dacvalue+=15;
                changed = 1;
            }
            break;
        case 3:
            if(wavestep < 255)
            {
                dacvalue=wavestep;
                changed = 1;
            }
            else if(wavestep > 300 && wavestep < 556)
            {
                dacvalue= 555 - wavestep;
                changed = 1;
            }
            if(wavestep < 600)
                wavestep++;
            else
                wavestep = 0;
            break;
        case 4:
            if(wavestep < 90)
            {
                dacvalue = sinvalues[wavestep];
                changed = 1;
            }
            else
            {
                dacvalue = sinvalues[180 - wavestep];
                changed = 1;
            }
            if(wavestep < 179)
                wavestep++;
            else
                wavestep = 0;
            break;
        case 5:
            if(wavestep < 90)
            {
                dacvalue = 127 + (sinvalues[wavestep]/2);
                changed = 1;
            }
            else
            {
                dacvalue = 128 - (sinvalues[180 - wavestep]/2);
                changed = 1;
            }
            if(wavestep < 179)
                wavestep++;
            else
                wavestep = 0;
            break;
        case 6:
            if(wavestep < 90)
            {
                dacvalue = 127 + (sinvalues[wavestep]/2);
                changed = 1;
            }
            else if(wavestep < 180)
            {
                dacvalue = 127 + (sinvalues[180 - wavestep]/2);
                changed = 1;
            }
            else if(wavestep < 270)
            {
                dacvalue = 128 - (sinvalues[wavestep - 180]/2);
                changed = 1;
            }
            else
            {
                dacvalue = 128 - (sinvalues[360 - wavestep]/2);
                changed = 1;
            }
            if(wavestep < 359)
                wavestep++;
            else
                wavestep = 0;
            break;
        default:
            break;
    }
    if(changed > 0)
        Dac_SetChannelData(DacRightAlign,DacBit8,dacvalue);
}
波形效果展示,不是示波器波形有点失真


使用特权

评论回复
沙发
tpgf| | 2024-2-5 14:55 | 只看该作者
一般这种低级错误 他们早就应该有勘误文件呀

使用特权

评论回复
板凳
keaibukelian| | 2024-2-5 15:27 | 只看该作者
其实对于128来说 这个波形已经非常圆滑了

使用特权

评论回复
地板
chenjun89| | 2024-2-5 21:35 | 只看该作者
这个波形还是可以的了

使用特权

评论回复
5
renzheshengui| | 2024-2-6 08:31 | 只看该作者
楼主dac外部硬件是连接的什么呢?

使用特权

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

本版积分规则

145

主题

695

帖子

6

粉丝