完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
stm32 ADC测量内部温度传感器温度值,使用DMA方式传输,并通过串口观察数据。
实验器材: 探索者STM32F407开发板 硬件资源: 内部温度传感器,连接在ADC1_CH1上面. 实验现象: 用ADC测量内部温度传感器温度值,使用DMA方式传输,并通过串口观察数据。 具体配置过程 一.ADC配置 STM32F4 有一个内部的温度传感器,可以用来测量 CPU 及周围的温度(TA)。该温度传感器在内部和 ADC1_IN16输入通道相连接,此通道把传感器输出的电压转换成数字值。 STM32F4 的内部温度传感器支持的温度范围为:-40~125 度。精度为±1.5℃左右。 ADC具体配置步骤为: 1,开启时钟 2,初始化IO口PA5 3,ADC复位 4,使能内部温度传感器 5,配置ADC通用控制寄存器(ADC_CommonInit) 6,每一个ADC控制器的初始化(ADC_init) 7,ADC通道配置 8,开启ADC和dma adc.c文件见下 #include "adc.h" #include "delay.h" //初始化ADC //开启温度传感器通道 void Adc_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_InitTypeDef ADC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//使能ADC1时钟 //先初始化IO口 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;// 上拉 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化 RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE); //ADC1复位 RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE); //复位结束 ADC_TempSensorVrefintCmd(ENABLE);//使能内部温度传感器 ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式 ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; //DMA ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; //ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz ADC_CommonInit(&ADC_CommonInitStructure); ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE;//扫描模式(开启DMA传输要设置扫描) ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//开启连续转换(开启DMA传输要设置连续转换) ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐 ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1 ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_480Cycles ); //ADC16,ADC通道,480个周期,提高采样时间可以提高精确度 ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE);//开启AD转换器 } 二.DMA配置 查DMA通道映射表可知,我们应选择DMA2的通道0。本次实验我选择了数据流0。 DMA具体配置步骤为: 1,使能时钟 2,初始化DMA 3,使能DMA传输完成中断 4,配置DMA的优先级 5,使能DMA DMA配置见下: void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 mar,u16 ndtr) { DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1 { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 }else { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能 } DMA_DeInit(DMA_Streamx); while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//等待DMA可配置 /* 配置 DMA Stream */ DMA_InitStructure.DMA_Channel = chx; //通道选择 DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址 DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA 存储器0地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;// DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据长度:16位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//存储器数据长度:16位 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 使用循环模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输 DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream DMA_ClearFlag(DMA2_Stream0,DMA_IT_TC); DMA_ITConfig(DMA2_Stream0,DMA_IT_TC,ENABLE); NVIC_InitStructure.NVIC_IRQChannel=DMA2_Stream0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01; //响应优先级 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStructure); while (DMA_GetCmdStatus(DMA2_Stream0) != DISABLE){} DMA_Cmd(DMA2_Stream0, ENABLE); } 以上代码存放在dma.c里。此外,还有如下代码: #define NUM 10 //采集次数 extern u16 avr;//ADC获得的数据的平均值 extern u16 ADC_Data[NUM];//ADC采集到的数据 void Get_average_ADC(void) { register u16 sum=0; u8 count=0,j=0; while(j if(ADC_Data[j]>0) { sum+=ADC_Data[j]; count++; } j++; } avr=sum/count; sum=0;count=0;j=0; } void DMA2_Stream0_IRQHandler(void) { if (DMA_GetFlagStatus(DMA2_Stream0, DMA_IT_TCIF0) == SET) { Get_average_ADC();//每次进入中断,都会更新avr的值 DMA_ClearFlag(DMA2_Stream0, DMA_IT_TCIF0); } } main.c的配置 比较简单,代码如下: #define NUM 10 //采集次数 u16 avr; u16 ADC_Data[NUM]; float voltage,temperature; int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2 delay_init(168); //初始化延时函数 uart_init(115200); //初始化串口波特率为115200 LED_Init(); //初始化LED Adc_Init(); //内部温度传感器ADC初始化 MYDMA_Config(DMA2_Stream0, DMA_Channel_0, (u32)&ADC1->DR, (u32)ADC_Data, NUM); ADC_SoftwareStartConv(ADC1); //使能指定的ADC1的软件转换启动功能 while(1) { voltage=(float)avr*(3.3/4096); //电压值 temperature=(voltage-0.76f)*400+25; //转换为温度值 printf("%frnrn",temperature); LED0=!LED0; delay_ms(250); } } 以上,便完成了ADC采集温度传感器数据,DMA传输ADC采集到的数据,用串口将当前温度显示的功能。 实验结果 打开XCOM,经过复位,串口调试助手会显示当前温度数值。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1617 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1543 浏览 1 评论
977 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1595 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 05:58 , Processed in 0.779695 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号