在学习(二)中提到本次会介绍有关芯片的ADC检测及相关的运算。网上也有许多介绍ADC采样的,但不同芯片不同电路,检测运算的方式也不同。
SN8F5702芯片的ADC功能简介
获取某输入引脚的电压值是不太可能的,因为芯片内部的信号只有01。所以必须经过运算转换将大致的模拟量算出来。进而得知对应的电压值。看芯片的手册的ADC章节可以了解到,SN8F5702芯片的ADC的分辨率是12位(后面运算有用),ADC 参考高电压包括 5 种:4 种内部参考源 (Vdd、4V、3V 和 2V)和外部参考源(由 AVREFH 引脚提供)。其他的不介绍了,自己想了解的去看芯片手册。直接介绍怎么编写ADC的初始化配置。
芯片ADC的初始化配置代码,结合上述自己理解相关意思。
void ADC_Init()
{
ADR=0x40;//使能AIN通道,选择时钟源Fosc/16;Fosc=32MHz;
VREFH=0x02;//使能ADCC內部VREFH,禁止PWM触发ADC开始,选择内部高电压4.0V
P1CON=0x0f;//
ADM=0x83;//使能ADC加上选择AIN3/P13通道作为ADC采样输入
}
SN8F5702芯片的获取ADC的值
配置好检测的参考电压和ADC的采样通道后,就需要通过相关的计算得到对应的电压模拟量。运算公式在主函数中。
uint GetAdc(uint ad_channel)//获取对应通道的ADC的值0x81,0x82,0x83等,分别检测P11,P12,P13等,看自己需求
{
uchar i = 0;
uint temp_ad_buf = 0;
uint temp_ad_data = 0;
ADM = (ADM&0XF0)|ad_channel;
for(i = 0; i < 8; i++)
{
ADM |= 0x40; //Start ADC
while((ADM & 0x20) != 0x20); //EOC
ADM &= 0xdf;
temp_ad_buf = ADB;
temp_ad_buf = (temp_ad_buf << 4) + (ADR & 0x0f);
temp_ad_data += temp_ad_buf;
}
temp_ad_data = (temp_ad_data ) >> 3;
return temp_ad_data;
}
获取到的值temp_ad_data为启动芯片进行ADC采样后相关寄存器中的值。
对某电池接入引脚进行ADC电压判断
前面介绍过ADC相关的程序编写,现在就看一看整个过程。代码如下。
#include<SN8F5702.H>
/*
SN8F5702芯片只有P0.0-P0.7,P1.0-P1.7,P2.0-P2.1引脚
*/
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
#define BAT_VC 0x83
sbit LED1=P0^0;
sbit LED2=P0^1;
void GpioInit()
{
//用户在用C语言编写的时候,必须按照这个顺序编写设置系统时钟
CKCON = 0x70;
CLKSEL = 0x05;
CLKCMD = 0x69;
CKCON = 0x00;
//芯片IO口的设置,P0,P1,P2
//其中P1口有唤醒使能P1W
P0=0xff;//输出高低电平控制,POM相应位使能
P0M=0xff;//定义输入0输出1。
P0UR=0x00;//内置上拉电阻控制,禁止0使能1,IO口为输出模式是建议禁止
P1=0x00;
P1M=0x00;
P1UR=0x00;
P1W=0x00;//唤醒禁用0,使能1
P2=0x00;
P2M=0x00;
P2UR=0x00;
}
void ADC_Init()
{
ADR=0x40;//使能AIN通道,选择时钟源Fosc/16;Fosc=32MHz;
VREFH=0x02;//使能ADCC內部VREFH,禁止PWM触发ADC开始,选择内部高电压4.0V
P1CON=0x0f;//
ADM=0x83;//使能ADC加上选择AIN3/P13通道作为ADC采样输入
}
uint GetAdc(uint ad_channel)//获取对应通道的ADC的值
{
uchar i = 0;
uint temp_ad_buf = 0;
uint temp_ad_data = 0;
ADM = (ADM&0XF0)|ad_channel;
for(i = 0; i < 8; i++)
{
ADM |= 0x40; //Start ADC
while((ADM & 0x20) != 0x20); //EOC
ADM &= 0xdf;
temp_ad_buf = ADB;
temp_ad_buf = (temp_ad_buf << 4) + (ADR & 0x0f);
temp_ad_data += temp_ad_buf;
}
temp_ad_data = (temp_ad_data ) >> 3;
return temp_ad_data;
}
uint BatAdc=0;
uint BatAdcValue=0;
void main()
{
GpioInit();
ADC_Init();
LED1=0,LED2=0;
while(1)
{
BatAdc=GetAdc(BAT_VC);
BatAdcValue=(ulong)BatAdc*4000/4096;//得到的数值位数字量,千数值
if(BatAdcValue >= 2800)//
{
//定2.8V
LED1=1;//端口值大于2.8V
LED2=0;
}
else
{
LED1=0;
LED2=1;//端口值小于2.8V
}
}
}