开始进入代码: /******************************************************************************* * Definitions ******************************************************************************/ #define DEMO_ADC16_CHANNEL 1U #define DEMO_ADC16_CHANNEL_GROUP 0U #define DEMO_ADC16_BASEADDR ADC0 #define DEMO_DMAMUX_BASEADDR DMAMUX0 #define DEMO_DMA_CHANNEL 1U #define DEMO_DMA_ADC0_SOURCE 40U #define DEMO_DMA_ADC1_SOURCE 41U #define DEMO_DMA_BASEADDR DMA0 #define ADC16_RESULT_REG_ADDR 0x4003b010U #define ADC16_RESULT_REG_ADDR1 0x40027010U//查询寄存器手册得到 #define DEMO_DMA_IRQ_ID DMA0_IRQn
#define DEMO_ADC16_SAMPLE_COUNT 8U /* The ADC16 sample count. */ /*********************************************************************************************************************** * ADC0 initialization code **********************************************************************************************************************/ adc16_channel_config_t ADC0_channelsConfig[1] = { { .channelNumber = 1U, //传输通道 .enableDifferentialConversion = true, //差分模式 .enableInterruptOnConversionCompleted = false, //使能传输完成中断 } }; const adc16_config_t ADC0_config = { .referenceVoltageSource = kADC16_ReferenceVoltageSourceVref, .clockSource = 0, .enableAsynchronousClock = false, .clockDivider = kADC16_ClockDivider1, .resolution = kADC16_ResolutionSE16Bit, .longSampleMode = kADC16_LongSampleDisabled, .enableHighSpeed = true, .enableLowPower = false, .enableContinuousConversion = false//连续的转换 }; const adc16_channel_mux_mode_t ADC0_muxMode = kADC16_ChannelMuxA; /* 硬件平均 8 */ const adc16_hardware_average_mode_t ADC0_hardwareAverageMode = kADC16_HardwareAverageDisabled; void ADC0_init(void) { /* Initialize ADC16 converter */ ADC16_Init(ADC0_PERIPHERAL, &ADC0_config); /* Make sure, that software trigger is used */ ADC16_EnableHardwareTrigger(ADC0_PERIPHERAL, false); /* Configure hardware average mode */ ADC16_SetHardwareAverage(ADC0_PERIPHERAL, ADC0_hardwareAverageMode); /* Configure channel multiplexing mode */ ADC16_SetChannelMuxMode(ADC0_PERIPHERAL, ADC0_muxMode); /* Initialize channel */ ADC16_SetChannelConfig(ADC0_PERIPHERAL, 0U, &ADC0_channelsConfig[0]); /* Perform auto calibration */ ADC16_DoAutoCalibration(ADC0_PERIPHERAL); /* Enable DMA. */ ADC16_EnableDMA(ADC0_PERIPHERAL, false); } /*********************************************************************************************************************** * ADC1 initialization code **********************************************************************************************************************/ adc16_channel_config_t ADC1_channelsConfig[1] = { { .channelNumber = 2U, .enableDifferentialConversion = true, //差分模式 .enableInterruptOnConversionCompleted = false, } }; const adc16_config_t ADC1_config = { .referenceVoltageSource = kADC16_ReferenceVoltageSourceVref, .clockSource = 0, .enableAsynchronousClock = false, .clockDivider = kADC16_ClockDivider1, .resolution = kADC16_ResolutionSE16Bit, .longSampleMode = kADC16_LongSampleDisabled, .enableHighSpeed = true, .enableLowPower = false, .enableContinuousConversion = false//连续的转换 }; const adc16_channel_mux_mode_t ADC1_muxMode = kADC16_ChannelMuxA; const adc16_hardware_average_mode_t ADC1_hardwareAverageMode = kADC16_HardwareAverageDisabled; void ADC1_init(void) { // EnableIRQ(ADC0_IRQn); /* 初始化ADC16转换器 */ ADC16_Init(ADC1_PERIPHERAL, &ADC1_config); /* 不使用软件触发器 */ ADC16_EnableHardwareTrigger(ADC1_PERIPHERAL, false); /* 配置硬件平均模式 */ ADC16_SetHardwareAverage(ADC1_PERIPHERAL, ADC1_hardwareAverageMode); /* 配置信道多路复用模式 */ ADC16_SetChannelMuxMode(ADC1_PERIPHERAL, ADC1_muxMode); /* 初始化通道 */ ADC16_SetChannelConfig(ADC1_PERIPHERAL, 1U, &ADC1_channelsConfig[0]); /* 自动校准 */ ADC16_DoAutoCalibration(ADC1_PERIPHERAL); /* Enable DMA. */ ADC16_EnableDMA(ADC1_PERIPHERAL, false);
} 这里以ADC0为例,传输通道设置为1,配置为差分模式,不使能传输完成中断。ADC0_config结构体中的配置主要是配置时钟和采样速度,我的配置是我能达到的最高速度。在ADC0_init函数中,配置为软件触发,如果使用PDB,需要改为硬件触发,关闭了硬件平均。 当我们需要获取ADC的数据时,需要以下代码。 adc16_channel_config_t adc16ChannelConfigStruct; adc16ChannelConfigStruct.channelNumber = 1; //ADC通道 adc16ChannelConfigStruct.channelNumber = 2; adc16ChannelConfigStruct.enableDifferentialConversion = true;//使能差分 adc16ChannelConfigStruct.enableInterruptOnConversionCompleted = false;//失能中断 ADC16_SetChannelConfig(ADC1, 0U, &adc16ChannelConfigStruct); ADC16_SetChannelConfig(ADC0, 0U, &adc16ChannelConfigStruct); while (0U == (kADC16_ChannelConversionDoneFlag & ADC16_GetChannelStatusFlags(ADC1, 0U))); ADC_Value0 = ADC16_GetChannelConversionValue(ADC0, 0U); ADC_Value1 = ADC16_GetChannelConversionValue(ADC1, 0U); 可以将上述代码添加进主循环,在需要AD值时便可以直接读取ADC_Value0和ADC_Value1的值便可,可以包装成一个函数,需要时调用即可,执行一次该代码大约需要3us。如果AD的通道很多,可以使用for循环,改善代码。但是此方法占用MCU的内存,下一篇更新灵活多通道的DMA采集。 要点: 这里配置为ADC16位模式,但是并不是真正意义上的16位,在数据寄存器中有介绍,数据寄存器是16位,只有低15位是有效数据位,最高位为16位,所以ADC的范围是0~32767,加上最高位的符号位能达到-32767~+32767. 我在这里没看手册,采集到的数据一直无法理解。 输入通道输入的是正弦波,结果串口打印出来的确是这个玩意,最后处理一下符号位解决。 |