天天看点

STM32+DMA+UART+ADC+内部温度传感器

作者:number007cool

转自:http://blog.chinaunix.net/uid-21658993-id-1820027.html

由于文件很多,只列举几个关键的文件。 ADC.c

#include "STM32Lib\\stm32f10x.h"

u16 ADCCov[16];

volatile bool ADC_Ok=FALSE;

static DMA_InitTypeDef DMA_InitStructure;

static ADC_InitTypeDef ADC_InitStructure;

//ADC,内部温度传感器配置

void ADCTEMP_Configuration(void)

{

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);

 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;      //独立模式

 ADC_InitStructure.ADC_ScanConvMode = DISABLE;       //单通道模式

 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;      //连续扫描

 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  //软件启动转换

 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;     //数据右对齐

 ADC_InitStructure.ADC_NbrOfChannel = 1;         //1个通道

 ADC_Init(ADC1, &ADC_InitStructure);

 ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_239Cycles5);

 ADC_TempSensorVrefintCmd(ENABLE);

 ADC_DMACmd(ADC1, ENABLE);

 ADC_Cmd(ADC1, ENABLE);

 ADC_ResetCalibration(ADC1);

 while(ADC_GetResetCalibrationStatus(ADC1));

 ADC_StartCalibration(ADC1);

 while(ADC_GetCalibrationStatus(ADC1));

 ADC_SoftwareStartConvCmd(ADC1, ENABLE);

}

//DMA的配置

void DMA_Configuration(void)

{

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

 DMA_DeInit(DMA1_Channel1);

 //指定DMA外设基地址

 DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)( &(ADC1->DR));  //ADC1数据寄存器

 //设定DMA内存基地址

 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADCCov;     //获取ADC的数组

 //外设作为数据传输的来源

 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;     //片内外设作源头

 //指定DMA通道的DMA缓存大小

 DMA_InitStructure.DMA_BufferSize = 16;        //每次DMA16个数据

 //外设地址不递增(不变)

 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不增加

 //内存地址不递增(不变)

 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    //内存地址增加

 //设定外设数据宽度为16位

 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字

 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;   //半字

 //设定DMA的工作模式普通模式,还有一种是循环模式

 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;        //普通模式

 //设定DMA通道的软件优先级

 DMA_InitStructure.DMA_Priority = DMA_Priority_High;       //高优先级

 //使能DMA内存到内存的传输,此处没有内存到内存的传输

 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;        //非内存到内存

 DMA_Init(DMA1_Channel1, &DMA_InitStructure);

 DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);        //DMA通道1传输完成中断

 DMA_Cmd(DMA1_Channel1, ENABLE);

}

//重新允许DMA,

void DMAReConfig(void)

{

 DMA_DeInit(DMA1_Channel1);

 DMA_Init(DMA1_Channel1, &DMA_InitStructure);

 DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);

 DMA_Cmd(DMA1_Channel1, ENABLE);

}

stm32f10x_it.c

#include "STM32Lib\\stm32f10x.h"

#include "hal.h"

extern volatile bool ADC_Ok;

void DMA1_Channel1_IRQHandler(void)

{

 if(DMA_GetITStatus(DMA1_IT_TC1))//通道1传输完成中断

  {

  DMA_ClearITPendingBit(DMA1_IT_GL1); //清除全部中断标志

  ADC_Ok=TRUE;

 }

}

main.c

#include "STM32Lib\\stm32f10x.h"

#include "hal.h"

#include "stdio.h"

extern volatile bool ADC_Ok;

extern u16 ADCCov[16];

extern void DMAReConfig(void);

void delay(u32 z);

u16 DigitFilter(u16* buf,u8 no);

int fputc(int ch, FILE *f) 

 //USART_SendData(USART1, (u8) ch); 

 USART1->DR = (u8) ch; 

 while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) 

 { 

 } 

 return ch; 

}

int main(void)

{

 u16 adc;

 u8 a,b,c,d;

 ChipHalInit();   //片内硬件初始化

 ChipOutHalInit();  //片外硬件初始化

 for(;;)

 {

  if(ADC_Ok==TRUE)

  {

   ADC_Ok=FALSE;

   adc=DigitFilter(ADCCov,16); //滤波,只要数据的中间一段

   DMAReConfig();//重新启动DMA

   adc=(1.42 - adc*3.3/4096)*1000/4.35 + 25;//转换为温度值,实际应用中,可考虑用毫伏为单位,避免浮点运算

   printf("T: %d C\r\n",adc);//可以不需要下面的那种操作,很简单的就可将数据从串口输出!!

   delay(2234567);

  }

 }

}

u16 DigitFilter(u16* buf,u8 no)

{

 u8 i,j;

 u16 tmp;

 u8 cut_no=0;

 //排序,将buf[0]到buf[no-1]从大到小排列

 for(i=0;i<no;i++)

 {

  for(j=0;j<no-i-1;j++)

  { 

   if(buf[j]>buf[j+1])

   { 

   tmp=buf[j];

   buf[j]=buf[j+1];

   buf[j+1]=tmp;

   }

  }

 }

 if(no>5)//no为整形,此处是将no的前2/5丢掉

 {

  cut_no=no/5;

 }

 //平均

 tmp=0;

 for(i=cut_no;i<no-cut_no;i++) //只取中间n-2*cut_no个求平均

  tmp+=buf[i];

 return(tmp/(no-2*cut_no));

}

void delay(u32 z)

{

while(z--);

}

STM32+DMA+UART+ADC+内部温度传感器
文件: 6_ADC_TEMP.rar
大小: 3364KB
下载: 下载

继续阅读