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

[复制链接]
1618|4
 楼主| yuyy1989 发表于 2023-8-8 19:16 | 显示全部楼层 |阅读模式
本帖最后由 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内部输出
QQ截图20230808112627.png
使用ADC时还需要使能BGR控制寄存器
QQ截图20230808190339.png
先来测一下内置温度传感器,这个不需要外接其它设备测起来比较方便
初始化ADC模块

  1. void adc_init()
  2. {
  3.     stc_adc_cfg_t              stcAdcCfg;
  4.     DDL_ZERO_STRUCT(stcAdcCfg);
  5.     ///< 开启ADC/BGR外设时钟
  6.     Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE);
  7.     Bgr_BgrEnable();
  8.     Bgr_TempSensorEnable();
  9.     ///< ADC 初始化配置
  10.     stcAdcCfg.enAdcMode         = AdcSglMode;               ///<采样模式-单次
  11.     stcAdcCfg.enAdcClkDiv       = AdcMskClkDiv1;            ///<采样分频-1
  12.     stcAdcCfg.enAdcSampCycleSel = AdcMskSampCycle12Clk;     ///<采样周期数-12
  13.     stcAdcCfg.enAdcRefVolSel    = AdcMskRefVolSelInBgr2p5;  ///<参考电压选择-内部2.5V
  14.     stcAdcCfg.enAdcOpBuf        = AdcMskBufEnable;          ///<打开放大器
  15.     stcAdcCfg.enInRef           = AdcMskInRefEnable;        ///<内部参考电压使能-开
  16.     stcAdcCfg.enAdcAlign        = AdcAlignRight;            ///<转换结果对齐方式-右
  17.     Adc_Init(&stcAdcCfg);
  18.     ///< 配置单次采样通道
  19.     Adc_CfgSglChannel(AdcAiTsInput);
  20.     ///< 启动单次一直采样
  21.     Adc_SGL_Always_Start();
  22. }
然后就发现了一个驱动文件的错误:
写完后发现这里一直报错,已经包含了bgr.h
QQ截图20230808150944.png
查看bgr.h发现这里居然是CRC,而我工程里正好还包含了crc.h,修改为BGR后问题解决,打开HC32L19x_DDL_Rev1.2.0.zip压缩包内的原始文件也是CRC,1.1那个也是,希 望官方后续修复吧
QQ截图20230808142720.png
手册里有温度计算的方法
QQ截图20230808151044.png
在主循环里打印adc和温度

  1. int32_t main(void)
  2. {
  3.     float TemF;
  4.     uint16_t adc_trim;
  5.     uint32_t adc_result;
  6.     xth_init();
  7.     //时钟分频设置
  8.     Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
  9.     Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
  10.     flash_init();
  11.     led_init();
  12.     key_init();
  13.     timer0_init();
  14.     uart0_io_init();
  15.     uart0_init();
  16.     adc_init();
  17.     adc_trim = *((unsigned short int *)0x00100C36);
  18.     while(1)
  19.     {
  20.         if(TRUE == Adc_GetIrqStatus(AdcMskIrqSgl))
  21.         {
  22.             ///< 获取采样值
  23.             adc_result = Adc_GetSglResult();
  24.             TemF = 25 + 0.0795 * 2.5 * ( adc_result - adc_trim );
  25.             printf("ADC %04X% 校准值:%04X 温度:%0.1f℃",adc_result,adc_trim,TemF);
  26.             Adc_ClrIrqStatus(AdcMskIrqSgl);
  27.         }
  28.         yuyy_delay_ms(1000);
  29.     }
  30. }
运行效果
QQ截图20230808152021.png
接下来测试一下外部输入,用这个游戏手柄的摇杆作为输入,选用PA00和PA01作为XY方向的输入
QQ截图20230808152722.png
参考电压选择AVDD,采样通道0和1,初始化IO和ADC模块

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

  31.     Adc_CfgSqrChannel(AdcSQRCH0MUX, AdcExInputCH0);
  32.     Adc_CfgSqrChannel(AdcSQRCH1MUX, AdcExInputCH1);
  33.    
  34.     ///< 启动顺序扫描采样
  35.     Adc_SQR_Start();
  36. }
在主循环中打印ADC值
  1. int32_t main(void)
  2. {
  3.     uint32_t adcresult0;
  4.     uint32_t adcresult1;
  5.     xth_init();
  6.     //时钟分频设置
  7.     Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
  8.     Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
  9.    
  10.     flash_init();
  11.     led_init();
  12.     key_init();
  13.     uart0_io_init();
  14.     uart0_init();
  15.     adc_io_init();
  16.     adc_init();
  17.     while(1)
  18.     {
  19.         if(TRUE == Adc_GetIrqStatus(AdcMskIrqSqr))
  20.         {
  21.             Adc_ClrIrqStatus(AdcMskIrqSqr);
  22.             adcresult0   = Adc_GetSqrResult(AdcSQRCH0MUX);  //获取顺序扫描通道0
  23.             adcresult1   = Adc_GetSqrResult(AdcSQRCH1MUX);  //获取顺序扫描通道1
  24.             printf("adc0:%d     adc1:%d",adcresult0,adcresult1);
  25.             Adc_SQR_Start();
  26.         }
  27.         yuyy_delay_ms(200);
  28.     }
  29. }
摇动摇杆在串口工具上查看打印的ADC值的变化
QQ截图20230808185458.png
7.2DAC
DAC(Digital to Analog Converter)与ADC模数转换相反,是将数字量转换为模拟量输出,HC32L196内部集成了一个12位的单通道DAC,输出IO是PA04
QQ截图20230808191056.png
利用DAC输出一些波形,按键切换波形,初始化IO和DAC模块

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

  6. void dac_init()
  7. {
  8.     stc_dac_cfg_t  dac_initstruct;
  9.     Sysctrl_SetPeripheralGate(SysctrlPeripheralDac, TRUE);     ///< 使能DAC模块的时钟
  10.     dac_initstruct.boff_t = DacBoffDisable;
  11.     dac_initstruct.ten_t  = DacTenDisable;
  12.     dac_initstruct.sref_t = DacVoltageAvcc;
  13.     dac_initstruct.wave_t = DacWaveDisable;      
  14.     dac_initstruct.mamp_t = DacMenp4095;
  15.     dac_initstruct.tsel_t = DacSwTriger;          ///< 软件触发方式
  16.     dac_initstruct.align  = DacRightAlign;        ///< 右对齐
  17.     dac_initstruct.dhr12  = 0;
  18.     Dac_Init(&dac_initstruct);
  19.     Dac_Cmd(TRUE);
  20. }
生成波形
  1. void proc_dac_wave()
  2. {
  3.     uint8_t changed = 0;
  4.     switch(wavetype)
  5.     {
  6.         case 0:
  7.             if(wavestep > 0)
  8.                 wavestep -= 1;
  9.             else
  10.             {
  11.                 if(dacvalue == 0)
  12.                     dacvalue = 255;
  13.                 else
  14.                     dacvalue = 0;
  15.                 changed = 1;
  16.                 wavestep = 9;
  17.             }
  18.             break;
  19.         case 1:
  20.             dacvalue+=1;
  21.             changed = 1;
  22.             break;
  23.         case 2:
  24.             if(wavestep > 0)
  25.                 wavestep -= 1;
  26.             else
  27.             {
  28.                 wavestep = 10;
  29.                 dacvalue+=15;
  30.                 changed = 1;
  31.             }
  32.             break;
  33.         case 3:
  34.             if(wavestep < 255)
  35.             {
  36.                 dacvalue=wavestep;
  37.                 changed = 1;
  38.             }
  39.             else if(wavestep > 300 && wavestep < 556)
  40.             {
  41.                 dacvalue= 555 - wavestep;
  42.                 changed = 1;
  43.             }
  44.             if(wavestep < 600)
  45.                 wavestep++;
  46.             else
  47.                 wavestep = 0;
  48.             break;
  49.         case 4:
  50.             if(wavestep < 90)
  51.             {
  52.                 dacvalue = sinvalues[wavestep];
  53.                 changed = 1;
  54.             }
  55.             else
  56.             {
  57.                 dacvalue = sinvalues[180 - wavestep];
  58.                 changed = 1;
  59.             }
  60.             if(wavestep < 179)
  61.                 wavestep++;
  62.             else
  63.                 wavestep = 0;
  64.             break;
  65.         case 5:
  66.             if(wavestep < 90)
  67.             {
  68.                 dacvalue = 127 + (sinvalues[wavestep]/2);
  69.                 changed = 1;
  70.             }
  71.             else
  72.             {
  73.                 dacvalue = 128 - (sinvalues[180 - wavestep]/2);
  74.                 changed = 1;
  75.             }
  76.             if(wavestep < 179)
  77.                 wavestep++;
  78.             else
  79.                 wavestep = 0;
  80.             break;
  81.         case 6:
  82.             if(wavestep < 90)
  83.             {
  84.                 dacvalue = 127 + (sinvalues[wavestep]/2);
  85.                 changed = 1;
  86.             }
  87.             else if(wavestep < 180)
  88.             {
  89.                 dacvalue = 127 + (sinvalues[180 - wavestep]/2);
  90.                 changed = 1;
  91.             }
  92.             else if(wavestep < 270)
  93.             {
  94.                 dacvalue = 128 - (sinvalues[wavestep - 180]/2);
  95.                 changed = 1;
  96.             }
  97.             else
  98.             {
  99.                 dacvalue = 128 - (sinvalues[360 - wavestep]/2);
  100.                 changed = 1;
  101.             }
  102.             if(wavestep < 359)
  103.                 wavestep++;
  104.             else
  105.                 wavestep = 0;
  106.             break;
  107.         default:
  108.             break;
  109.     }
  110.     if(changed > 0)
  111.         Dac_SetChannelData(DacRightAlign,DacBit8,dacvalue);
  112. }
波形效果展示,不是示波器波形有点失真
QQ截图20230808183044.png QQ截图20230808183105.png QQ截图20230808183527.png QQ截图20230808183152.png QQ截图20230808183204.png QQ截图20230808183217.png QQ截图20230808183232.png

tpgf 发表于 2024-2-5 14:55 | 显示全部楼层
一般这种低级错误 他们早就应该有勘误文件呀
keaibukelian 发表于 2024-2-5 15:27 | 显示全部楼层
其实对于128来说 这个波形已经非常圆滑了
chenjun89 发表于 2024-2-5 21:35 来自手机 | 显示全部楼层
这个波形还是可以的了
renzheshengui 发表于 2024-2-6 08:31 | 显示全部楼层
楼主dac外部硬件是连接的什么呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

826

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部