这次的实验和上一个ADC实验不同的是,采用扫描模式采样通道13和通道16。因为规则通道转换的值储存在一个仅有的数据寄存器中,所以当转换多个规则通道时需要使用DMA,这可以避免丢失已经存储在ADC_DR寄存器中的数据。 只有在规则通道的转换结束时才产生DMA请求,并将转换的数据从ADC_DR寄存器传输到用户指定的目的地址。因此这样也能体验一下GD32的DMA功能。
void AdcInit()
{
GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;
DMA_InitTypeDef DMA_InitStruct;
RCC_AHBPeriphClockCmd (RCC_AHBPeriph_DMA1 ,ENABLE );
RCC_APB2PeriphClockCmd (RCC_APB2Periph_ADC1, ENABLE);
RCC_ADCCLKConfig (RCC_PCLK2_Div6);
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN ;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init (GPIOC,&GPIO_InitStruct);
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE ;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_InitStruct.ADC_NbrOfChannel = 2;
ADC_InitStruct.ADC_ScanConvMode = ENABLE ;
ADC_Init (ADC1,&ADC_InitStruct);
ADC_RegularChannelConfig(ADC1,ADC_Channel_13,1,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1,ADC_Channel_16,2,ADC_SampleTime_239Cycles5);
ADC_DMACmd (ADC1,ENABLE);
ADC_Cmd (ADC1,ENABLE);
ADC_TempSensorVrefintCmd (ENABLE );
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1) == SET)
{
;
}
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1) == SET)
{
;
}
DMA_InitStruct.DMA_BufferSize = 2;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC ;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_InitStruct.DMA_MemoryBaseAddr = (u32)gAdcVal;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord ;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord ;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_Init (DMA1_Channel1 ,&DMA_InitStruct);
DMA_Cmd (DMA1_Channel1,ENABLE);
ADC_SoftwareStartConvCmd (ADC1,ENABLE);
}
这次代码没有在中断服务函数里去获取AD采样的值,在这里是通过建立一个数组,通过DMA来直接将ADC1的数据寄存器的值传到数组中。那么再主函数里就可以直接使用:
float gVoltage = 0.01;
float gTemperate = 0.01;
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
LedPinInit();
SysTickInit();
TimerInit(99,7199);
AdcInit();
GUI_Init();
GUI_SetBkColor(GUI_RED);
GUI_SetColor(GUI_WHITE);
GUI_Clear();
GUI_DispStringAt("liklon--->GD32107C-EVAL",1,40);
GUI_DispStringAt("www.eepw.com.cn",40,60);
GUI_DispStringAt("ADC:",80,80);
GUI_DispStringAt("VOLTAGE:",48,120);
GUI_DispStringAt("TEMPERATE:",48,160);
while(1)
{
if(gLedRunFlag > 10)
{
gVoltage = gAdcVal[0] * 3.3 / 4096.0;
gTemperate = gAdcVal[1] * 3.3 / 4096.0;
gTemperate = (1.43 - gTemperate) / 0.0043 + 25;
GUI_DispDecAt(gAdcVal[0],100,100,4);
GUI_GotoXY(100,140);
GUI_DispFloat(gVoltage,3);
GUI_GotoXY(100,180);
GUI_DispFloat(gTemperate,5);
gLedRunFlag = 0;
}
}
}
计算温度误差比较大,下面是效果图:
这次体验的是DMA功能在ADC中的应用,这样以后如果需要多个通道采集时,便方便许多了。GD32的内部资源丰富而且都非常实用。这个温度误差有点大,不知道是不是自己换算的过程中有问题,一眼看出道道的童鞋希望可以指点指点。
我要赚赏金
