//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 }
复制代码