使用51单片机设计软件钟涡流称重计光电转速计.docx
《使用51单片机设计软件钟涡流称重计光电转速计.docx》由会员分享,可在线阅读,更多相关《使用51单片机设计软件钟涡流称重计光电转速计.docx(22页珍藏版)》请在冰豆网上搜索。
![使用51单片机设计软件钟涡流称重计光电转速计.docx](https://file1.bdocx.com/fileroot1/2023-1/3/8cc5e972-ed13-479a-ab01-7ce69b66d77d/8cc5e972-ed13-479a-ab01-7ce69b66d77d1.gif)
使用51单片机设计软件钟涡流称重计光电转速计
课程设计报告
课题一使用51单片机设计软件钟
一、实验目的:
1.掌握元器件及芯片的焊接与调试;
2.了解基于51单片机的软件钟的工作原理;
3.会用C语言编写时钟函数,复习用switch语句和do-while语句、for语句实现循环的方法;
4.会使用MEDWIN编译调试程序,并生成HEX,通过数据线下载到电路板上;
5.根据自己焊接的板子在程序中设置按键控制时钟的调整。
二、算法原理:
所谓软件钟就是利用51单片机制作一个电子时钟。
其算法就是以单片机的时钟为基准,记录单片机时钟脉冲的数量,当数量足够多(如脉冲为每秒6Mhz,那么记录6M个脉冲所需时间即为1秒)就可以将显示部分的“秒”位加一。
加到60以后进位为“分”,”秒“位清零以后继续记录。
当“分”累加为60以后进位为”时“,”分“位清零以后继续记录,当”时“位为24以后,”时“位清零并继续记录。
三、硬件原理:
显示电路:
单片机外围电路(复位电路,时钟电路):
按键控制电路:
数码管驱动电路:
四、实现功能要求:
使用中需要对时钟进行调整。
在调整的时候需要一个按键来进入调整状态。
进入调整状态以后需要一个按键来向左移动调整位置,一个按键来向右移动调整位置,一个按键来增加所选位置的数值,一个按键来减小所选位置的数值。
调整完成以后还需要一个按键来退出调整位置,恢复时钟的计数运转。
以上所需按键可以根据需要合并。
在调整中另外一个需要注意的问题是如何显示目前所选定调整的位置(如秒的个位或者十位,分的个位或者十位等)。
可以采用是否显示数位右下的小数点或者所选需调整位是否闪烁来让操作者明确目前自己所选定的需要调整的数位。
五、设计内容:
(1)硬件焊接:
按照电路图焊接好各个元器件和芯片插座,注意焊接时焊点要尽量光滑,与管脚接触良好,元件的管脚弯曲处要尽量光滑,有需要区分正负极的元器件焊接时要注意不要焊反。
焊接完后将元件多余的管脚用尖嘴钳剪掉,以免形成短路。
(2)软件设计:
1.子程序设计:
A.单片机初始化程序
a)定时器T0中断服务程序
B.显示子程序
C.时钟运行计数子程序
D.时间数据送显示缓冲区子程序
E.设置时间子程序
F.时钟调整子程序
G.键值读入子程序
H.延时子程序
2.实验程序清单:
#pragmadboe
#include
#include
#include
#include
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
#defineulongunsignedlong
voiddisplay(void);
voidinitsiu(void);
voiddelay(void);
voidsztz(void);
voidjssz(void);
voidsetsz(void);
voidtzszw(ucharzj);
ucharinkey(void);
ucharsec,min,hour;
uchardisdat[6];
ucharcodetab[]={0x3f,0x6,0x5b,0x4f,0x66,0x6d,0x7d,0x7,0x7f,0x6f};
uintcount;
ucharset_state,xsd;
sbitzsd=P1^0;
main()
{
uchari;
for(i=0;i<2;i++)
{
disdat[i]=0;//将显示缓存清零
}
initsiu();//初始化单片机
set_state=0;
do
{
i=inkey();//设置时钟
if(i==0x70)
setsz();
jssz();
display();//显示
if((sec&0x01))//指示灯闪烁
zsd=1;
else
zsd=0;
}
while
(1);
}
voiddisplay(void)//六位数码管显示程序,disdat[]是要显示的内容(是0~9的数字),xsd是在那一位显示小数点
{
uchari,disa,disb,disc;
disb=0x00;//显示第n位
for(i=0;i<6;i++)//共显示6个数据
{
disa=disdat[i];//显示数据
if(disa<10)
{
P2=disb;
disc=tab[disa];//显示段码
if(set_state==0)//显示时钟
{
if((i==1)||(i==3))
disc=disc|0x80;//增加小数点显示
}
else//设置时显示
{
if(xsd==i)
disc=disc|0x80;//增加小数点显示
}
P0=disc;//送显示
delay();//延时
P0=0x0;
disb++;//下一个要显示的位置
}
}
P2=0xff;
}
voidsetsz(void)//设置时间
{
uchari,k;
set_state=1;//改变显示状态
xsd=0;//设置位置
TR0=0;//停止时钟运行
jssz();//将现在的结果放到数组disdat[]
do
{
display();//显示
i=inkey();//读键
switch(i)
{
case0x70:
//退出设置,1号键
k=0xff;
break;
case0xb0:
//改变设置位置,每按下一次右移一个,2号键
k=0;
xsd++;
if(xsd==6)
xsd=0;
break;
break;
case0xd0:
//加1,3号键
k=0;
tzszw(0);
break;
case0xe0:
//进入设置,减1,4号键
k=0;
tzszw
(1);
break;
default:
k=0;
break;
}
}
while(k!
=0xff);
set_state=0;//恢复显示时钟
TR0=1;//时钟运行
_nop_();
}
voidtzszw(ucharzj)
{
ucharj;
switch(xsd)
{
case0:
//时高位调整
if(zj==0)
{
disdat[0]++;
if(disdat[0]>2)
disdat[0]=0;
}
else
{
if(disdat[0]==0)
disdat[0]=2;
else
disdat[0]--;
}
hour=disdat[0]*10+disdat[1];
break;
case1:
//时低位调整
if(zj==0)
{
disdat[1]++;
if(disdat[1]>9)
disdat[1]=0;
}
else
{
if(disdat[0]!
=2&&disdat[1]==0)
disdat[1]=9;
//else
//disdat[1]--;
elseif(disdat[0]==2&&disdat[1]==0)
disdat[1]=3;
else
disdat[1]--;
}
if(disdat[0]==2&&disdat[1]>3)
disdat[1]=0;
hour=disdat[0]*10+disdat[1];
break;
case2:
//分高位调整
if(zj==0)
{
disdat[2]++;
if(disdat[2]>5)
disdat[2]=0;
}
else
{
if(disdat[2]==0)
disdat[2]=5;
else
disdat[2]--;
}
min=disdat[2]*10+disdat[3];
break;
case3:
//分低位调整
if(zj==0)
{
disdat[3]++;
if(disdat[3]>9)
disdat[3]=0;
}
else
{
if(disdat[3]==0)
disdat[3]=9;
else
disdat[3]--;
}
min=disdat[2]*10+disdat[3];
break;
case4:
//秒高位调整
if(zj==0)
{
disdat[4]++;
if(disdat[4]>5)
disdat[4]=0;
}
else
{
if(disdat[4]==0)
disdat[4]=5;
else
disdat[4]--;
}
sec=disdat[4]*10+disdat[5];
break;
case5:
//秒低位调整
if(zj==0)
{
disdat[5]++;
if(disdat[5]>9)
disdat[5]=0;
}
else
{
if(disdat[5]==0)
disdat[5]=9;
else
disdat[5]--;
}
sec=disdat[4]*10+disdat[5];
break;
default:
break;
}
}
voiddelay(void)//延时程序
{
uchari;
for(i=0;i<201;i++)
_nop_();
}
voidjssz(void)//将时钟分离送到显示缓存
{
disdat[0]=hour/10;
disdat[1]=hour%10;
disdat[2]=min/10;
disdat[3]=min%10;
disdat[4]=sec/10;
disdat[5]=sec%10;
}
voidsztz(void)//时钟运行计数,每秒运行一次
{
sec++;
if(sec==60)
{
sec=0;
min++;
if(min==60)
{
min=0;
hour++;
if(hour==24)
{
hour=0;
}
}
}
}
voidinitsiu(void)//初始化单片机
{
TMOD=0x11;//定时器1:
gate=0->TR1=1开始计数,C/T=0->对内部计数,模式1->16位计数
TH0=0X3C;
TL0=0XAF;
ET0=1;//打开定时器0中断
ET1=0;//关闭定时器1中断
TR0=1;//打开计数器0
TR1=0;//关闭计数器1
EA=1;//总中断允许
}
voidinttime0(void)interrupt1using1
{
TH0=0X3C;//50ms中断一次,20次为一秒,调整时间一次
TL0=0XAF;
count++;
if(count==20)
{
count=0;
sztz();
}
}
ucharinkey(void)
{
ucharjjj,keydat;
P2=0xff;//P2准备读入
keydat=P2;//读入键值
keydat=keydat&0xf0;//找出四个键的值
if(keydat!
=0xf0)//有键输入
{
_nop_();
_nop_();
jjj=P2;//再读,去抖动
jjj=jjj&0xf0;
if(jjj!
=keydat)
keydat=0xf0;
do
{
jjj=P2;
jjj=jjj&0xf0;
}//等待键松手
while(jjj!
=0xf0);
}
return(keydat);
}
六、测试结果分析:
经过medwin对程序的调试无误后,将hex文件下载到电路板上,可正常显示时钟,并且可以通过按键对时钟进行调整。
针对我的程序,按键实现功能依次为:
一号键:
进入和退出设置,当时钟运行时按下可进入设置;当设置完成后按下可恢复时钟显示。
二号键:
右移一位。
在设置状态每次按下就右移一位。
三号键:
加一
四号键:
减一
此外还设有一个复位键,按下后时钟归零。
七、遇到的问题与解决方法:
问题一:
如何编写时钟函数?
解决方法:
每60秒进一位,即一分钟;每60分钟进一位,即一小时;在函数体内用循环,在主函数中调用。
编写时注意当时高位为2时,时地位最高到3,且分高位和秒高位最高为5。
问题二:
如何设置时间?
解决方法:
改变现实状态,将现在的结果放到数组中去,读取按键,设置按键对时钟进行调整,编写SWITCH语句控制按键的选择。
问题三:
如何解决时间变化太快?
解决方法:
使用一个延时函数来缓冲每一秒变化时间。
八、实验总结:
通过本次实验,我对时钟函数的编写有了更深一步的掌握,复习了C语言的编程。
并且可以通过自己焊接的板子来调试时钟程序,对今后的学习与研究有了很大的帮助
课题二使用51单片机设计涡流称重计
一、实验目的
1.了解电涡流传感器用于称重的原理与方法;
2.熟悉ADC0832的器件手册;
3.了解基于51单片机的涡流称重计的工作原理;
4.会用C语言编写时钟函数,复习用switch语句和do-while语句、for语句实现循环的方法;
5.会使用MEDWIN编译调试程序,并生成HEX,通过数据线下载到电路板上;
二、算法原理
本项设计中用电位器的中间抽头所输出的电压模拟采集的重量数据,单片机经ADC0832的通道0输入该电压信号,并将其转换为数字信息送6位共阳8段LED显示。
ADC0832的芯片接口说明:
·CS_片选使能,低电平芯片使能。
·CH0模拟输入通道0,或作为IN+/-使用。
·CH1模拟输入通道1,或作为IN+/-使用。
·GND芯片参考0电位(地)。
·DI数据信号输入,选择通道控制。
·DO数据信号输出,转换数据输出。
·CLK芯片时钟输入。
·Vcc/REF电源输入及参考电压输入(复用)
当此2位数据为“1”、“0”时,只对CH0进行单通道转换。
当2位数据为“1”、“1”时,只对CH1进行单通道转换。
当2位数据为“0”、“0”时,将CH0作为正输入端IN+,CH1作为负输入端IN-进行输入。
当2位数据为“0”、“1”时,将CH0作为负输入端IN-,CH1作为正输入端IN+进行输入。
到第3个脉冲的下沉之后DI端的输入电平就失去输入作用,此后DO/DI端则开始利用数据输出DO进行转换数据的读取。
从第4个脉冲下沉开始由DO端输出转换数据最高位DATA7,随后每一个脉冲下沉DO端输出下一位数据。
直到第11个脉冲时发出最低位数据DATA0,一个字节的数据输出完成。
也正是从此位开始输出下一个相反字节的数据,即从第11个字节的下沉输出DATD0。
随后输出8位数据,到第19个脉冲时数据输出完成,也标志着一次A/D转换的结束。
最后将CS置高电平禁用芯片,直接将转换后的数据进行处理就可以了。
三、实现功能要求:
使用时用5V的电压来表示200g的重量,使用通道O来输入模拟量。
四、设计内容:
(1)硬件焊接:
根据ADC0832的接口说明焊接导线
(2)软件设计:
1.子程序设计:
A.单片机的初始化程序
B.显示子程序
C.3.0832的转换子程序
D.采样数据换算压力子程序
E.将压力值转换为十进制数,并将每位送入显示缓冲区子程序
2.实验程序清单:
#include
#include"intrins.h"
#defineuintunsignedint
#defineucharunsignedchar
//ADC0832的引脚
sbitADCS=P3^5;//ADC0832chipseclect
sbitADCLK=P3^4;//ADC0832clocksignal
sbitADDI=P3^3;//ADC0832kin
sbitADDO=P3^3;//ADC0832kout
uchardispbuf[6];
ucharcodetab[]={0x3f,0x6,0x5b,0x4f,0x66,0x6d,0x7d,0x7,0x7f,0x6f};
ucharcodetab1[]={0x79,0x3f,0x77};
uinttemp;
uchargetdata;//获取ADC转换回来的值
uchare=0;
voiddelay(void)//延时程序
{
uchari;
for(i=0;i<201;i++)
_nop_();
}
voiddisplay(void)//六位数码管显示程序,disdat[]是要显示的内容(是0~9的数字),xsd是在那一位显示小数点
{
uchari,disa,disb,disc;
disb=0x00;//显示第n位
for(i=0;i<6;i++)//共显示3个数据
{
if(e==0)
disa=dispbuf[i];//显示数据
else
disa=i-3;
if(disa<10&&e==0)
{
P2=disb;
disc=tab[disa];//显示段码
if(i==0||i==5)
disc=disc|0x80;//增加小数点显示
P0=disc;//送显示
delay();//延时
P0=0x0;
disb++;//下一个要显示的位置
}
else//(e==1)
{
P2=disb;
disc=tab1[disa];//显示段码
P0=disc;//送显示
delay();//延时
P0=0x0;
disb++;//下一个要显示的位置
}
}
P2=0xff;
}
unsignedintAdc0832(unsignedcharchannel)//AD转换,返回结果
{
uchari=0;
ucharj;
uintdat=0;
ucharndat=0;
if(channel==0)channel=2;
if(channel==1)channel=3;
ADDI=1;
_nop_();
_nop_();
ADCS=0;//拉低CS端
_nop_();
_nop_();
ADCLK=1;//拉高CLK端
_nop_();
_nop_();
ADCLK=0;//拉低CLK端,形成下降沿1
_nop_();
_nop_();
ADCLK=1;//拉高CLK端
ADDI=channel&0x1;
_nop_();
_nop_();
ADCLK=0;//拉低CLK端,形成下降沿2
_nop_();
_nop_();
ADCLK=1;//拉高CLK端
ADDI=(channel>>1)&0x1;
_nop_();
_nop_();
ADCLK=0;//拉低CLK端,形成下降沿3
ADDI=1;//控制命令结束
_nop_();
_nop_();
dat=0;
for(i=0;i<8;i++)
{
dat|=ADDO;//收数据
ADCLK=1;
_nop_();
_nop_();
ADCLK=0;//形成一次时钟脉冲
_nop_();
_nop_();
dat<<=1;
if(i==7)dat|=ADDO;
}
for(i=0;i<8;i++)
{
j=0;
j=j|ADDO;//收数据
ADCLK=1;
_nop_();
_nop_();
ADCLK=0;//形成一次时钟脉冲
_nop_();
_nop_();
j=j<<7;
ndat=ndat|j;
if(i<7)ndat>>=1;
}
ADCS=1;//拉低CS端
ADCLK=0;//拉低CLK端
ADDO=1;//拉高数据端,回到初始状态
dat<<=8;
dat|=ndat;
return(dat);//returnadk
}
voidmain(void)
{
//doublek;
unsignedintw;
while
(1)
{
getdata=Adc0832(0);
temp=getdata*1.0/255*500;//电压值转换,5V做为参考电压,分成256份。
dispbuf[2]=temp%10;//个位
dispbuf[1]=temp/10%10;//十位
dispbuf[0]=temp/100;//百位
w=temp*1.0/2.5;
if(w<=199)
{
e=0;
dispbuf[5]=w%10;//个位
dispbuf[4]=w/1