三杯式风速传感器实验报告 一、实验目的
1.掌握三杯式风速传感器的工作原理; 2.将三杯式风速传感器测得的风速(风由风扇提供)实时显示在液晶和上位机上; 3.进一步掌握1602液晶的使用以及串口通讯; 4.规范C的书写格式。 二、实验原理
三杯式风速传感器有一个测速码盘,当码盘转动并不断地通过三杯式风速传感器内部的光电传感器后,就会产生脉冲信号,脉冲信号触发单片机产生外部中断0,外部中断0对脉冲次数进行计数,定时器0中断设定1s的时间,并获取1s内的脉冲次数,然后通过公式:(脉冲次数*7)/80.0+0.1(注意:此处的80.0不能写成80,否则将会丢失风速的小数位,因为除以80得到的是整数)就可以计算出风速,然后就可以通过单片机将风速显示在液晶和上位机上了。
三、实验步骤
1.查阅三杯式风速传感器的相关资料,掌握其测速原理;
2.测三杯式风速传感器的脉冲次数并显示在数码管上;
3.将风速测出并显示在1602液晶上;
4.将风速测出并显示在1602液晶和上位机上。
5.观察实验现象,总结。
四、实验结果
1602液晶和上位机均能实时显示三杯式风速传感器测得的风速,且显示一致,风速精确到了小数点后两位。
五、实验总结
这次实验刚开始测脉冲次数的时候就遇到了挫折,原因是按照文档上的接法,将红色线和黑色线接反了,废了一番波折将传感器拆开后才把线接对,将脉冲次数测出来。这件事原因还是在我,不敢挑战文档的权威性,当时要是把红黑线的接法对调一下就不会有后面的麻烦事了(不过这也与红色线是重新接上去的有关系,我一直怀疑它接触不良)。脉冲次数测出来后液晶显示很快也顺利地实现了,不过到液晶与上位机同时显示的时候,出现了问题,究其原因是我把显示写在了串口中断里,但是没有加标志位,串口中断接收不到脉冲次数,所以风速一直显示是0,不过在加了标志位后,这个问题顺利解决了。另外将显示写在主程序里通过查询方式也实现了液晶和上位机的显示。至于为什么没有同时将脉冲次数显示在数码管上,这是因为数码管的位选端P2口和液晶要用到的P2^0,P2^1和P2^2口发生了冲突(这里要吐槽一下,这个单片机没有锁存器)。
附录1 数码管显示风速传感器脉冲次数的程序 单片机源程序如下:
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- uchar i;
- uint f,num;
- uchar code table[]=
- {
- 0x28,0x7e,0xa2,0x62,
- 0x74,0x61,0x21,0x7a,
- 0x20,0x60
- };//数码表(0-9)
- void delay(uint z)//1ms延时函数
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- void display()
- {
- uchar wan,qian,bai,shi,ge;
- wan=num/10000;//获取计数值的万位
- qian=num%10000/1000;//获取计数值的千位
- bai=num%10000%1000/100;//获取计数值的百位
- shi=num%10000%1000%100/10;//获取计数值的十位
- ge=num%10000%1000%100%10;//获取计数值的个位
- P2=0xfe;
- P0=table[wan];
- delay(2);
- P2=0xfd;
- P0=table[qian];
- delay(2);
- P2=0xfb;
- P0=table[bai];
- delay(2);
- P2=0xf7;
- P0=table[shi];
- delay(2);
- P2=0xef;
- P0=table[ge];
- delay(2);
- }
- void init()//初始化子程序
- {
- TMOD=0x01;//设置定时器0为工作方式1
- TH0=(65536-50000)/256; //定时器0装初值
- TL0=(65536-50000)%256; //同上
- IT0=1;//外部中断0为跳变沿触发方式
- EA=1;//打开总中断
- EX0=1;//打开外部中断0
- ET0=1;//打开定时器0中断
- TR0=1;//打开定时器0
- }
- void main()
- {
- init();
- while(1)
- {
- display();
- }
- }
- void exter0() interrupt 0 //外部中断0子程序
- {
- f++; //脉冲计数
- }
- void timer0() interrupt 1 //定时器0中断子程序
- {
- TH0=(65536-50000)/256; //定时器0重装初值
- TL0=(65536-50000)%256; //同上
- i++;
- if(i==20) //定时器0计时1s
- {
- num=f;
- i=0;
- f=0;
- }
- }
复制代码
附录2 液晶上显示风速的程序
附录3 液晶和上位机同时显示风速的程序
单片机源程序如下:
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- uchar i;
- //uchar flag;//标志位
- uint a,b,c,f,num;
- uint ws_i;
- double ws_d,ws_d1;//定义风速的数据类型为双精度型
- uchar code table1[]=" speed: ";
- uchar code table2[]=" . m/s ";
- uchar code table3[]="speed:";
- sbit RS=P2^0;
- sbit RW=P2^1;
- sbit EN=P2^2;
- void delay(uint z)//1ms延时函数
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- void write_com(uchar com) //液晶写命令子程序
- {
- RS=0;//写入命令
- RW=0;//读写控制端设置为写模式
- P0=com;//将命令送给P0口
- delay(10);
- EN=1;//将命令送给液晶显示屏
- delay(10);
- EN=0;
- }
- void write_data(uchar dat)//液晶写数据子程序
- {
- RS=1;//写入数据
- RW=0;
- P0=dat;//将数据送给P0口
- delay(10);
- EN=1;//将数据送给液晶显示屏
- delay(10);
- EN=0;
- }
- void init()//初始化子程序
- {
- write_com(0x38);//设置16*2显示,5*7点阵,8位数据接口
- write_com(0x01);//清屏
- write_com(0x06);//写一个字符后,地址指针加1
- write_com(0x0C);//设置开显示,不显示光标
- write_com(0x80);//液晶显示屏从第一行的第一个位置开始写入字符
- for(a=0;a<16;a++)//液晶显示屏第一行写入" speed: "
- {
- write_data(table1[a]);
- delay(1);
- }
- write_com(0x80+0x40);//液晶显示屏从第二行的第一个位置开始写入字符
- for(b=0;b<16;b++)//液晶显示屏第二行写入" . m/s "
- {
- write_data(table2[b]);
- delay(1);
- }
- TMOD=0x21;//设置定时器0为工作方式1,定时器1为工作方式2
- TH0=(65536-50000)/256; //定时器0装初值
- TL0=(65536-50000)%256; //同上
- TH1=0xf3;//设置波特率为2400
- TL1=0xf3;//同上
- TR1=1;//打开定时器1
- TR0=1;//打开定时器0
- IT0=1;//外部中断0为跳变沿触发方式
- REN=1;//允许串口接收数据
- SM0=0;//设置串口的工作方式为1
- SM1=1;//同上
- EX0=1;//打开外部中断0
- ET0=1;//打开定时器0中断
- EA=1;//打开总中断
- // ES=1;//打开串口中断
- }
- void main()
- {
- uchar shi,ge,sf,bf,shi_1,ge_1,sf_1,bf_1;
- init();
- delay(1);
- while(1)
- {
- ws_i=(int)(ws_d1);//将双精度类型的风速强制转化为整型
- shi_1=ws_i/1000;//将风速的十位分离出来;
- write_com(0x80+0x40+7);
- write_data(0x30+shi_1);//液晶第二行第8个位置写入风速的十位数
- ge_1=ws_i%1000/100;//将风速的个位分离出来
- write_com(0x80+0x40+8);
- write_data(0x30+ge_1);//液晶第二行第9个位置写入风速的个位数
- sf_1=ws_i%1000%100/10;//将风速的十分位分离出来
- write_com(0x80+0x40+10);
- write_data(0x30+sf_1);//液晶第二行第11个位置写入风速的十分位
- bf_1=ws_i%1000%100%10;//将风速的百分位分离出来
- write_com(0x80+0x40+11);
- write_data(0x30+bf_1);//液晶第二行第12个位置写入风速的十分位
- delay(500);
- TI=0;//允许发送
- for(c=0;c<6;c++) //上位机接收字符串“speed:”
- {
- TI=0;//允许发送
- SBUF=table3[c];
- while(!TI);//等待发送
- delay(5);
- }
- delay(5);
- shi=ws_i/1000;
- ge=ws_i%1000/100;
- sf=ws_i%1000%100/10;
- bf=ws_i%1000%100%10;
- SBUF=0x30+shi;//上位机显示风速的十位
- delay(5);
- SBUF=0x30+ge;//上位机显示风速的个位
- delay(10);
- SBUF='.';
- delay(10);
- SBUF=0x30+sf;//上位机显示风速的十分位
- delay(10);
- SBUF=0x30+bf;//上位机显示风速的百分位
- delay(10);
- SBUF='m';
- delay(10);
- SBUF='/';
- delay(10);
- SBUF='s';
- delay(10);
- SBUF='\n';//换行
- delay(1000);
- while(!TI);//等待数据传送
- }
- }
- void exter0() interrupt 0 //外部中断0子程序
- {
- f++; //脉冲计数
- }
- void timer0() interrupt 1 //定时器0中断子程序
- {
- TH0=(65536-50000)/256; //定时器0重装初值
- TL0=(65536-50000)%256; //同上
- i++;
- if(i==20) //定时器0计时1s
- {
- num=f;
- ws_d=(num*7)/80.0+0.1;//80后面的.0不能少,少的话(num*7)/80只能得到整数
- if(ws_d>0.1) //风速大于0
- ws_d1=ws_d*100;//为了使风速显示到小数点后两位
- else
- ws_d1=0; //风速为0
- i=0;
- f=0;
- // flag=1;
- }
- }
- /*void ser() interrupt 4 //串口中断函数
- {
- uchar shi,ge,sf,bf,shi_1,ge_1,sf_1,bf_1;
- if(flag==1)
- {
- ws_i=(int)(ws_d1);//将双精度类型的风速强制转化为整型
- shi_1=ws_i/1000;
- write_com(0x80+0x40+7);
- write_data(0x30+shi_1);
- ge_1=ws_i%1000/100;
- write_com(0x80+0x40+8);
- write_data(0x30+ge_1);
- sf_1=ws_i%1000%100/10;
- write_com(0x80+0x40+10);
- write_data(0x30+sf_1);
- bf_1=ws_i%1000%100%10;
- write_com(0x80+0x40+11);
- write_data(0x30+bf_1);
- delay(500);
- TI=0;//允许发送
- for(c=0;c<6;c++) //上位机接收字符串“speed:”
- {
- TI=0;//允许发送
- SBUF=table3[c];
- while(!TI);//等待发送
- delay(5);
- }
- delay(5);
- shi=ws_i/1000;
- ge=ws_i%1000/100;
- sf=ws_i%1000%100/10;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
三杯式风速传感器实验报告.docx
(23.44 KB, 下载次数: 169)
|