标题:
STM8L的ADC之测量VDD电压详解 含例程
[打印本页]
作者:
51hei小林
时间:
2016-10-10 00:55
标题:
STM8L的ADC之测量VDD电压详解 含例程
STM8L内部含有一个12位的ADC,拥有25个输入通道,包括一个内部温度传感器,一个内部参考电压。
STM8L使用外部参考电压作为ADC参考电压,由于VDD,GND一般和ADC的外部参考电压引脚VREF+,VREF-连接在一起。所以VDD的电压就是ADC的参考电压,由于LDO供给MCU的电压有一定的偏差。所以使用ADC前需要知道VDD的电压为多少,对于十二位的ADC,VDD电压对应的转换出的数值为4096(2^12).
从第一张图中可以看到,STM8L内部还有一个内部参考电压,这个内部参考电压的电压值是可知的,且是精确的。由数据手册可知,内部参考电压为1.225V。
ADC选择内部参考电压作为测量通道,可以测量到内部电压的转化值Nadc。
此时,已经VDD的转化值4096,VREFINT电压值1.225V及对应的转化值Nadc。
这些值满足比例关系,VDD/4096=VREFINT/Nadc
VDD/4096 =1.225/Nadc
VDD=1.225*4096/Nadc
本文使用ADC的单次转换模式,每隔大约0.5S触发一次ADC转换。ADC转换的通道需要在ADC_SQR寄存器中选择。
ADC完成一次数据采集转化后,会进入中断。我们在中断中打一个断点,查看变量VDD_Value中的数据,可以看到此时数据为2976(电压值被扩大了1000倍),即VDD的电压为2.976V。.与实际用万用表测量的2.99V几乎一样。
/****************************************************************************************
*开发环境:IAR for stm8 v1.40.1
*硬件平台:STM8L-DISCOVERY
*功能说明:测量VDD电压,VDD的计算结果在ADC中断中,通过仿真,设置断点,可以在IAR中查看扩大1000被后的VDD电压数据VDD_Value
*作 者:茗风
****************************************************************************************/
#include"iostm8l152c6.h"
#include"stdbool.h"
#include"stdint.h"
uint16_t VDD_Value=0;
/******************************************************************************************************
* 名 称:void delay_10ms(uint8_t x_ms)
* 功 能:延时10ms
* 入口参数:无
* 出口参数:无
* 说 明:
* 范 例:无
******************************************************************************************************/
void delay_100ms(void)
{
uint8_t i,j;
for(i=0;i<255;i++)//2*255个指令周期
for(j=0;j<255;j++);//2*255个指令周期
//delay_10ms共消耗 x_ms*2*255+2*x_ms个指令周期
//255*2*255+2*255=130610us=130ms
//此延时函数,延时时间为130ms
//16M/8/2=1M 一个指令周期为1us
}
/******************************************************************************************************
* 名 称:void ADC_Init(void)
* 功 能:初始化ADC
* 入口参数:无
* 出口参数:无
* 说 明:ADC1的测量通道为内部参考电压,单次转换模式
* 范 例:无
******************************************************************************************************/
void ADC_Init(void)
{
CLK_PCKENR2_PCKEN20=1; //国际惯例,开启ADC1外设时钟
ADC1_TRIGR1_VREFINTON=1;//打开内部参考电压源
ADC1_CR1_ADON=1; //wakes up the ADC from Power down mode.
ADC1_CR2_PRESC=1;//Select a sample time of 10 μs
// 0: f(ADC_CLK) = CK
// 1: f(ADC_CLK) = CK/2 //系统时钟此时为默认的16M/8=2M,这里分频后,fadc=2M/2=1M
ADC1_SQR1_DMAOFF=1; //关闭DMA,暂时不用
ADC1_CR3_SMTP2=0x06;//采样时间为24 ADC clock cycles,也就是24*1us=24us
//000: 4 ADC clock cycles
//001: 9 ADC clock cycles
//010: 16 ADC clock cycles
//011: 24 ADC clock cycles
//100: 48 ADC clock cycles
//101: 96 ADC clock cycles
//110: 192 ADC clock cycles
//111: 384 ADC clock cycles
ADC1_SQR1_CHSEL_S28=1; //选择内部参考电压通道
ADC1_CR1_EOCIE=1;
}
void main(void)
{
ADC_Init();
asm("rim"); //enable interrupts
while(1)
{
delay_100ms();
ADC1_CR1_START=1;
delay_100ms();
delay_100ms();
delay_100ms();
delay_100ms();
}
}
/******************************************************************************************************
* 名 称: ADC中断
* 功 能: EOC事件处理函数
* 入口 参数:无
* 出口 参数:无
* 说 明:
* 范 例:无
******************************************************************************************************/
#pragma vector=COMP_EF2_vector
__interrupt void ADC1_ISR(void)
{
static uint16_t temp=0;
PC_ODR_ODR7 ^=0x01;//输出低电平
ADC1_SR_EOC=0;
temp = ADC1_DRH;
temp = (temp<<8)+ADC1_DRL;
VDD_Value=(uint32_t)1225*4096/temp;//得到的数值单位为mv
asm("nop");
}
复制代码
作者:
s414545584
时间:
2017-8-24 20:22
这么好的东西咋没人点赞呢???怒赞,狂赞,超赞666
作者:
zengruiqiu
时间:
2018-6-20 12:02
这么好的东西咋没人点赞呢???怒赞,狂赞,超赞666
作者:
jstele
时间:
2018-6-30 09:41
學習了
作者:
Boney
时间:
2018-11-15 15:25
学习了,正需要,mark
作者:
wdp1123
时间:
2018-11-29 11:56
好东西要学习
作者:
jxchen
时间:
2019-2-15 22:59
棒棒棒
作者:
monkeg3267
时间:
2020-5-15 15:24
教大家一起来点赞! 挺详细的的
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1