|
给大家分享一个51单片机双积分式AD转换的Proteus仿真,下面是原理图:
单片机双积分式AD转换的所有资料下载(包含源程序和proteus仿真):
单片机双积分式AD转换电路源程序Proteus仿真.rar
(63.1 KB, 下载次数: 170)
单片机源程序:
- /*-------------------------------------------------------------------
- LCD1602.c 1602用的函数
-
- 作者:liunian
- 邮箱:liunian_leon@sohu.com
- 日期:7.13
-
- 版本:V1.0 适合初学者使用
- -------------------------------------------------------------------*/
- #include<reg51.h>
- #include<absacc.h>
- #include<intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit EN=P2^2; //使能信号
- sbit RW=P2^1; //读写控制信号
- sbit RS=P2^0; //数据命令选择端口
- sbit P34=P3^4;
- sbit P35=P3^5;
- #define D_port P0 //传送数据的端口设为P0,以上端口根据实际硬件电路图可做修改
- uint ss,lo,loo;
- uchar kl = 0;
- unsigned char code love[]="Dual Integral AD";
- unsigned char code no[]=" ";
- unsigned char code time[]="0123456789ABCDEF:MinHour ";
- unsigned char code tin[]= "Vin:";
- unsigned char code tvref[]="Vref:";
- /****************1MS延时函数******************************/
- void delay(unsigned int n)
- {
- unsigned int i,j;
- for(j=n;j>0;j--)
- for(i=112;i>0;i--);
- }
- /*液晶***************查询液晶是否忙*************************/
- void Checkbusy()
- {
-
- D_port=0xff; //P0全部置1,可以查询判断P0口状态,读取液晶的命令
- RS=0;
- RW=1;
- EN=1;
- _nop_(); //读液晶命令时各控制位的状态几时序
- while(D_port&0x80) //判断最高位状态,最高位是液晶忙的状态位
- {
- EN=0;
- _nop_();
- _nop_();
- EN=1;
- _nop_();
- _nop_();
- } //如果液晶忙,则循环查询
- EN=0;
- }
- /*液晶***************写数据到液晶***************************/
- D_write(uchar a)
- {
- Checkbusy(); //检查忙标志位
- D_port=a;
- RS=1;
- RW=0;
- EN=1; //写数据各控制位的值既对应的时序
- _nop_();
- _nop_();
- _nop_(); //发送数据,此处是发送到P0口,程序前已经定义
- EN=0;
- }
- /*液晶***************写指令到液晶***************************/
- C_write(uchar a)
- {
- Checkbusy(); //检查忙标志位
- D_port=a;
- RS=0;
- RW=0;
- EN=1; //写指令各控制位的值既对应的时序
-
- _nop_();
- _nop_();
- _nop_(); //发送指令,此处是发送到P0口,程序前已经定义
- EN=0;
- }
- /*液晶**************液晶初始化******************************/
- Initial()
- {
- D_port=0;
- delay(20);
- C_write(0x38);
- delay(10);
- C_write(0x38);
- delay(10);
- C_write(0x38);
- delay(10);
- Checkbusy();
- C_write(0x38);
- Checkbusy();
- C_write(0x08); //关闭显示
- Checkbusy();
- C_write(0x01); //清屏
- Checkbusy();
- C_write(0x06); //显示光标右移设置
- Checkbusy();
- C_write(0x0c); //显示开,光标不显示,不闪烁
- delay(5);
- } //根据1602初始化的指令顺序来初始化LCD,相关初始化步骤可查阅相关资料
- /*液晶**************设定显示位置函数************************/
- setpos(uchar posx,uchar posy)
- {
- posx=posx&0xf; //将显示在第几位置转为二十六进制,每行总共16个位置
- posy=posy&0x1; //设置显示在第几行
- C_write(posx|posy*0x40+0x80); //设置位置命令最高位必须为一,所以要加0x80
- }
- /*液晶**************显示一个字符子程序**********************/
- displaychar(uchar x,uchar y,uchar a)
- {
- Checkbusy(); //检查忙标志位
- setpos(x,y); //设置显示位置
- D_write(a); //将要显示的数据写到液晶
- }
- /*液晶**************显示一串字符串**************************/
- displaystring(uchar x,uchar y,unsigned char code *string)
- {
- uchar length=0; //定义一个字符串长度
- Checkbusy();
- while(string[length]!='\0') //字符串是以'\0'结束的,因此只要每结束就显示下一字符
- {
- displaychar(x,y,string[length++]); //显示一个字符子程序
- x++; //液晶显示的位置+1
- }
- }
- /*液晶**************显示个数**************************/
- void lcd_byte(unsigned char x, unsigned char y ,unsigned int byte_data) //以十进制的方式显示一个字符变量
- {
- unsigned int temp_data;
- temp_data=byte_data/10000; //求万位数
- displaychar(x+0,y,temp_data+48); //转化为ASCII值再显示
- temp_data=byte_data % 10000 /1000; //求千位数
- displaychar(x+1,y,temp_data+48); //转化为ASCII值再显示
-
- temp_data=byte_data%1000/100; //求百位数
- displaychar(x+2,y,temp_data+48); //转化为ASCII值再显示
-
- temp_data=byte_data%100/10; //求十位数
- displaychar(x+3,y,temp_data+48); //转化为ASCII值再显示
-
- temp_data=byte_data%10; //求个位数
- displaychar(x+4,y,temp_data+48); //转化为ASCII再再显示
- }
- void my_t0(void) interrupt 1 //定时器0中断用于固定时间对输入待测电压进行积分
- {
- TR0 = 0; //T0中断关
- P34=1; //选择-2.5V基准
- TH0 = 0;
- TL0 = 0;
- //lo=lo+1;
- //TMOD=TMOD | 0x8;
- //TF0 = 0; //清除T0中断标志
- TR0 = 1; //T0中断开
- EX0 = 1; //INT0中断开
- }
- void my_int0(void) interrupt 0 //外部中断 用于反积分过程结束检测
- {
- TR0 = 0; //T0中断关
- TF0 = 0; //清除T0中断标志
- EX0 = 0; //INT0中断关
- ss = TH0 * 256 + TL0;
- P34=1; //选择-2.5V基准
- // P35=1; //选择放电
- TH0 = 0;
- TL0 = 0;
- kl = 0;
- }
- main()
- {
- Initial();
- P34=1; //选择-2.5V基准
- //P35=1; //选择放电
- displaystring( 0, 0, love);
- delay(500);
- displaystring( 0, 0, no);
- displaystring( 0, 1, tvref);
- EA = 1; //中断开
- ET0 = 1; //定时计数0中断开
- IP = 1; //定时0中断最高优先级 =2
- TMOD = 1; //定时0模式1 2个16位定时/计数器
- TCON=0x00; //INT0负边缘触发或低电平触发在此好象作用相同
- displaystring( 0, 0, tin);
- while(1)
- {
- if(kl==0)
- {
- P34=1; //选择-2.5V基准
- //P35=1; //选择放电
- delay(26);
- TMOD = 1;
- TH0 = 0x63;
- TL0 = 0xC0;
- //loo=loo+1;
- P34=0; //选择输入电压基准
- //P35=0; //选择测量
- kl = 1;
- TR0 = 1; //定时计数0起动
- TF0 = 0; //清除T0中断标志
- }
- delay(500);
- //lo=ss*0.0773;
- loo=ss-lo;
- if(loo>32767)
- {loo=65535-loo;}
- lo=ss;
- lcd_byte(5,0,ss);
- lcd_byte(5,1,loo);
- //lcd_byte(11,1,loo);
- }
- }
复制代码
|
评分
-
查看全部评分
|