已经可以显示温度了——不过这个功能与小车功能无关,纯属跑题。呵呵。<br /><br />感觉DMA的功能很实用。可以让CPU腾出时间去做其它事情。<br /><br />俺现在是4个通道(2个外部,2个内部)轮流扫描检测,并且为每个通道开辟100个存放位置。到时候取个平均就好了。<br /><br />感觉真是奢侈。欧耶!<br /><br />下面给出几个程序片段 :<br /><br /><br /><br /><br />//--------------------------------------------------------<br />//主函数<br />//--------------------------------------------------------<br />int main(void)<br />{<br />#ifdef DEBUG<br /> debug();<br />#endif<br /><br /><br /> //================<br /> //主程序初始化段<br /> //================<br /><br /> RCC_Configuration(); //系统时钟配置<br /> NVIC_Configuration(); //中断配置<br /> GPIO_Configuration(); //IO口(GPIO)配置<br /> DMA_Configuration(); //DMA配置<br /> ADC_Configuration(); //ADC配置<br /> SysTick_Configuration(); //SysTick初始化设置<br /><br /> Init_LCD() ; //LCD初始化函数<br /> //DisplayString_LCD(0,1,"CXJR21ic");<br /><br /><br /> //================<br /> //主程序循环段<br /> //================<br /> while(1)<br /> {<br /> SysTick_Delay(300); //延时<br /><br /> X_AVR = Average(AD_Value,0); //计算 X轴加速度采样滤波值<br /> //Y_AVR = Average(AD_Value,1); //计算 Y轴加速度采样滤波值<br /> TEMP_AVR = Average(AD_Value,2); //计算 内部温度传感器采样滤波值<br /> VREF_AVR = Average(AD_Value,3); //计算 内部参考电压采样滤波值<br /><br /> GetTemp(); //根据ADC结果计算温度<br /> <br /> Disp_X_AVR(); //显示X轴加速度采样滤波值<br /> Disp_Temp_Value(); //显示温度值<br /> //Disp_XY_ADR(); //显示XY轴加速度采样值<br /><br /> //Disp_XY_AVR(); //显示XY轴加速度采样滤波值<br /><br /> //Disp_Inside_ADR(); //显示内部通道采样值<br /><br /> }<br />}<br /><br /><br /><br />//--------------------------------------------------------<br />//双字节中位值平均滤波<br />//功能: 将队列中数据减去最大值和最小值,然后求平均值(小数四舍五入)<br />//入口: QUEUE =队列<br />// nChannel =序列号<br />//出口: =滤波结果(平均值)<br />//--------------------------------------------------------<br />u16 Average(vu16 QUEUE[],u8 nChannel) <br />{<br /> u16 max = 0;<br /> u16 min = 0xFFFF;<br /> u32 sum = 0;<br /> u16 i,j;<br /><br /> for(i=0;i<ADC_Average_n;i++) //<br /> {<br /> j=nChannel+i*ADC_Channel_n; <br /> if ( QUEUE[j] > max ) max = QUEUE[j]; //比较并更新最大值<br /> if ( QUEUE[j] < min ) min = QUEUE[j]; //比较并更新最小值<br /><br /> sum = sum + QUEUE[j]; //追加到和值<br /><br /> }<br /> i = ADC_Average_n - 2; <br /> sum = sum - max - min + i/2;<br /> sum = sum / i; //平均值=(和值-最大值-最小值+n/2)/(队列长度-2)<br /> //说明:+(n-2)/2的目的是为了四舍五入<br /> return ((u16) sum) ;<br /> <br />}<br /><br />//--------------------------------------------------------<br />//DMA配置<br />//功能: 从ADC模块自动读转换结果至内存<br />//--------------------------------------------------------<br />void DMA_Configuration(void)<br />{<br /> DMA_InitTypeDef DMA_InitStructure; //定义DMA初始化结构体<br /> DMA_DeInit(DMA_Channel1); //复位DMA通道1<br /> DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //定义DMA通道外设基地址=ADC1_DR_Address<br /> DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value; //定义DMA通道存储器地址<br /> DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //指定外设为源地址<br /> DMA_InitStructure.DMA_BufferSize = ADC_Channel_n*ADC_Average_n; //定义DMA缓冲区大小(对应于ADC转换序列数量),<br /> DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //当前外设寄存器地址不变<br /> DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //当前存储器地址自动递增加1<br /> DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //定义外设数据宽度16位<br /> DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //定义存储器数据宽度16位<br /> DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA通道操作模式=循环模式开启(Buffer写满后,自动回到初始地址开始传输)<br /> DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道优先级高<br /> DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止DMA通道存储器到存储器传输<br /> DMA_Init(DMA_Channel1, &DMA_InitStructure); //初始化DMA通道1<br /> DMA_Cmd(DMA_Channel1, ENABLE); //使能DMA通道1<br />}<br /><br /><br />//--------------------------------------------------------<br />//ADC配置<br />//说明:包括ADC模块配置和自校准,并启动第一次AD转换<br />//--------------------------------------------------------<br />void ADC_Configuration(void)<br />{<br /> //====ADC模块配置<br /> ADC_InitTypeDef ADC_InitStructure; //定义ADC初始化结构体<br /> ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC1和ADC2工作在独立模式<br /> ADC_InitStructure.ADC_ScanConvMode = ENABLE; //使能扫描<br /> ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //ADC转换工作在连续模式<br /> ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //有软件控制转换<br /> ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //转换数据右对齐<br /> ADC_InitStructure.ADC_NbrOfChannel = ADC_Channel_n; //设置转换序列长度<br /> ADC_Init(ADC1, &ADC_InitStructure); //初始化ADC1<br /> ADC_TempSensorVrefintCmd(ENABLE); //ADC内置温度传感器使能(要使用片内温度传感器,切忌要开启它)<br /> //ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_13Cycles5); //常规转换序列1:通道8<br /> //ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 2, ADC_SampleTime_13Cycles5); //常规转换序列2:通道9<br /> ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5); //常规转换序列1:通道8<br /> ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 2, ADC_SampleTime_239Cycles5); //常规转换序列2:通道9<br /> ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 3, ADC_SampleTime_239Cycles5); //常规转换序列3:通道16(内部温度传感器),采样时间>2.2us,(239cycles)<br /> ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 4, ADC_SampleTime_239Cycles5); //常规转换序列4:通道17(内部参考电压),采样时间>2.2us,(239cycles)<br /> ADC_Cmd(ADC1, ENABLE); //使能ADC1 <br /> ADC_DMACmd(ADC1, ENABLE); //开启ADC1的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数)<br /> <br /> //====ADC自动校准<br /> ADC_ResetCalibration(ADC1); //重置ADC1校准寄存器<br /> while(ADC_GetResetCalibrationStatus(ADC1)); //等待ADC1校准重置完成<br /> ADC_StartCalibration(ADC1); //开始ADC1校准<br /> while(ADC_GetCalibrationStatus(ADC1)); //等待ADC1校准完成<br /><br /> //====启动第一次AD转换<br /> ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC1,开始转换<br /> //因为已经配置好了DMA,接下来AD自动连续转换,结果自动保存在AD_Value处 <br /> <br />}<br /><br /><br />//--------------------------------------------------------<br />//根据ADC结果计算温度<br />//入口: TEMP_AVR=温度传感器采样值<br />// VREF_AVR=参考电压采样值<br />//出口: Temp_Value=温度值<br />//--------------------------------------------------------<br />//温度值计算公式如下:<br />// V25 - VSENSE<br />// T(℃) = ------------ + 25℃<br />// Avg_Slope<br />//其中:<br />// V25: 温度传感器在25℃时 的输出电压,典型值1.43 V。<br />// VSENSE: 温度传感器的当前输出电压. VSENSE = 温度传感器采样值(TEMP_AVR) * 参考电压(1.2V) / 参考电压采样值(VREF_AVR)<br />// Avg_Slope: 温度传感器输出电压和温度的关联参数,典型值4.3 mV/℃。<br />//--------------------------------------------------------<br />void GetTemp(void)<br />{<br /> s32 i;<br /> i = (143 - TEMP_AVR * 120 / VREF_AVR)*10000/43 + 2500; <br /><br /> if (i<0) Temp_Value=0;<br /> else if (i>9999) Temp_Value=99;<br /> else Temp_Value = i /100;<br />}
|