STM32F103RC DMA ADC 温度,电压采样
时间:2023-01-14 06:30:00
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