外部的模拟信号需要转变成数字信号才能由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);,当产生接收中断时开始转换。