资源描述
工程测控设计报告
班级:电子121班 姓名:马明杰 学号:122121
分组序号:A—15 同组人:焦亚男 122100
1、课程设计目及规定
(1)、课程设计目
1、掌握元器件及芯片焊接与调试;
2、 理解基于51单片机软件钟工作原理;
3、 会用C语言编写时钟函数,复习用switch语句和do-while语句、for语句实现循环办法;
4、 会使用MEDWIN编译调试程序,并生成HEX,通过数据线下载到电路板上;
5、 依照自己焊接板子在程序中设立按键控制时钟调节。
(2)、课程设计规定
①软件时钟设计规定:
使用中需要对时钟进行调节。在调节时候需要一种按键来进入调节状态。进入调节状态后来需要一种按键来向左移动调节位置,一种按键来向右移动调节位置,一种按键来增长所选位置数值,一种按键来减小所选位置数值。调节完毕后来还需要一种按键来 退出调节位置,恢复时钟计数运转。以上所需按键可以依照需要合并。
在调节中此外一种需要注意问题是如何显示当前所选定调节位置(如秒个位或者十位,分个位或者十位等)。可以采用与否显示数位右下小数点或者所选需调节位与否闪烁来让操作者明确当前自己所选定需要调节数位。
本小组最后实现用第一种按键进入调节状态,并进行循环左移,用第二个按键实当前软件时钟以及涡流称重计两种模式之间切换,第三个按键实现时钟设立时加法,第四个按键退出调节状态,并采用显示数位右下小数点来显示当前要调节位。
②涡流称重计设计规定:
使用时用2V电压来表达200g重量,使用通道O来输入模仿量。用按键2实现涡流称重计在两个不同函数之间切换。
③光电转速计设计规定:
本实验规定编写程序实现当板子上P3.5引脚接光电转速计时,在数码管上后三位显示转速,单位为转/分,前三位显示脉冲频率,单位是脉冲/秒。
2、硬件电路原理框图
(1)、软件时钟硬件电路原理图
①显示电路
②电源及功能批示电路 ③单片机外围电路(复位电路、时钟电路)
④按键控制电路 ⑤数码管驱动电路
4个按键地址从左至右依次为:0xe0、0xd0、0xb0、0xff
(2)、涡流称重计原理图
3、软件设计
(1)、软件时钟软件设计
①算法原理概述
所谓软件时钟就是运用51单片机制作一种电子时钟。其算法就是以单片机时钟为基准,记录单片机时钟脉冲数量,当数量足够多(如脉冲为每秒12Mhz,那么记录12M个脉冲所需时间即为1秒)就可以将显示某些“秒”位加一。加到60后来进位为“分”,“秒”位清零后来继续记录。当“分”累加为60后来进位为“时”,“分”位清零后来继续记录,当“时”位为24后来,“时”位清零并继续记录。
②程序流程图
见图3-1
③源程序
见本报告最后附加页文档。
(2)、涡流称重计软件设计
①算法原理概述
本项设计中用电位器中间抽头所输出电压模仿采集重量数据,单片机经ADC0832通道0输入该电压信号,并将其转换为数字信息送6位共阳8段LED显示。
②程序流程图
见图3-2
③源程序
见本报告最后附加页文档。
(3)、光电转速计软件设计
①算法原理概述
数字频率计是直接用十进制数字来显示被测信号频率一种测量装置。它不但可以测量正弦波,方波,三角波和尖脉冲信号频率,并且还可以测量她们周期。数字频率计在测量其她物理量如转速、振荡频率等方面获得广泛应用。
所谓频率,就是周期性信号在单位时间(1s)里变化次数。若在一定期间间隔T内测得这个周期性信号重复变化次数N,则其频率可表达为
f =N/T,普通为简朴起见咱们普通选取测量间隔为1秒(即T=1),这样1秒内信号重复变化次数就是信号频率
1秒计数周期要采用单片机自身时钟脉冲来计算,在1秒时间内,记录外部脉冲数量就是外部信号频率。因此一共需要2个计数过程,一种是记录单片机自身时钟脉冲个数以精确划定1秒时间,一种是记录外部脉冲个数,以精确记录外部信号频率。
由于显示数码管数量有限,因此在编写程序时要注意采用小数点所在位置来表达频率单位
②程序流程图
见图3-3
③源程序
见本报告最后附加页文档。
图3-3
图3-2
图3-1
开始
程序初始化
程序运营
显示转速与频率
输入频率
开始
程序初始化
选取称重函数
函数1
函数2
程序运营
显示重量
4、检测装置用法
(1)、软件时钟
按按键1进入设立状态并进行移位,按键2减,按键3加,按键4退出,调节时间为23:59:57,若三秒后变为00:00:00,则装置没有问题。
(2)、涡流称重计
按按键2切换测量函数,测量值与相应函数线理论值进行比较,若误差在容许范畴内,则装置没有问题。
(3)、光电转速计
将单片机P3.5脚接频率发生器正极,40脚接负极,调节频率发生器为方波,频率150HZ,幅值4V,看数码管显示值与否对的。然后将其接入光脉冲上并用数字示波器对脉冲频率进行测量,调节转速在1000以内,查看数码管值转速值与否对的,并与数字示波器频率值进行比较,查看大小与否相似,若均相似,则装置没有问题。
5、测试成果分析
(1)、软件时钟
本实验共设立了5个按钮,按键1设立小数点到达哪位数码管值,按键2减小设立位值,按键3增长设立位值,到达23:59:59后数据清零为00:00:00,按键1按下后进入设立状态,按键5是复位按键。
(2) 、涡流称重计
通过从电位器中调出一某些电压,并将其进行A/D转换,将模仿量转换为数字量,显示高三位数码管,
测量值显示在低三位数码管,咱们组测最高值为1.96v 199g,超过此数,后三位数码管显示“EOR”。
测试数据表格:
测试值
函数1测试成果
函数2测试成果
0.5
0.49 000
0.49 000
1.0
0.98 067
0.98 099
1.5
1.49 133
1.49 167
2.0
1.96 199
1.96 199
2.5
2.49 349
2.49 349
(3)、光电转速计
STC89C52芯片P3.5引脚实现是计数功能,将P3.5引脚转速测量仪正极接,芯片40引脚与转速测量仪负极接,板子通电后,即为显示频率值。
6、遇到问题与解决办法。
(1) 遇到问题:焊接完毕后连接电源,状态批示灯不亮;
解决办法:运用万用表测试焊接板各点,检测电路问题。经查状态批示灯所用二极管损坏,更换后,状态批示灯正常工作。
(2)遇到问题:下载电路测试程序(数码管显示程序)后,按下按键K1第一位数码管不亮;
解决办法:经检查使用数码管应为共阴数码管,而实际使用数码管为共阳数码管,更换数码管之后问题解决。
(3) 遇到问题:涡流称重中单片机测量电压,始终是万用表测量值1/2;
解决办法:认真检查AD转换中数字量读取程序,并和所给ADC0832时序图相比较,发当前读取数据时少读了一位数据,因而导致所得数字量向左少移一位,更改程序后问题解决。
(4) 遇到问题:在涡流称重状态下,数码管显示不稳定,特别是电压和重量最低位跳变迅速引起串红,读数困难。
解决办法:经教师指引,将显示缓存赋值改为每0.5秒一次,这样数码管显示至少需要0.5秒才会变化一次,从而消除了跳变太快导致读数困难。
1. 焊接、设计、调试心得体会。
通过本次课程设计再次熟悉并提高了自己焊接技术,巩固并加强了51单片机C语言程序设计能力,深切体会到了51单片机在开发过程中运用keil编辑软件调试程序重要性,开发过程要一步步进行,完毕一某些功能之后再进行下一功能开发,最后将程序整合到一起实现所有功能,否则排查错误会十分困难。
焊接要按一定环节进行,焊接之前先要对元件进行检查,元件能否正常工作、焊接位置与否相应等。然后将焊接模块和独立元件顺序排好依次焊接,例如一方面焊接布局紧密某些中小部件,然后再焊接较大元件。焊接要完毕一种功能模块焊接,再焊接下一种功能模块,这样也有助于加强对电路结识。
在进行软件开发时,编写流程图有助于构造化编程,使得编程思路更加清晰。编程要化整为零,将一种大功能分解成诸多子功能、子函数,这样有助于提高代码可读性和重用性。在开发调试过程中,要分别对每个函数进行调试和验证,例如显示子函数、按键子函数、时间调节子函数等,各各功能完毕之后再将她们组合,这有助于细化环节和检查错误。
通过本次完整课程设计,对系统开发流程,软件开发环节等有了清晰结识,锻炼了动手能力。但这过程中依然暴露出许多问题,例如编程还不十分规范、排查问题能力尚有待提高等。发现自己局限性就要及时进行补强,在进行理论学习同步要多多动手实践,要学以致用。在理论学习过程中不忘实践,在实践过程中深化对理论理解,这样才干达到学习真是目和效果。
附加内容1:软件时钟/**********************************************************
注:按键抬手时瞬间显示
***********************************************************/
#include <reg52.h> //定义8052特殊功能寄存器、中断
#include <absacc.h> //绝对地址函数
#include <string.h> //字符串函数
#include <stdio.h> //原则i/o函数
#include <intrins.h> //内部函数
#include <MATH.H> //数学函数
#define uint unsigned int //定义uint代替unsigned int
#define uchar unsigned char //定义uchar代替unsigned char
#define ulong unsigned long //定义ulong 代替 unsigned long
//void display(void); //六位数码管显示程序
void initsiu(void); //初始化单片机
void delay(void); //延时程序
void delay1ms(unsigned int i);
void delay500us();
uchar inkey(void); //键盘输入程序
void timeset();
void DisplaySecond(unsigned char s);
void DisplayMinute(unsigned char m);
void DisplayHour(unsigned char h);
uchar code seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //显示缓存 数码管
// 0 1 2 3 4 5 6 7 8 9
uchar int_time ;//中断次数计数变量
char second; //秒计数变量
char minute; //分钟计数变量
char hour; //小时计数变量
uchar keyscan;
char set=0;// timeset
char add=0;// timeset
char swee=0;
sbit zsd=P1^0;//LED
sbit P20=P2^0;//
sbit P21=P2^1;//
sbit P22=P2^2;//
sbit P23=P2^3;//74LS138 - CS
/**********************************************************
主程序
***********************************************************/
void main()
{
//uchar i;
initsiu(); //调用:初始化单片机
//i=inkey(); //调用:键盘输入程序
P23=0;
while(1)
{
DisplaySecond(second); //调用秒显示子程序
delay1ms(1);
DisplayMinute(minute); //调用分钟显示子程序
delay1ms(1);
DisplayHour(hour);
delay1ms(1);
keyscan=inkey(); //调用:键盘输入程序
timeset();
}
}
/**********************************************************
延时程序
***********************************************************/
void delay(void)
{
uchar i;
for (i=0;i<201;i++)
_nop_();
}
void delay1ms(unsigned int i)
{
unsigned char j;
while(i--)
{
for(j=0;j<115;j++)//延时1ms延时语句(11.0592M晶振时)
{}
}
}
void delay500us()
{
unsigned char j;
for(j=0;j<57;j++)//延时500us延时语句(11.0592M晶振时)
{}
}
/**********************************************************
初始化程序
***********************************************************/
void initsiu(void)
{
TMOD=0x11; //定期器1:gate=0->TR1=1开始计数,C/T=0->对内部计数,模式1->16位计数
TH0=(65536-50000)/256;//51计数器为加计数
TL0=(65536-50000)%256;
ET0=1; //打开定期器0中断
ET1=0; //关闭定期器1中断
TR0=1; //打开计数器0
TR1=0; //关闭计数器1
EA=1; //总中断容许
int_time=0; //中断计数变量初始化
second=0; //秒计数变量初始化
minute=30; //分钟计数变量初始化
hour=6; //小时计数变量初始化
}
/**********************************************************
键盘输入程序
1:0x70 2:0xb0 3:0xd0 4:0xe0
**********************************************************/
uchar inkey(void)
{
uchar jjj,keydat;
//P2 = 0xff; //P2准备读入
P2 |= 0xf0; //P2准备读入 高4位置1 低4位不变
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);
}
void timeset()
{
switch(keyscan)
{
case 0x70://0111 0000
ET0=1; //打开定期器0中断
TR0=1; //打开计数器0
set--;
if(set<0) set=2;
break;
case 0xb0://1011 0000
ET0=0; //关闭定期器0中断
TR0=0; //关闭计数器0
set++;
if(set>2) set=0;
break;
case 0xd0://1101 0000
add--;break;
case 0xe0://1110 0000
add++;break;
default :break;
}
switch(set)
{
case(0):
second+=add;
if(second>60) second=0;
if(second<0) second=59;
add=0;
break;
case(1):
minute+=add;
if(minute>60) minute=0;
if(minute<0) minute=59;
add=0;
break;
case(2):
hour+=add;
if(hour>24) hour=0;
if(hour<0) hour=23;
add=0;
break;
default :break;
}
}
/******************************************************************
函数功能:显示秒子程序
入口参数:s
********************************************************************/
void DisplaySecond(unsigned char s)
{
P22=1;P21=0;P20=0;//xxxx x100 ->1111 0111
P0=seg[s/10]; //显示十位
delay1ms(2);
P22=1;P21=0;P20=1;//xxxx x101 ->1111 1011
P0=seg[s%10]; //显示个位
delay1ms(2);
}
/******************************************************************
函数功能:显示分钟子程序
入口参数:m
********************************************************************/
void DisplayMinute(unsigned char m)
{
P22=0;P21=1;P20=0;//xxxx x010 ->1110 1111
P0=seg[m/10];//显示十位
delay1ms(2);
P22=0;P21=1;P20=1;//xxxx x011 ->1101 1111
P0=seg[m%10]|0x80;
delay1ms(2);
}
/******************************************************************
函数功能:显示小时子程序
入口参数:h
********************************************************************/
void DisplayHour(unsigned char h)
{
P22=0;P21=0;P20=0;//xxxx x000 ->0111 1111
P0=seg[h/10]; //显示十位
delay1ms(2);
P22=0;P21=0;P20=1;//xxxx x001 ->1011 1111
P0=seg[h%10]|0x80; //显示个位
delay1ms(2);
}
/******************************************************************
函数功能:定期器T0中断服务子程序
********************************************************************/
void interserve(void ) interrupt 1 using 1 //using Time0
{
int_time++;
if(int_time==20)
{
int_time=0; //中断计数变量清0
second++; //秒计数变量加1
}
if(second==60)
{
second=0; //如果秒计满60,将秒计数变量清0
minute++; //分钟计数变量加1
}
if(minute==60)
{
minute=0; //如果分钟计满60,将分钟计数变量清0
hour++; //小时计数变量加1
}
if(hour==24)
{
hour=0; //如果小时计满24,将小时计数变量清0
}
TH0=(65536-50000)/256; //定期器重新赋初值
TL0=(65536-50000)%256;
}
附加内容2:涡流称重计综合程序
/**********************************************
程序名称:
**********************************************/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char //定义uchar代替unsigned char
#define uint unsigned int //定义uint代替unsigned int
#define ulong unsigned long //定义ulong代替unsigned long
void delay1ms(unsigned int i);
void convdata(unsigned char i);
void display(void); //六位数码管显示程序
sbit LED1=P1^0;//LED
sbit P23=P2^3;//74LS138 - CS
sbit P22=P2^2;//74LS138
sbit P21=P2^1;//74LS138
sbit P20=P2^0;//74LS138
sbit ADDI = P3^3; //数据输入接口 P3.3接口进行分时复用
sbit ADDO = P3^3; //数据输出接口
sbit ADCLK = P3^4; //时钟接口
sbit ADCS = P3^5; //使能接口
uchar code seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //数码管
// 0 1 2 3 4 5 6 7 8 9
uchar dis[] = {0,0,0,0,0,0};//AD转换为电压显示
double adg=0;
double adv=0;
uchar Temp;
/********************************************************
函数名称:void AD_init(uchar i)
函数作用:初始化ADC0832
参数阐明:i=2,表达通道0,i=3,表达通道1
0010 0011
********************************************************/
uchar ADC0832(uchar ch)
{
uchar temp = 0;
uchar temp1 = 0;
uchar temp2 = 0;
uchar i = 0;
/*在第1个时钟脉冲下沉之前DI端必要是高电平,表达启始信号*/
ADCLK = 0;
_nop_();
_nop_();
ADDI = 1;
_nop_();
_nop_();
ADCS = 0; //使能ADC0832
_nop_();
_nop_();
ADCLK = 1;
_nop_();
_nop_();
ADCLK = 0; //形成下降沿1
_nop_();
_nop_();
/*在第2、3个脉冲下沉之前DI端应输入2位数据用于选取通道功能*/
ADDI = 1;
_nop_();
_nop_();
ADCLK = 1;
_nop_();
_nop_();
ADCLK = 0; //形成下降沿2
_nop_();
_nop_();
ADDI = 0;
_nop_();
_nop_();
ADCLK = 1;
_nop_();
_nop_();
ADCLK = 0; //形成下降沿3
_nop_();
_nop_();
ADDI = 1;
_nop_();
_nop_();
//第4-11个脉冲期间读数据(MSB->LSB) DATA7~DATA0
for(i = 0;i < 8;i++) //读取前8位值
{
ADCLK = 1;
_nop_();
_nop_();
ADCLK = 0; //形成下降沿
_nop_();
_nop_();
if(ADDI) temp1 |= 0x01;
else temp1 |= 0x00;
//temp1 = temp1 << 1;
temp1 = temp1 >> i;
}
//第11-18个脉冲期间读数据(LSB->MSB) DATA0~DATA7反向校验
for(i = 0;i < 8;i++) //读取后8位值
{
if(ADDI) temp = 0x01;
else temp = 0x00;
temp = temp << i;
temp2 |= temp;
ADCLK = 1;
_nop_();
_nop_();
ADCLK = 0; //形成下降沿
_nop_();
_nop_();
}
ADCS = 1; //ADC0832
_nop_();
_nop_();
return temp2;
}
void main()
{
Temp=0;
P23=0;//CS
Temp= ADC0832(2);
while(1)
{
Temp= ADC0832(2);
convdata(Temp);
display();
}
}
/****************************************************************************
函数功能:将0-255级换算成0.00-5.00电压数值
入口参数:i
出口参数:
****************************************************************************/
void convdata(uchar i)
{
adv=(double)i;
//3.5+
if(adv>125) adg=3.5;
//1.5~2.5
else if(adv>75) adg=adv/50+1.0;
//0.5~1.5
else if(adv>25) adg=adv/50*2.5-1.25;
//0~0.5
else adg=0;
//adg=1.55;
//1~3位
dis[0] = i/50; //个位
dis[1] = (i%50)/5; //小数点后第一位
dis[2] = (i%50)%5; //小数点后第二位
//4~6位
//dis[3] = i/100; //
//dis[4] = (i%100)/10; //
//dis[5] = (i%100)%10; //
//4~6位
dis[3] = (uchar)adg%10; //
dis[4] = ((uchar)(adg*10))%10; //
dis[5] = ((uchar)(adg*100))%100%10; //
}
/********************************************************
函数名称:void display(void)
函数作用:数码管显示
参数阐明:无
函数返回:无返回
********************************************************/
void display(void)
{
P22=0;P21=0;P20=0;//xxxx x000 ->0111 1111
P0=seg[dis[0]]|0x80;//显示个位和小数点
delay1ms(2);
P22=0;P21=0;P20=1;//xxxx x001 ->1011 1111
P0=seg[dis[1]]; //显示小数点后第一位
delay1ms(2);
P22=0;P21=1;P20=0;//xxxx x010 ->1101 1111
P0=seg[dis[2]]; //显示小数点后第二位
delay1ms(2);
P22=0;P21=1;P20=1;//xxxx x011 ->1110 1111
P0=seg[dis[3]]|0x80;
delay1ms(2);
P22=1;P21=0;P20=0;//xxxx x100 ->1111 0111
P0=seg[dis[4]];
delay1ms(2);
P22=1;P21=0;P20=1;//xxxx x101 ->1111 1011
P0=seg[dis[5]];
delay1ms(2);
}
/********************************************************
函数名称:void delay1ms(unsigned int i)
函数作用:1ms延时程序
********************************************************/
void delay1ms(unsigned int i)
{
unsigned char j;
while(i--)
{
for(j=0;j<125;j++)//延时1ms延时语句
{}
}
}
附加内容3:光电转速计程序
#include <reg52.h>
#include <intrins.h>
#include <MATH.H>
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
uchar disValue[6];
uchar lb1,hb1;
uint Value,Value1;
uchar code tab[]={0x3f,0x6,0x5b,0x4f,0x66,0x6d,0x7d,0x7,0x7f,0x6f};
uint count;
void delay();
void display();
void initinit();
void intitimer0();
void main
展开阅读全文