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)
{
   /* 允许ADC */
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
 /* ADC1 */
 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);
 
 /* 配置通道16的采样速度,这里因为是测温,不需要很快,配置为最慢*/
 ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_239Cycles5);
 
 /* 使能内部温度传感器和内部的参考电压 */
 ADC_TempSensorVrefintCmd(ENABLE);
 
 /* 允许ADC1的DMA模式 */
 ADC_DMACmd(ADC1, ENABLE);
 
 /* 允许ADC1*/
 ADC_Cmd(ADC1, ENABLE);
 
 /*重置校准寄存器 */  
 ADC_ResetCalibration(ADC1);
 while(ADC_GetResetCalibrationStatus(ADC1));
 
 /*开始校准状态*/
 ADC_StartCalibration(ADC1);
 while(ADC_GetCalibrationStatus(ADC1));
   
 /* 人工打开ADC转换.*/
 ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}


//DMA的配置
void DMA_Configuration(void)
{
 
 /* 允许 DMA1 */
 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
 /* DMA通道1*/
 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传输完成中断
 
 /* Enable DMA1 channel1 */
 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

/* Includes ------------------------------------------------------------------*/
#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

/************************************************************
**实验名称:ADC TEMP
**功能:使用片内的温度传感器测量温度,并通过串口输出温度值
*************************************************************/

#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; 
 /* Loop until the end of transmission */ 
 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);//可以不需要下面的那种操作,很简单的就可将数据从串口输出!!
   /*
   a = adc/1000;
      b = (adc - a*1000)/100;
      c = (adc - a*1000 - b*100)/10;
      d = adc - a*1000 - b*100 - c*10;

  
      USART1_Puts("Temprature is:");
      USART1_Putc(a+'0');
      USART1_Putc(b+'0');
      USART1_Putc(c+'0');
      USART1_Putc(d+'0');
  
      USART1_Puts("C \r\n");
   */
   delay(2234567);
  }
 }
}


/**************************************************************
** 函数名:DigitFilter
** 功能:软件滤波
** 注意事项:取NO的2/5作为头尾忽略值,注意N要大于5,否则不会去头尾
***************************************************************/
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--);
}

文件:6_ADC_TEMP.rar
大小:3364KB
下载:下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值