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);
}
波形效果展示,不是示波器波形有点失真
---------------------
作者:yuyy1989
链接:https://bbs.21ic.com/icview-3319844-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。