/******************************************************************************** 文件名: ADC转换器使用 * 描 述: 电池电压 * 功 能:中断方式 11.059200MHZ * 作 者:大核桃 * 版本号:1.0.1(2017.05.23) *******************************************************************************/ #include "stc15w.h"//头文件 #include "intrins.h" /******************************************************************************* * 文件名: 重定义 * 描 述: * 功 能: * 作 者:大核桃 * 版本号:1.0.1(2017.05.23) *******************************************************************************/ typedef unsigned char uint8; typedef unsigned int uint16; typedef unsigned long uint32; #define ADC_POWER 0x80 //ADC电源控制位 #define ADC_FLAG 0x10 //ADC完成标志 #define ADC_START 0x08 //ADC起始控制位 #define ADC_SPEEDLL 0x00 //540个时钟 /******************************************************************************* * 文件名:全局变量定义区域 * 描 述: * 功 能: * 作 者:大核桃 * 版本号:1.0.1(2015.03.03) *******************************************************************************/ uint8 val,ch; uint16 temp; /******************************************************************************* * 文件名:共阳数码管真值表 * 描 述: * 功 能: * 作 者:大核桃 * 版本号:1.0.1(2015.03.03) *******************************************************************************/ code uint8 LedChar[] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xc1 }; /******************************************************************************* * 文件名:单独位定义 * 描 述: * 功 能: * 作 者:大核桃 * 版本号:1.0.1(2017.05.23) *******************************************************************************/ sbit LED0 = P1^0;//第1组LED sbit LED1 = P1^1;//第2组LED sbit LED2 = P1^2;//第3组LED sbit LED3 = P1^3;//第4组LED sbit LED4 = P1^4;//第5组LED sbit LED5 = P3^2;//第6组LED sbit LED6 = P0^0;//第7组LED sbit LED7 = P0^1;//第8组LED sbit LEDS1 = P3^3;//数码管1 sbit LEDS2 = P3^4;//数码管2 sbit LEDS3 = P3^6;//数码管3 sbit LEDS4 = P3^7;//数码管4 /******************************************************************************* * 文件名:函数前置声明 * 描 述: * 功 能: * 作 者:大核桃 * 版本号:1.0.1(2017.05.23) *******************************************************************************/ void Mcu_Port_Init(); void LedScan(); void Delay500ms(); //24MHZ void Time0_Init();//定时器0 void InitADC(void); /******************************************************************************* * 文件名 * 描 述: 主函数 * 功 能:入口 * 作 者:大核桃 * 版本号:1.0.1(2017.05.23) *******************************************************************************/ void main(void) { Mcu_Port_Init();//IO上电初始化 Time0_Init(); InitADC(); while(1); } /******************************************************************************* * 文件名:void LedScan() * 描 述: LED刷新 * 功 能: * 作 者:大核桃 * 版本号:1.0.1(2017.05.23) *******************************************************************************/ void LedScan() { static uint8 i = 0; P2 = 0Xff; switch(i) { case 0: LEDS4 = 0;LEDS1 = 1;P2 = 0x7f & LedChar[16];i++;break; case 1: LEDS1 = 0;LEDS2 = 1;P2 = LedChar[val / 10 % 10];i++;break; case 2: LEDS2 = 0;LEDS3 = 1;P2 = LedChar[val % 10];i++;break; case 3: LEDS3 = 0;LEDS4 = 1;P2 = LedChar[17];i = 0;break; default:break; } } /******************************************************************************* * 文件名:void InitADC(void) * 描 述: //初始化 AD 转换 * 功 能: * 作 者:大核桃 * 版本号:1.0.1(2015.03.03) *******************************************************************************/ void InitADC(void) { P1ASF = 0xE0; //设置 P1 口为模拟口 ADC_RES = 0; //清除结果寄存器 CLK_DIV |= 0x20; //ADRJ 为 1,ADC_RES 存放高两位结果,ADC_RESL 存放低 8 位结果 //ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START; ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START; //ADC上电并延时 } /******************************************************************************* * 文件名:void adc_isr() interrupt 5 using 1 * 描 述: 中断服务程序 * 功 能: * 作 者:大核桃 * 版本号:1.0.1(2015.03.03) *******************************************************************************/ void adc_isr() interrupt 5 using 1 { EADC = 1; //允许ADC转换中断 ET0 = 0; //关闭定时器0中断 ADC_CONTR &= !ADC_FLAG; //清除ADC中断标志 temp = ADC_RES; temp <<= 8; temp |= ADC_RESL; ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 5; EADC = 0;//关闭ADC转换 ET0 = 1; //打开定时器0中断 } /******************************************************************************* * 文件名:void VoltageCheckRefresh() * 描 述: 电压检测 * 功 能: * 作 者:大核桃 * 版本号:1.0.1(2015.03.03) *******************************************************************************/ void VoltageCheckRefresh() { val = (uint8)((temp)* 2 * 10 * 3.3 / 1023); } /******************************************************************************* * 文件名:void Time0_Init() * 描 述: 定时器0初始化 * 功 能:10毫秒@11.0592MHz * 作 者:大核桃 * 版本号:1.0.1(2017.05.23) *******************************************************************************/ void Time0_Init(void) { AUXR &= 0x7F; //定时器时钟12T模式 TMOD &= 0xF0; //设置定时器模式 TMOD |= 0X01; //确保不干扰其他配置 TH0 = (65536 - 1000) / 256; //设置定时初值 TL0 = (65536 - 1000) % 256; //设置定时初值 ET0 = 1; TR0 = 1; //定时器0开始计时 EA = 1; } /******************************************************************************* * 文件名: * 描 述: 中断函数 * 功 能:1毫秒@11.0592MHz * 作 者:大核桃 * 版本号:1.0.1(2017.05.23) *******************************************************************************/ void ET0_IRQHandler() interrupt 1 { static uint8 tmr5ms = 0; TH0 = (65536 - 1000) / 256; //设置定时初值 TL0 = (65536 - 1000) % 256; //设置定时初值 EADC = 0; //不允许ADC转换中断 tmr5ms++; if(tmr5ms >= 5) { tmr5ms = 0; //定时器5MS溢出一次 VoltageCheckRefresh(); } LedScan(); EADC = 1; //允许ADC转换中断 } /******************************************************************************* * 文件名:void Mcu_Port_Init() * 描 述: io初始化 * 功 能: * 作 者:大核桃 * 版本号:1.0.1(2017.05.23) *******************************************************************************/ void Mcu_Port_Init() { IE = 0xa8;//允许AD转换 //将P0口低二位配置为推挽输出 //234567位配置位高阻输入 P0M1 = 0xFC;//1111 1100 P0M0 = 0X03;//0000 0011 //P0 = 0X01;//第6个 //P0 = 0X02;//第7个 //高3位配置高阻输入,用作模拟口 //其他配置推挽输出,驱动LED P1M1 = 0xE0;//1110 0000 P1M0 = 0X1F;//0001 1111 //P2口配置准双向口 P2M1 = 0X00; P2M0 = 0X00; P2 = 0Xff; //上电为1111 1111 // //P54,P55口为推挽输出 P5M1 = 0X00; P5M0 = 0X00; P5 = 0xFF; //P37,P36,3.2,P3.3 P3.4口为推挽输出 P3M1 = 0X00; P3M0 = 0XFC; P3 = 0X23; //0010 0111//第5个LED端口 LED0 = 0;//第1组LED,如果使能请置为1 LED1 = 0; LED2 = 0; LED3 = 0; LED4 = 0; LED5 = 0; LED6 = 0; LED7 = 0; } /******************************************************************************* * 文件名:void Delay500ms() //@11.0592MHz * 描 述:Y5内核延时 * 功 能: * 作 者:大核桃 * 版本号:1.0.1(2017.05.23) *******************************************************************************/ void Delay500ms() //@11.0592MHz { unsigned char i, j, k; _nop_(); _nop_(); i = 22; j = 3; k = 227; do { do { while (--k); } while (--j); } while (--i); }
复制代码在数码管上显示的数值如下图所示,注意这是测试的锂电池的电压:
实际万用表测量的结果是4.01V,数码管显示的结果跟万用表的结果相差0.01V,我们用的ADC是10位的分辨率,参考电压是3.3V,那么一个LSB是3.3/1024 = 0.00322265625,那么0.01V,差不多3个LSB,考虑到我们的参考电压也是有少许误差存在的,所以这个结果还是比较合理的,如果使用独立的参考电压,误差应该会更小。