当前位置: 首页 > news >正文

STM32F030通过DMA方式读取ADC及芯片内部温度程序

说明:采用DMA方式读取8通道ADC以及1通道芯片内部温度,Chip_Temp最终为计算得出的温度值。注:温度精确度一般为±1℃,最大为±2℃。

代码详见如下:

/*ADC.C*/



#include <stdio.h>
#include <math.h>
#include "stm32f0xx_exti.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_flash.h"
#include "stm32f0xx_rcc.h"
#include "stm32f0xx_usart.h"
#include "stm32f0xx_tim.h"
#include "stm32f0xx_rtc.h"
#include "stm32f0xx_dma.h"
#include "stm32f0xx_adc.h"
#include "platform_config.h"
#include "adc.h"

#define ADC_BUF_LEN 10
#define Channel_Num 9											//增加内部温度
#define Sample_Num	((unsigned short)120)
#define ADC_DAT_LEN (Sample_Num*Channel_Num)



#define ADC1_DR_ADDRESS (0x50000000+0x40)
extern struct SysInfo s;
unsigned short AdcDat[Sample_Num][Channel_Num];		//存储外部ADC通道数据
unsigned short Inject_Index;
#define VREF_TEMP_BUF_LEN 16
unsigned short VrefTempBuf[VREF_TEMP_BUF_LEN];
extern void UpdataAdcVal(unsigned char ch, unsigned short AdcVal);
extern void InsertDataToU16Buf(unsigned short Data, unsigned short *Buf, unsigned short Len);
/*
#define ADC_SampleTime_1Cycles5                    ((uint8_t)0x00)
#define ADC_SampleTime_7Cycles5                    ((uint8_t)0x01)
#define ADC_SampleTime_13Cycles5                   ((uint8_t)0x02)
#define ADC_SampleTime_28Cycles5                   ((uint8_t)0x03)
#define ADC_SampleTime_41Cycles5                   ((uint8_t)0x04)
#define ADC_SampleTime_55Cycles5                   ((uint8_t)0x05)
#define ADC_SampleTime_71Cycles5                   ((uint8_t)0x06)
#define ADC_SampleTime_239Cycles5                  ((uint8_t)0x07)

信号为50hz交流信号,
8M/6分频=1.333M,
采用55.5采集周期,采样频率约等于24.024K,那么一个周期采样点=24.024K/50=480个点
*/





unsigned short AverageU16(unsigned short *Buf, unsigned short Len){
	unsigned long temp;
	int i;
	for(i=0,temp=0; i<Len; i++){
		temp = temp + Buf[i];
	}
	
	return(temp/Len);
}
unsigned short MaxU16(unsigned short *Buf, unsigned short Len){
	unsigned long temp;
	int i;
	for(i=0,temp=0; i<Len; i++){
		if(temp < Buf[i])		temp = Buf[i];
	}
	
	return(temp);
}
void InitDma(void) 
{ 
 DMA_InitTypeDef DMA_InitStructure; 

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
 DMA_DeInit(DMA1_Channel1);
 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
 DMA_InitStructure.DMA_MemoryBaseAddr = (unsigned long)&AdcDat;
 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
 DMA_InitStructure.DMA_BufferSize = ADC_DAT_LEN;
 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
 DMA_InitStructure.DMA_Priority = DMA_Priority_High;
 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
 DMA_Init(DMA1_Channel1, &DMA_InitStructure);
 DMA_Cmd(DMA1_Channel1,ENABLE);
 ADC_DMACmd(ADC1, ENABLE);

	
}
void DMA1_Channel1_IRQHandler(void){
	if(DMA_GetITStatus(DMA1_IT_TC1) != RESET)	{
		DMA_ClearITPendingBit(DMA1_IT_TC1);
		StopAdc();
	}
}
void InitialAdc(void){
	    ADC_InitTypeDef     ADC_InitStructure;
			GPIO_InitTypeDef GPIO_InitStructure;  
			InitDma();	
	//NVIC_InitTypeDef NVIC_InitStructure;
        /*设置ADC分频因子为4 ,ADC最大时间不能超过14M*/
        RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);        

        /* ADC1 Periph clock enable */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

        /* ADC1 DeInit */  
        ADC_DeInit(ADC1);
        
        /*初始化ADC结构体,此句必须加,不加的话多路ADC数据会交换*/
        ADC_StructInit(&ADC_InitStructure);                         

        /*配置ADC分辨率为12位*/
        ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

        /*开启连续转换*/
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 

        /*禁止触发检测,使用软件触发*/
        ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

        /*ADC采集数据右对齐*/
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

        /*向上扫描*/
        ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;

        /*ADC初始化*/
        ADC_Init(ADC1, &ADC_InitStructure); 
                          
				//配置IO
			
				RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
				GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3| GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;  
				GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
				GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
				GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
				GPIO_Init(GPIOA,&GPIO_InitStructure);  
			
			ADC_ChannelConfig(ADC1, 
			    ADC_Channel_0 
				| ADC_Channel_1
				| ADC_Channel_2
				| ADC_Channel_3
				| ADC_Channel_4
		    | ADC_Channel_5
				| ADC_Channel_6
			  | ADC_Channel_7
			  | ADC_Channel_16, ADC_SampleTime_55_5Cycles); 

        /* ADC 校准 */
        ADC_GetCalibrationFactor(ADC1);
				ADC_VrefintCmd(ENABLE);
				ADC_TempSensorCmd(ENABLE);
				
				//ADC_TempSensorVrefintCmd(); //开启内部温度传感器

        /* 循环模式下的 ADC DMA 请求 */
        ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);

        /* 使能 ADC_DMA */
        ADC_DMACmd(ADC1, ENABLE);  

        /* 使能 ADC1 */
        ADC_Cmd(ADC1, ENABLE);     

        /* 等待 ADCEN 标志 */
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));

        /*  ADC1 常规软件启动转换 */  
        ADC_StartOfConversion(ADC1);

}


void StartAdc(void)
{
	ADC_StartOfConversion(ADC1);
	DMA_Cmd(DMA1_Channel1, ENABLE); 
}

void StopAdc(void)
{
	ADC_StopOfConversion(ADC1);
	DMA_Cmd(DMA1_Channel1, DISABLE); 
}

#if defined(SCU_ARM)
const unsigned char ADC_CHANNEL_MAP[8] = {0,1,2,3,4,5,6,7};
#elif defined(SCU_X86)
const unsigned char ADC_CHANNEL_MAP[8] = {0,1,2,3,4,5,6,7};
#endif

float Chip_Temp;


void ProcReadAdc(void){
	volatile int i,j;
	long v=0,v1=0;
	
	#if 0   //M0取消 Vint的处理方式

	//计算VREFINT,并校准, 得到的值用于模拟量校准
	for(j=0,v1=0; j<Sample_Num; j++){
		v1 = v1 + AdcDat[j][Channel_Num-1];
	}
	v = v1 / Sample_Num;
	InsertDataToU16Buf(v,VrefTempBuf, VREF_TEMP_BUF_LEN);
	s.u16_AdcVref_Now = AverageU16(VrefTempBuf, VREF_TEMP_BUF_LEN);
	///
	
	#endif
	
	for(i=0; i<AI_NUM; i++){
		for(j=0,v=0; j<Sample_Num; j++){
			v = v + AdcDat[j][i];
		}
		v = v / Sample_Num;
		UpdataAdcVal(ADC_CHANNEL_MAP[i], v);
		
		
		//s.fCali_Vref[i] = (float)s.u16_AdcVref_Now/s.u16_ADC_Vref[i];
		//s.fCali_Vref[i] = 1.0;
		/
	}
	
	
	for(j=0,v=0; j<Sample_Num; j++){
		v = v + AdcDat[j][8];
	}
	v = v / Sample_Num;
	Chip_Temp = (float)(v) * ((float)3.3/4096);
  Chip_Temp = (1.43 -Chip_Temp)/0.0043 +25.0;

	StartAdc();
}
void ADC_IRQHandler(void){
    /* Clear ADC1 EOC pending interrupt bit */
    ADC_ClearITPendingBit(ADC1, ADC_IT_EOSMP);    
}

相关文章:

  • 基于srpingboot高校智慧校园教学管理服务平台的设计与实现(源码+文档+部署讲解)
  • 折叠树展示树状层级数据
  • WEB安全--SQL注入--DNSlog外带
  • c# 正则表达式基础知识
  • Hard Disk Sentinel:您的硬盘健康“全科医生”,守护数据安全的智能管家
  • STT-MRAM CIM 赋能边缘 AI:高性能噪声鲁棒贝叶斯神经网络宏架构详解
  • 进行交通流预测,使用KAN+Transformer模型
  • 好的服务设计怎么做?15个原则.服务的归一化设计原则是什么?
  • VMware Tools 安装详细教程(Ubuntu 虚拟机)
  • 堆(heap)
  • Shell 语法基础学习(二)
  • vue 获取当前时间并自动刷新
  • 解决 ECharts 切换图表时的 Resize 问题
  • STL---set常用函数
  • c语言笔记 结构体基础
  • QT QML实现音频波形图进度条,可点击定位或拖动进度
  • 单目3d detection算法记录
  • 24集《不负美食不负卿》联合出品制作签约仪式成功举行
  • 【运维自动化-标准运维】如何实现一个最简单的流程编排
  • 【Redis】Redis的数据删除(过期)策略,数据淘汰策略。
  • 新城市志|上海再攻坚,营商环境没有最好只有更好
  • 工行回应两售出金条发现疑似杂质:情况不属实,疑似杂质应为金条售出后的外部附着物
  • 三大猪企4月生猪销量同比均增长,销售均价同比小幅下降
  • 越怕出错越会出错,“墨菲定律”的魔咒该怎么破?
  • 看展览|2025影像上海艺博会:市场与当代媒介中的摄影
  • 心相印回应官方旗舰店客服辱骂消费者:正排查