外部的模拟信号需要转变成数字信号才能由MCU进一步处理。内部集成了一个12位高精度、高转换速率的逐次逼近型模数转换器(SAR ADC)模块。
1M SPS 转换速度;
12 路转换通道:9 个引脚通道、内置温度传感器、内置 1.2v 基准电压、1/3 电源电压;
4 种参考源:电源电压、ExRef 引脚、内置 1.5v 参考电压、内置 2.5v 参考电压;
ADC 的电压输入范围:0~Vref;
3 种转换模式:单次转换、连续转换、累加转换;
软件可配置 ADC 的转换速率;
内置信号放大器,可转换高阻信号;
支持片内外设自动触发ADC转换,有效降低芯片功耗并提高转换的实时性。
ADC 框图
ADC 转换速度与 ADC 参考电压及 VCC 电压相关,最高转换速度如下表所示:
开发板的配置为最后一个,也就是理论上转换速度可以达到1M。
例程就是adc的几种转换模式,单次,连续,累加,外部触发,然后在有查询和中断两种,一个8个例程,这里就比较典型的连续和外部触发讲解一下,其他的步骤在文档里有详细的说明,可以对照代码查看。
adc_scan_polling_sw连续触发,查询模式
Gpio_SetAnalog(3, 2, TRUE); // AIN2
Gpio_SetAnalog(3, 3, TRUE); // AIN3
Gpio_SetAnalog(3, 4, TRUE); // AIN4
Adc_Enable();
M0P_BGR->CR_f.BGR_EN = 0x1u; // BGR必须使能
M0P_BGR->CR_f.TS_EN = 0x1u;
delay100us(1);
stcAdcCfg.enAdcOpMode = AdcScanMode; //扫描采样模式
stcAdcCfg.enAdcClkSel = AdcClkSysTDiv8;
stcAdcCfg.enAdcSampTimeSel = AdcSampTime4Clk;
stcAdcCfg.enAdcRefVolSel = RefVolSelAVDD;
stcAdcCfg.bAdcInBufEn = FALSE;
stcAdcCfg.enAdcTrig0Sel = AdcTrigDisable;
stcAdcCfg.enAdcTrig1Sel = AdcTrigDisable;
Adc_Init(&stcAdcCfg);
stcAdcScanCfg.u8AdcScanModeCh = ADC_SCAN_CH2_EN | ADC_SCAN_CH3_EN | ADC_SCAN_CH4_EN;
stcAdcScanCfg.u8AdcSampCnt = 0x6;
Adc_ConfigScanMode(&stcAdcCfg, &stcAdcScanCfg);
while (1) {
Adc_Start();
while (FALSE != Adc_PollBusyState())
;
for (u8Channel = 0; u8Channel < 8; u8Channel++) {
Adc_GetScanResult(u8Channel, &u16ScanResult[u8Channel]);
if ((1 << u8Channel) & stcAdcScanCfg.u8AdcScanModeCh) {
printf("CH: %d is enabled, AdcVal: 0x%X\n", u8Channel, u16ScanResult[u8Channel]);
} else {
printf("CH: %d is disabled, AdcVal: 0x%X\n", u8Channel, u16ScanResult[u8Channel]);
}
}
delay1ms(1000);
Adc_Init(&stcAdcCfg);
Adc_ConfigScanMode(&stcAdcCfg, &stcAdcScanCfg);
}
配置P32,P33,P34为adc,并配置u8AdcScanModeCh设置扫描通道。然后Adc_Start()开始转换。
查询转换结束Adc_PollBusyState(),读取转换结果Adc_GetScanResult(u8Channel, &u16ScanResult[u8Channel]);
adc_uart_polling_sw串口触发
stcAdcCfg.enAdcOpMode = AdcNormalMode; //单次采样模式
stcAdcCfg.enAdcClkSel = AdcClkSysTDiv1;
stcAdcCfg.enAdcSampTimeSel = AdcSampTime4Clk;
stcAdcCfg.enAdcRefVolSel = RefVolSelExtern1;
stcAdcCfg.bAdcInBufEn = FALSE;
stcAdcCfg.u32AdcRegHighThd = 0x0fffu;
stcAdcCfg.u32AdcRegLowThd = 0u;
stcAdcCfg.enAdcTrig0Sel = AdcTrigUart1;
Adc_Init(&stcAdcCfg);
M0P_ADC->CR1_f.REGCMP = 1;
stcAdcNormCfg.enAdcNormModeCh = AdcExInputCH4;
stcAdcNormCfg.bAdcResultAccEn = FALSE;
Adc_ConfigNormMode(&stcAdcCfg, &stcAdcNormCfg);
stcUartIrqCb.pfnRxIrqCb = RxIntCallback;
stcUartIrqCb.pfnTxIrqCb = TxIntCallback;
stcUartIrqCb.pfnRxErrIrqCb = ErrIntCallback;
stcConfig.pstcIrqCb = &stcUartIrqCb;
stcConfig.bTouchNvic = TRUE;
stcConfig.enRunMode = UartMode1; //测试项,更改此处来转换4种模式测试
stcMulti.enMulti_mode = UartNormal; //测试项,更改此处来转换多主机模式,mode2/3才有多主机模式
enTb8 = Data;
Uart_SetMMDOrCk(UARTCH1, enTb8);
stcConfig.pstcMultiMode = &stcMulti;
stcBaud.bDbaud = 0u; //双倍波特率功能
stcBaud.u32Baud = 9600u; //更新波特率位置
stcBaud.u8Mode = UartMode1; //计算波特率需要模式参数
pclk = Clk_GetPClkFreq();
timer = Uart_SetBaudRate(UARTCH1, pclk, &stcBaud);
stcBtConfig.enMD = BtMode2;
stcBtConfig.enCT = BtTimer;
Bt_Init(TIM1, &stcBtConfig); //调用basetimer1设置函数产生波特率
Bt_ARRSet(TIM1, timer);
Bt_Cnt16Set(TIM1, timer);
Bt_Run(TIM1);
Uart_Init(UARTCH1, &stcConfig);
Uart_EnableIrq(UARTCH1, UartRxIrq);
Uart_ClrStatus(UARTCH1, UartRxFull);
Uart_EnableFunc(UARTCH1, UartRx);
while (1) {
while (FALSE == M0P_ADC->IFR_f.REG_INTF)
;
M0P_ADC->ICLR_f.REG_INTC = 0u;
Adc_GetResult(&u16AdcResult);
Adc_ClrAccResult();
Gpio_SetIO(2, 3, 1);
delay1ms(200);
Gpio_SetIO(2, 3, 0);
u32RxData[0] = '0';
u32RxData[1] = 'x';
if ((u16AdcResult >> 12) > 9) {
u32RxData[2] = (u16AdcResult >> 12) - 10 + 'A';
} else {
u32RxData[2] = (u16AdcResult >> 12) + '0';
}
if (((u16AdcResult >> 8) & 0xF) > 9) {
u32RxData[3] = ((u16AdcResult >> 8) & 0xF) - 10 + 'A';
} else {
u32RxData[3] = ((u16AdcResult >> 8) & 0xF) + '0';
}
if (((u16AdcResult >> 4) & 0xF) > 9) {
u32RxData[4] = ((u16AdcResult >> 4) & 0xF) - 10 + 'A';
} else {
u32RxData[4] = ((u16AdcResult >> 4) & 0xF) + '0';
}
if (((u16AdcResult)&0xF) > 9) {
u32RxData[5] = ((u16AdcResult)&0xF) - 10 + 'A';
} else {
u32RxData[5] = ((u16AdcResult)&0xF) + '0';
}
u32RxData[6] = '\n';
for (u8TxCnt = 0; u8TxCnt < 7; u8TxCnt++) {
Uart_SendData(UARTCH1, u32RxData[u8TxCnt]);
}
}
外部触发意思就是当你设置的外部触发中断时,自动开始进行转换,比如例程中设置的 stcAdcCfg.enAdcTrig0Sel = AdcTrigUart1;串口1触发,就是串口1产生中断就会开始adc转换,所以需要同时配置uart1中断。Uart_EnableIrq(UARTCH1, UartRxIrq);,当产生接收中断时开始转换。