使用两个运放组成积分电路,比较器电路,结合单片机定时器计数,测量ADC,并使用protues仿真实现
视频连接:https://www.bilibili.com/video/av81800813/
单片机源程序如下:
- #include<reg52.h>
- //#include<absacc.h>
- //#include<intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- #define GPIO_DIG P0 //传送数据的端口设为P0,以上端口根据实际硬件电路图可做修改
- sbit S4=P2^3;
- sbit S3=P2^2; //使能信号
- sbit S2=P2^1; //读写控制信号
- sbit S1=P2^0; //数据命令选择端口
- sbit P30=P3^0;
- sbit P31=P3^1;
- sbit P33=P3^3;
- uint ss,vin;
- uchar lo,kl = 0;
- //--定义全局变量--//
- unsigned char code DIG_CODE[10]={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
- //0、1、2、3、4、5、6、7、8、9的显示码
- unsigned char DisplayData[4];
- //用来存放要显示的4位数的值
- /****************10MS延时函数******************************/
- void Delay10ms() //@12.000MHz
- {
- unsigned char i, j;
- i = 20;
- j = 113;
- do
- {
- while (--j);
- } while (--i);
- }
- /****************1MS延时函数******************************/
- void delay(unsigned int n)
- {
- unsigned int i,j;
- for(j=n;j>0;j--)
- for(i=112;i>0;i--);
- }
- void led_byte(unsigned int byte_data) //以十进制的方式显示一个字符变量
- {
- DisplayData[0] = ~DIG_CODE[(byte_data % 10000 /1000)]; //求千位数
- DisplayData[0] |= 0x80; //小数点
- DisplayData[1] = ~DIG_CODE[(byte_data%1000/100)]; //求百位数
- DisplayData[2] = ~DIG_CODE[(byte_data%100/10)]; //求十位数
- DisplayData[3] = ~DIG_CODE[(byte_data%10)]; //求个位数
- }
- /*******************************************************************************
- * 函 数 名 : DigDisplay
- * 函数功能 : 使用数码管显示
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void DigDisplay()
- {
- unsigned char i;
- led_byte(vin);
- for(i=0;i<4;i++)
- {
- switch(i) //位选,选择点亮的数码管,
- {
- case(0):
- S1=0;S2=1;S3=1;S4=1; break;//显示第0位
- case(1):
- S1=1;S2=0;S3=1;S4=1; break;//显示第1位
- case(2):
- S1=1;S2=1;S3=0;S4=1; break;//显示第2位
- case(3):
- S1=1;S2=1;S3=1;S4=0; break;//显示第3位
- }
- GPIO_DIG=DisplayData[i];//发送段码
- delay(10); //扫描间隔时间设定
- GPIO_DIG=0x00;//消隐
- }
- }
- /**************数码管显示*************************/
- void my_t0(void) interrupt 1 //定时器0中断用于固定时间对输入待测电压进行积分
- {
- TR0 = 0; //T0中断关 ///
- TH0 = 0;
- TL0 = 0;
- lo++; ///
- TF0 = 0; //清除T0中断标志 ///
- TR0 = 1; //T0中断开
- }
- void my_int0(void) interrupt 0 //外部中断 用于反积分过程结束检测
- {
- EX0 = 0; //INT0中断关
- TR0 = 0; //T0中断关
- TF0 = 0; //清除T0中断标志
- ss = TH0 * 256 + TL0;
- if(ss == 5) ss = vin; //解决数据缓存溢出BUG
- else {
- // ss = ss/10 + lo*6553 ; //计算电压
- // ss = ss/10 + lo*6553 + 37; //补偿系统误差
-
- if((ss % 10000 /1000) < 4)
- vin = ss/10 + lo*6553 + ss/1000; //补偿系统误差
- else
- vin = ss/10 + lo*6553 + ss/2000;
- }
- TH0 = 0;
- TL0 = 0;
- kl = 1;
- lo = 0;
- ss = 0;
- EA = 0;
- }
- void main()
- {
- char i = 0;
- P33 = 0;
- P31 = 0; ///
- P30 = 1;
- kl = 0;
- EA = 1; //中断开
- ET0 = 1; //定时计数0中断开
- //IP = 1; //定时0中断最高优先级 =2
- TMOD = 0x01; //定时0,1模式1 2个16位定时/计数器
- EX0 = 1; //INT0中断开
- TCON=0x01; //INT0负边缘触发或低电平触发在此好象作用相同
- IT0 = 1;
- while(1)
- {
- if(kl == 1 && i == 20)
- {
- ss = 0;
- lo = 0;
- // vin = 0;
- TR0 = 0;
- P31 = 0;
- P33 = 0;
- P30 = 1; //选择放电 ///
- delay(100);
-
- kl = 0;
- P30 = 0;
- P33 = 0;
- P31 = 1; //选择输入电压
- Delay10ms();
-
- TH0 = 0;
- TL0 = 0;
- P31 = 0;
- P33 = 1; //选择比较电压
- TF0 = 0; //清除T0中断标志
- TR0 = 1; //定时计数0起动
- EX0 = 1;
- EA = 1;
- }
- i++;
- if(i==21) i=0; //彻底完成第一次转换后进行下一次转换,防止互相干扰
- // delay(1);
-
-
- delay(1);
- DigDisplay();
-
- }
- }
复制代码
所有资料51hei提供下载:
单片机双积分AD-数码管.rar
(89.47 KB, 下载次数: 48)
|