STM32F103RC DMA ADC 温度,电压采样
#include "stm32f10x.h"
#include "stm32f10x_adc.h"
#include "adc.h"
extern const u16 NTCTab[];
__IO uint16_t ADC_DualConvertedValueTab[10][10];
/**
*/
void ADCx_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 打开 ADC IO端口时钟
ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE );
ADC_GPIO_APBxClock_FUN ( RCC_APB2Periph_GPIOB, ENABLE );
ADC_GPIO_APBxClock_FUN ( RCC_APB2Periph_GPIOA, ENABLE );
// 配置 ADC IO 引脚模式
// 必须为模拟输入
GPIO_InitStructure.GPIO_Pin = ADC_PIN_T1 | ADC_PIN_T2 | ADC_PIN_T3 | ADC_PIN_T4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
// 初始化 ADC IO
GPIO_Init(ADC_PORT_T, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ADC_PIN_L1 | ADC_PIN_L2 ;
GPIO_Init(ADC_PORT_L, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ADC_PIN_L3 | ADC_PIN_L4 | ADC_PIN_V1 | ADC_PIN_V2;
GPIO_Init(ADC_PORT_V, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = TEST_SEL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(TEST_SEL_PORT, &GPIO_InitStructure);
}
/**
* @brief 配置ADC工作模式
* @param 无
* @retval 无
*/
static void ADCx_Mode_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能时钟
/* DMA1 channel1 configuration ----------------------------------------------*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_DualConvertedValueTab;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 100;
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_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA1 Channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
// 打开ADC时钟
ADC_APBxClock_FUN ( ADC_CLK, ENABLE );
// /*IO和ADC使能时钟*/
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA,ENABLE);
// RCC_ADCCLKConfig(RCC_PCLK2_Div6);
// ADC 模式配置
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 只使用一个ADC,属于独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE ; // 扫描模式,多通道
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换模式
// 不用外部触发转换,软件开启即可
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
// 转换结果右对齐
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
// 转换通道1个
ADC_InitStructure.ADC_NbrOfChannel = 10;
// 初始化ADC
ADC_Init(ADCx, &ADC_InitStructure);
// 配置ADC时钟为PCLK2的8分频,即9MHz
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
// 配置 ADC 通道转换顺序和采样时间
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL_T1, 1,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL_T2, 2,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL_T3, 3,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL_T4, 4,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL_L1, 5,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL_L2, 6,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL_L3, 7,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL_L4, 8,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL_V1, 9,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL_V2, 10,ADC_SampleTime_239Cycles5);
// ADC 转换结束产生中断,在中断服务程序中读取转换值
// ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
// 开启ADC ,并开始转换
ADC_DMACmd(ADC1, ENABLE);//开启ADC的DMA支持
ADC_Cmd(ADCx, ENABLE);
// 初始化ADC 校准寄存器
ADC_ResetCalibration(ADCx);
// 等待校准寄存器初始化完成
while(ADC_GetResetCalibrationStatus(ADCx));
// ADC开始校准
ADC_StartCalibration(ADCx);
// 等待校准完成
while(ADC_GetCalibrationStatus(ADCx))
{
}
// 由于没有采用外部触发,所以使用软件触发ADC转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //开始转换
}
/**********************************************************************
//
******************************************
static void ADC_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
// 配置中断优先级
NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
*/
/**
* @brief ADC初始化
* @param 无
* @retval 无
*/
void ADCx_Init(void)
{
ADCx_GPIO_Config();
ADCx_Mode_Config();
// ADC_NVIC_Config();
}
/******************************************************
计算平均数
******************************************************/
u16 adc_result(u8 ch)
{
u8 i;
u16 Value;
u32 sum;
sum = 0;
for(i=0;i<10;i++)
sum += ADC_DualConvertedValueTab[i][ch];
Value = sum / 10;
return Value;
}
/******************************************************
查表函数
******************************************************/
u16 look_up_table(const u16 *a,u16 ArrayLong,u16 data)
{
u16 begin,end,middle ;
u16 i ;
begin = 0 ;
end = ArrayLong-1 ;
i = 0 ;
if(data >= a[begin])
{
return begin ;
}
else if(data <= a[end])
return end ;
while(begin < end)
{
middle = (begin+end)/2 ;
if(data == a[middle] )
break ;
if(data < a[middle] && data > a[middle+1])
break ;
if(data > a[middle])
end = middle ;
else
begin = middle ;
if(i++ > ArrayLong)
break ;
}
if(begin > end )
return 0 ;
return middle ;
}
/******************************************************
温度查表转换计算(33K+100K)3路
******************************************************/
int temp_LookUp(uchar a)
{
uint i;
uint dy1=0,xsd;
int tt;
dy1 = adc_result(a);
i = look_up_table(NTCTab,260,dy1);
tt = NTCTab[i] - NTCTab[i+1];
xsd = 10-((dy1 % tt)*10/tt); //计算小数点后的数值
if(i>40)
{
tt = i - 40;
tt = tt * 10;
tt = tt + xsd;
}
else if(i > 0)
{
tt = -40 + (int)i;
tt = tt * 10;
tt = tt + xsd;
}
else
tt = -400;
return(tt);
}
/*************************************
检查漏电互感器
*************************************/
void CheckLeak(u16 *lc,u16 *ca,u16 *cb,u16 *cc)
{
u32 sum;
u16 i;
SET_TEST_SEL; //模拟开关常开NO -> ON 常闭打开NC -> OFF
DelayMsKey(500);
sum = 0;
for(i=0;i<10;i++)
sum += 0xfff-ADC_DualConvertedValueTab[i][ADC_LC1];
*lc = sum;
// *lc = adc_result(ADC_LC1);
sum = 0;
for(i=0;i<10;i++)
sum += 0xfff-ADC_DualConvertedValueTab[i][ADC_CA];
*ca = sum;
sum = 0;
for(i=0;i<10;i++)
sum += 0xfff-ADC_DualConvertedValueTab[i][ADC_CB];
*cb = sum;
sum = 0;
for(i=0;i<10;i++)
sum += 0xfff-ADC_DualConvertedValueTab[i][ADC_CC];
*cc = sum;
// *ca = adc_result(ADC_CA);
// *cb = adc_result(ADC_CB);
// *cc = adc_result(ADC_CC);
CLR_TEST_SEL; //模拟开关常开NO -> OFF 常闭打开NC -> ON
DelayMsKey(1500);
}
/**********************
电源模块输出电压
**********************/
u16 GetSysVoltage(void)
{
float temp;
temp = (float)adc_result(ADC_SV);
temp = (temp/4096)*3.3*2;
temp *= 10;
return((u16)temp);
}
/**********************
电池电压
**********************/
u16 GetBatVoltage(void)
{
float temp;
temp = (float)adc_result(ADC_BatVol);
temp = (temp/4096)*3.3*2;
temp *= 10;
return((u16)temp);
}
/*******************************************
ADC 温度转换
********************************************/
const u16 NTCTab[]=
{
0xfff,//0
0xFF3,//-40℃
0xFF2,//-39℃
0xFF1,//-38℃
0xFF0,//-37℃
0xFEF,//-36℃
0xFED,//-35℃
0xFED,//-34℃
0xFEC,//-33℃
0xFEA,//-32℃
0xFE9,//-31℃
0xFE8,//-30℃
0xFE6,//-29℃
0xFE4,//-28℃
0xFE3,//-27℃
0xFE1,//-26℃
0xFDF,//-25℃
0xFDD,//-24℃
0xFDB,//-23℃
0xFD9,//-22℃
0xFD7,//-21℃
0xFD6,//-20℃
0xFD3,//-19℃
0xFD1,//-18℃
0xFCE,//-17℃
0xFCB,//-16℃
0xFC8,//-15℃
0xFC5,//-14℃
0xFC2,//-13℃
0xFBF,//-12℃
0xFBB,//-11℃
0xFB7,//-10℃
0xFB3,//-9℃
0xFAF,//-8℃
0xFAB,//-7℃
0xFA6,//-6℃
0xFA2,//-5℃
0xF9D,//-4℃
0xF98,//-3℃
0xF92,//-2℃
0xF8D,//-1℃
0xF87,//0℃
0xF81,//1℃
0xF7B,//2℃
0xF74,//3℃
0xF6D,//4℃
0xF66,//5℃
0xF5E,//6℃
0xF57,//7℃
0xF4F,//8℃
0xF46,//9℃
0xF3E,//10℃
0xF35,//11℃
0xF2B,//12℃
0xF21,//13℃
0xF17,//14℃
0xF0C,//15℃
0xF01,//16℃
0xEF5,//17℃
0xEEA,//18℃
0xEDE,//19℃
0xED1,//20℃
0xEC4,//21℃
0xEB7,//22℃
0xEA9,//23℃
0xE9A,//24℃
0xE8C,//25℃
0xE7C,//26℃
0xE6D,//27℃
0xE5D,//28℃
0xE4C,//29℃
0xE3B,//30℃
0xE2A,//31℃
0xE18,//32℃
0xE05,//33℃
0xDF2,//34℃
0xDDF,//35℃
0xDCB,//36℃
0xDB6,//37℃
0xDA1,//38℃
0xD8C,//39℃
0xD78,//40℃
0xD61,//41℃
0xD4B,//42℃
0xD33,//43℃
0xD1C,//44℃
0xD03,//45℃
0xCEB,//46℃
0xCD1,//47℃
0xCB8,//48℃
0xC9E,//49℃
0xC83,//50℃
0xC68,//51℃
0xC4D,//52℃
0xC31,//53℃
0xC15,//54℃
0xBF8,//55℃
0xBDB,//56℃
0xBBD,//57℃
0xBA0,//58℃
0xB81,//59℃
0xB63,//60℃
0xB44,//61℃
0xB25,//62℃
0xB06,//63℃
0xAE6,//64℃
0xAC6,//65℃
0xAA6,//66℃
0xA85,//67℃
0xA64,//68℃
0xA44,//69℃
0xA23,//70℃
0xA02,//71℃
0x9E0,//72℃
0x9BF,//73℃
0x99D,//74℃
0x979,//75℃
0x957,//76℃
0x935,//77℃
0x914,//78℃
0x8F2,//79℃
0x8D1,//80℃
0x8AF,//81℃
0x88E,//82℃
0x86D,//83℃
0x84C,//84℃
0x82B,//85℃
0x80A,//86℃
0x7E9,//87℃
0x7C8,//88℃
0x7A8,//89℃
0x789,//90℃
0x769,//91℃
0x74A,//92℃
0x72B,//93℃
0x70C,//94℃
0x6ED,//95℃
0x6CF,//96℃
0x6B0,//97℃
0x692,//98℃
0x675,//99℃
0x657,//100℃
0x63A,//101℃
0x61D,//102℃
0x601,//103℃
0x5E4,//104℃
0x5C8,//105℃
0x5AD,//106℃
0x592,//107℃
0x577,//108℃
0x55C,//109℃
0x542,//110℃
0x528,//111℃
0x50F,//112℃
0x4F6,//113℃
0x4DD,//114℃
0x4C3,//115℃
0x4AB,//116℃
0x493,//117℃
0x47C,//118℃
0x463,//119℃
0x44F,//120℃
0x439,//121℃
0x424,//122℃
0x40E,//123℃
0x3FA,//124℃
0x3E5,//125℃
0x3D1,//126℃
0x3BE,//127℃
0x3AA,//128℃
0x397,//129℃
0x385,//130℃
0x373,//131℃
0x361,//132℃
0x34F,//133℃
0x33E,//134℃
0x32E,//135℃
0x31D,//136℃
0x30D,//137℃
0x2FD,//138℃
0x2EE,//139℃
0x2E0,//140℃
0x2D1,//141℃
0x2C2,//142℃
0x2B4,//143℃
0x2A6,//144℃
0x298,//145℃
0x28B,//146℃
0x27E,//147℃
0x271,//148℃
0x264,//149℃
0x258,//150℃
0x24B,//151℃
0x240,//152℃
0x234,//153℃
0x229,//154℃
0x21D,//155℃
0x212,//156℃
0x208,//157℃
0x1FD,//158℃
0x1F3,//159℃
0x1E9,//160℃
0x254,//161℃
0x24C,//162℃
0x243,//163℃
0x23B,//164℃
0x232,//165℃
0x22A,//166℃
0x222,//167℃
0x21A,//168℃
0x212,//169℃
0x20A,//170℃
0x203,//171℃
0x1FB,//172℃
0x1F4,//173℃
0x1ED,//174℃
0x1E6,//175℃
0x1DE,//176℃
0x1D7,//177℃
0x1D1,//178℃
0x1CA,//179℃
0x1C3,//180℃
0x1BD,//181℃
0x1B6,//182℃
0x1B0,//183℃
0x1AA,//184℃
0x1A4,//185℃
0x19E,//186℃
0x198,//187℃
0x192,//188℃
0x18C,//189℃
0x186,//190℃
0x181,//191℃
0x17B,//192℃
0x176,//193℃
0x170,//194℃
0x16B,//195℃
0x166,//196℃
0x161,//197℃
0x15C,//198℃
0x157,//199℃
0x152,//200℃
0x14D,//201℃
0x148,//202℃
0x144,//203℃
0x13F,//204℃
0x13B,//205℃
0x136,//206℃
0x132,//207℃
0x12D,//208℃
0x129,//209℃
0x125,//210℃
0x121,//211℃
0x11D,//212℃
0x119,//213℃
0x115,//214℃
0x111,//215℃
0x10D,//216℃
0x10A,//217℃
0x106,//218℃
0x102,//219℃
0x0FF,//220℃
0x000 //短路
};
#ifndef _ADC_H_
#define _ADC_H_
#include "stm32f10x.h"
// ADC 编号选择
// 可以是 ADC1/2,如果使用ADC3,中断相关的要改成ADC3的
#define ADC_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADCx ADC1
#define ADC_CLK RCC_APB2Periph_ADC1
// ADC GPIO宏定义
#define TEST_SEL_PORT GPIOC
#define TEST_SEL_PIN (1<<9) //PC9 模块开关选择
#define CLR_TEST_SEL TEST_SEL_PORT->ODR &= ~TEST_SEL_PIN
#define SET_TEST_SEL TEST_SEL_PORT->ODR |= TEST_SEL_PIN
// 注意:用作ADC采集的IO必须没有复用,否则采集电压会有影响
#define ADC_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADC_GPIO_CLK RCC_APB2Periph_GPIOC
#define ADC_PORT_T GPIOA
#define ADC_PIN_T1 GPIO_Pin_7
#define ADC_PIN_T2 GPIO_Pin_6
#define ADC_PIN_T3 GPIO_Pin_5
#define ADC_PIN_T4 GPIO_Pin_4
#define ADC_PORT_L GPIOB
#define ADC_PIN_L1 GPIO_Pin_0
#define ADC_PIN_L2 GPIO_Pin_1
#define ADC_PORT_V GPIOC
#define ADC_PIN_L3 GPIO_Pin_0
#define ADC_PIN_L4 GPIO_Pin_1
#define ADC_PIN_V1 GPIO_Pin_2 //开关电源
#define ADC_PIN_V2 GPIO_Pin_3 //电池
// ADC 通道宏定义
#define ADC_CHANNEL_T1 ADC_Channel_7
#define ADC_CHANNEL_T2 ADC_Channel_6
#define ADC_CHANNEL_T3 ADC_Channel_5
#define ADC_CHANNEL_T4 ADC_Channel_4
#define ADC_CHANNEL_L1 ADC_Channel_8 //漏电
#define ADC_CHANNEL_L2 ADC_Channel_9 //A相
#define ADC_CHANNEL_L3 ADC_Channel_10
#define ADC_CHANNEL_L4 ADC_Channel_11
#define ADC_CHANNEL_V1 ADC_Channel_12 //开关电源
#define ADC_CHANNEL_V2 ADC_Channel_13 //电池
#define ADC_LC1 4
#define ADC_CA 5
#define ADC_CB 6
#define ADC_CC 7
#define ADC_SV 8
#define ADC_BatVol 9
// ADC 中断相关宏定义
#define ADC_IRQ ADC1_2_IRQn
#define ADC_IRQHandler ADC1_2_IRQHandler
//#define ADC_IRQ ADC3_IRQn
//#define ADC_IRQHandler ADC3_IRQHandler
#define ADC1_DR_Address ((uint32_t)0x4001244C)
void ADCx_Init(void);
int temp_LookUp(uchar a);
void CheckLeak(u16 *lc,u16 *ca,u16 *cb,u16 *cc);
u16 GetSysVoltage(void);
u16 GetBatVoltage(void);
#endif