image.png
//3位数码电压表
//电压范围:0-50V
//原理:比较器做为ADC
//共阴数码管
//5V稳定性越高,测量的电压越准确
//3位数码电压表
  • //电压范围:0-50V
  • //原理:比较器做为ADC
  • //共阴数码管
  • //5V稳定性越高,测量的电压越准确
  • #include "stc15w204s.h"
  • #include "Led_can.h"
  • typedef unsigned long u32;  //32位无符号整型数
  • typedef unsigned int u16;  //16位无符号整型数
  • typedef unsigned char u8;  //8位无符号整型数
  • #define MAIN_Fosc                22118400        //定义主时钟
  • #define        ADC_SCALE                50000                //ADC满量程, 根据需要设置
  • /*************        本地常量声明        **************/
  • //CMPCR1
  • #define        CMPEN        0x80        //1: 允许比较器, 0: 禁止,关闭比较器电源
  • #define        CMPIF        0x40        //比较器中断标志, 包括上升沿或下降沿中断, 软件清0
  • #define        PIE                0x20        //1: 比较结果由0变1, 产生上升沿中断
  • #define        NIE                0x10        //1: 比较结果由1变0, 产生下降沿中断
  • #define        PIS                0x08        //输入正极性选择, 0: 选择内部P5.5做正输入,           1: 由ADCIS[2:0]所选择的ADC输入端做正输入.
  • #define        NIS                0x04        //输入负极性选择, 0: 选择内部BandGap电压BGv做负输入, 1: 选择外部P5.4做输入.
  • #define        CMPOE        0x02        //1: 允许比较结果输出到P1.2, 0: 禁止.
  • #define        CMPRES        0x01        //比较结果, 1: CMP+电平高于CMP-,  0: CMP+电平低于CMP-,  只读
  • //CMPCR2
  • #define        INVCMPO        0x80        //1: 比较器输出取反,  0: 不取反
  • #define        DISFLT        0x40        //1: 关闭0.1uF滤波,   0: 允许
  • #define        LCDTY        0x00        //0~63, 比较结果变化延时周期数
  • #define        Pin0                0x01        //IO引脚 Px.0
  • #define        Pin1                0x02        //IO引脚 Px.1
  • #define        Pin2                0x04        //IO引脚 Px.2
  • #define        Pin3                0x08        //IO引脚 Px.3
  • #define        Pin4                0x10        //IO引脚 Px.4
  • #define        Pin5                0x20        //IO引脚 Px.5
  • #define        Pin6                0x40        //IO引脚 Px.6
  • #define        Pin7                0x80        //IO引脚 Px.7
  • #define        PinAll                0xFF        //IO所有引脚
  • /*************        本地变量声明        **************/
  • sbit        P_ADC        = P1^5;        //P1.5 比较器转IO输出端
  • u16                adc;                        //ADC中间值, 用户层不可见
  • u16                adc_duty;                //ADC计数周期, 用户层不可见
  • u16                adc_value;                //ADC值, 用户层使用
  • bit                adc_ok;                        //ADC结束标志, 为1则adc_value的值可用. 此标志给用户层查询,并且清0
  • /*************        本地函数声明        **************/
  • void ConfigTimer0();
  • void ConfigTimer2(u8 ms);
  • void main(void)
  • {
  •       
  • //IO口初始化
  •         P1M0 |= (Pin0+Pin1+Pin5);   //P1.0 P1.1 P1.5脚定义为推挽模式
  •         P3M0 |= (Pin0+Pin1+Pin2+Pin3+Pin6+Pin7);   //P3.0-P3.7脚定义为推挽模式
  •         P5M1 |= Pin4+Pin5;          //P5.4 P5.5设置为高阻输入
  •       
  • //比较器初始化
  •         CMPCR1 = 0;
  •         CMPCR2 = 20;                //比较结果变化延时周期数, 0~63
  •         CMPCR1 |= CMPEN;        //允许比较器                ENABLE,DISABLE
  • //        CMPCR1 |= PIE;                //允许上升沿中断        ENABLE,DISABLE
  • //        CMPCR1 |= NIE;                //允许下降沿中断        ENABLE,DISABLE
  • //        CMPCR1 |= PIS;                //输入正极性选择, 0: 选择内部P5.5做正输入,           1: 由ADCIS[2:0]所选择的ADC输入端做正输入.
  •         CMPCR1 |= NIS;                //输入负极性选择, 0: 选择内部BandGap电压BGv做负输入, 1: 选择外部P5.4做输入
  • //        CMPCR1 |= CMPOE;        //允许比较结果输出到P1.2,   ENABLE,DISABLE
  • //        CMPCR2 |= INVCMPO;        //比较器输出取反,         ENABLE,DISABLE
  •         CMPCR2 |= DISFLT;        //内部0.1uF滤波,          ENABLE,DISABLE
  •         ConfigTimer0();
  •         ConfigTimer2(5);
  •         EA = 1;                        //允许全局中断
  •         while (1)
  •         {
  •                
  •                 if(adc_ok)                //等待ADC结束
  •                 {
  •                         adc_ok = 0;                                //清除ADC已结束标志                              
  •                         Led_buff[0] = Led_Char[adc_value / 10000 % 10];
  •                         Led_buff[1] = Led_Char[adc_value / 1000 % 10];
  •                         Led_buff[1] &= 0x7f;   //加小数点
  •                         Led_buff[2] = Led_Char[adc_value / 100 % 10];
  •                 }
  •         }
  • }
  • /* 配置并启动T0,10us定时时间 */
  • void ConfigTimer0()
  • {
  •         AUXR |= 0x80;                //定时器时钟1T模式
  •         TMOD &= 0xF0;                //设置定时器模式
  •         TL0 = 0x23;                //设置定时初值 10微秒@22.1184MHz
  •         TH0 = 0xFF;                //设置定时初值
  •         TF0 = 0;                //清除TF0标志
  •         ET0 = 1;                //允许中断
  •         PT0 = 1;                //高优先级中断
  •         TR0 = 1;                //开始运行
  • }
  • /* 配置并启动T2,ms-T2定时时间 */
  • void ConfigTimer2(u8 ms)
  • {
  •     u32 tmp;  //临时变量
  •    
  •     tmp = MAIN_Fosc / 12;      //定时器计数频率
  •     tmp = (tmp * ms) / 1000;  //计算所需的计数值
  •     tmp = 65536 - tmp;        //计算定时器重载值
  •     tmp = tmp + 18;           //补偿中断响应延时造成的误差
  •     T2H = (u8)(tmp>>8);  //定时器重载值拆分为高低字节
  •     T2L = (u8)tmp;
  •          
  •         AUXR &= 0xEF;  // 启动T2定时器  方式 :16位重装模式计数器
  •         AUXR |= 0x10;  // 启动T2定时器
  •            IE2 &= 0xFB;  // 使能T2中断
  •         IE2 |= 0x04;  // 使能T2中断
  •          
  •     //ET2 = 1;        //使能T2中断
  •     //T2R = 1;        //启动T2定时器
  • }
  • /********************* Timer0中断函数************************/
  • void timer0_int () interrupt 1
  • {
  •         if((CMPCR1 & CMPRES) == 0)        P_ADC = 0;        //比较器输出高电平
  •         else                                //P_ADC输出低电平, 给负输入端做反馈.
  •         {
  •                 P_ADC = 1;                        //P_ADC输出高电平, 给负输入端做反馈.
  •                 adc ++;        //ADC计数+1
  •         }
  •         if(--adc_duty == 0)                        //ADC周期-1, 到0则ADC结束
  •         {
  •                 adc_duty = ADC_SCALE;        //周期计数赋初值
  •                 adc_value = adc;                //保存ADC值
  •                 adc = 0;                                //清除ADC值
  •                 adc_ok = 1;                                //标志ADC已结束
  •         }
  • }
  • /* T0中断服务函数,执行数码管扫描显示 */
  • void InterruptTimer2() interrupt 12
  • {               
  •    Led_can();
  •    WDT_CONTR=0x36;             //喂狗 2S
  • }
  • 复制代码