打印
[信息]

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

[复制链接]
1821|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mintspring|  楼主 | 2013-11-30 20:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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


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

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; //
内存地址增加
第2/6页

//设定外设数据宽度为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;
}
第3/6页

}
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
第4/6页

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])
第5/6页

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;

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

}

void delay(u32 z)

{

while(z--);

}

沙发
dinghui28| | 2013-11-30 22:04 | 只看该作者
不错  顶一个

使用特权

评论回复
板凳
地瓜patch| | 2013-11-30 22:12 | 只看该作者
只有DMA没用过

使用特权

评论回复
地板
ZRJ8951| | 2013-12-2 20:25 | 只看该作者
收藏!!!

使用特权

评论回复
5
hkcj| | 2013-12-3 07:48 | 只看该作者
好东西    收藏一个     楼主    谢谢了   这一块    需要好好熟悉熟悉  话说   这一块  做项目  一直没有用到   所以也就没有怎么熟悉   需要花时间   看看

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

296

主题

4893

帖子

24

粉丝