基于C51单片机的智能仪器综合设计实验

基于单片机的智能仪器综合设计实验

一、实验目的

在实验一~实验三的基础上,完成综合设计实验,学会信号采集、数据处理、键盘控制、LCD或LED显示等功能的智能仪器设计。

二、复习与参考

实验一~实验三

三、设计指标

利用K分度号热电偶进行温度检测,测温范围为500-1200?C,室温为20?C,用LCD或LED显示室温和测量温度。

具有4路温度信号循环检测功能,通道切换时间可调;具有任意指定通道显示功能。

四、实验要求

1.选择传感器,设计硬件电路,包括检测电路、信号调理电路、AD转换电路、单片机最小系统、LED显示(单号)、LCD显示(双号)、独立式按键,画出电路原理图。

2.画出软件流程图。

3.用Keil C51编写程序。

3.实验结果在LCD或LED上显示出来。

4.实验前完成第1、2项备查。

五、实验仪器设备和材料清单

PC机;单片机实验板、连接导线、ST7920图形液晶模块

Keil c51软件

六、实验成绩评定方法

实验成绩包括预习、实验完成质量、实验报告质量3部分组成,各部分所占比例分别为30%、40%、30%。

八、实验报告要求

实验报告格式:

? 实验名称

? 实验目的

1

? 实验内容

? 硬件设计

? 软件设计

? 调试过程

? 参考文献

? 附1:电路原理图

? 附2:程序清单

附录:实验程序源代码如下:(陈寅) #include "reg51.h"

#define THC0 0xee //5ms时间常数设置

#define TLC0 0x00

sbit ADWR=P3^6; /***WR*****/

sbit ADRD=P3^7; /***RD*****/

sbit ADCS=P2^7; /***CS*****/

sbit EOC=P3^3; /***EOC****/

sbit ADA=P1^3; //通道选择引脚

sbit ADB=P1^4;

sbit ADC=P1^5;

sbit CS =P1^0; /****************/

sbit SID=P1^1; /**液晶引脚定义**/

sbit SCLK=P1^2; /****************/

sbit MODE=P2^0; /*************************/

sbit UP=P2^1; /*四个按键接口,0表示按下*/

sbit DOWN=P2^2; /*************************/

sbit LED1=P2^3; /**4个LED灯引脚定义**/

sbit LED2=P2^4; /********************/

sbit LED3=P2^5; /********************/

sbit LED4=P2^6; /********************/

/***************500~1200°C范围的K分度表,间隔10*******************/ unsigned int code K_TABLE[71]={

20644,21066,21493,21919,22346,22772,23198,23624,24050,24476, 24902,25327,25751,26176,26599,27022,27445,27867,28288,28709, 29128,29547,29965,30383,30799,31214,31629,32042,32455,32866, 33277,33686,34095,34502,34909,35314,35718,36121,36524,36925,

2

37325,37725,38122,38519,38915,39310,39703,40096,40488,40897, 41296,41657,42045,42432,42817,43202,43585,43968,44349,44729,

45108,45486,45863,46238,46612,46985,47356,47726,48095,48462,48828}; unsigned char GetAdData[10]={0}; //存放获得AD值的数组变量

unsigned char ViewTemperature[4]={"0000"}; //显示温度缓冲数组变量 unsigned MODESelect=1;

int ChangeTime=2; //通道切换时间,单位S

int TongDao=1;

void delay(unsigned int j)

{

unsigned char i;

do{

for(i=0;i<100;i++);

}while(j--);

}

void send_command(unsigned char command_data) //发送命令

{

unsigned char i;

unsigned char i_data;

i_data=0xf8; //操作命令,可以查看资料

delay(10);

CS=1;

SCLK=0;

for(i=0;i<8;i++)

{

SID=(bit)(i_data&0x80);

SCLK=0;

SCLK=1;

i_data=i_data<<1;

}

i_data=command_data;

i_data&=0xf0;

for(i=0;i<8;i++)

{

SID=(bit)(i_data&0x80);

SCLK=0;

SCLK=1;

i_data=i_data<<1;

}

i_data=command_data;

i_data=i_data&0x0f;

i_data<<=4;

3

for(i=0;i<8;i++)

{

SID=(bit)(i_data&0x80);

SCLK=0;

SCLK=1;

i_data=i_data<<1;

}

CS=0;

}

void send_data(unsigned char command_data) //发送数据 {

unsigned char i;

unsigned char i_data;

i_data=0xfa; //操作命令,可以查看资料

delay(10);

CS=1;

for(i=0;i<8;i++)

{

SID=(bit)(i_data&0x80);

SCLK=0;

SCLK=1;

i_data=i_data<<1;

}

i_data=command_data;

i_data&=0xf0;

for(i=0;i<8;i++)

{

SID=(bit)(i_data&0x80);

SCLK=0;

SCLK=1;

i_data=i_data<<1;

}

i_data=command_data;

i_data=i_data&0x0f; //取低四位

i_data<<=4; //左移四位,从而变成高四位 for(i=0;i<8;i++)

{

SID=(bit)(i_data&0x80);

SCLK=0;

SCLK=1;

i_data=i_data<<1;

}

CS=0;

}

4

void InitLCD() //液晶初始化

{

send_command(0x30); //功能设置:一次送8位数据,基本指令集

send_command(0x06); //点设定:显示字符/光标从左到右移位,DDRAM地址加1 send_command(0x0c); //显示设定:开显示,显示光标,当前显示位反白闪动

send_command(0x04); //显示设定:开显示,显示光标,当前显示位反白闪动 send_command(0x01); //清DDRAM send_command(0x02); //DDRAM地址归位 send_command(0x80); //把显示地址设为0X80,即为第一行的首位 }

/* x,y为起始座标 x(0<=x<=3),y(0<=y<=7),x为行座标,y为列座标;

how为要显示汉字的个数;

style为显示字符的类型,0表汉字,1表字母; str是要显示汉字的地址 */

void Display(unsigned char x,unsigned char y,unsigned char how,bit style,unsigned char *stri) //液晶显示

{

unsigned char hi=0; if(x==0) send_command(0x80+y); else if(x==1) send_command(0x90+y); else if(x==2) send_command(0x88+y); else if(x==3) send_command(0x98+y); if(style==0) { for(hi=0;hi<how;hi++) } { } send_data(*(stri+hi*2)); send_data(*(stri+hi*2+1)); else for(hi=0;hi<how;hi++) send_data(*(stri+hi));

}

float LvBo(void)//复合滤波

{

unsigned char max,min,i; unsigned int sum=0;

float U1;

max=GetAdData[0];

min=GetAdData[0]; for(i=0;i<10;i++) { sum=sum+GetAdData[i]; if(max<GetAdData[i]) max=GetAdData[i]; 5

if(min>GetAdData[i]) min=GetAdData[i]; } sum=sum-max-min; U1=(float)sum/8; U1=10.0*((U1*5.0)/255); return U1; //换成mv

}

void search (void)//查表子函数

{

unsigned int da=0,max,min,mid,j; unsigned int var; da=LvBo()*1000; //u1扩大1000倍 da=da+798; max=71; min=0; var=0; while(1) { mid=(max+min)/2; //中心元素位置 //20度

if(K_TABLE[mid]==da) {var=mid*10;break;} //中心元素等于查表元素,计算相应温度

else if(K_TABLE[mid]>da) max=mid-1; else min=mid+1; if(max-min==1) /*线性插值计算温度值*/ { } j=(K_TABLE[max]-K_TABLE[min])/10; /*表中相邻两值对应温度相差j=(da-K_TABLE[min])/j; var=10*min+j; break; 10°C*/ if(max==min) { if(da>=K_TABLE[min]) { j=(K_TABLE[min+1]-K_TABLE[min])/10; j=(da-K_TABLE[min])/j; } else if(da<K_TABLE[min]) { j=(K_TABLE[min]-K_TABLE[min-1])/10; j=(da-K_TABLE[min-1])/j; min=min-1; 6

} } } var=10*min+j; break; var=var+500; ViewTemperature[0]=var/1000+0x30; ViewTemperature[1]=var/100%10+0x30; ViewTemperature[2]=var/10%10+0x30; ViewTemperature[3]=var%10+0x30;

}

void LcdDisplay(void)

{

unsigned char ViewMODESelect,ViewTongDao[5]={"0 "},ViewChangeTime[5]={"00(S)"};

ViewMODESelect=MODESelect+0x30;

ViewTongDao[0]=TongDao+0x30; if(MODESelect==1||MODESelect==2) { if(MODESelect==1) Display(0,3,5,0,":自动切换"); else if(MODESelect==2) Display(0,3,5,0,":手动切换"); } else if(MODESelect==3) { }

//AD通道设置 ViewChangeTime[0]=ChangeTime/10+0x30; ViewChangeTime[1]=ChangeTime%10+0x30; Display(0,0,2,0,"模式"); Display(0,2,1,1,&ViewMODESelect); Display(0,3,5,0,":设置时间"); Display(1,0,5,0,"切换时间:"); Display(1,5,5,1,ViewChangeTime); Display(2,0,14,1," "); //本行清屏 Display(0,0,2,0,"模式"); //液晶显示 Display(0,2,1,1,&ViewMODESelect); Display(1,0,5,0,"温度通道:"); Display(1,5,5,1,ViewTongDao); Display(2,0,4,0,"温度值:"); Display(2,4,4,1,ViewTemperature); Display(2,6,2,1,"℃"); } void TDSelect(void)

{

7

if(TongDao>=5) TongDao=1;

if(TongDao<=0) TongDao=4;

if(TongDao==1) {ADC=0;ADB=0;ADA=0;}

else if(TongDao==2) {ADC=0;ADB=0;ADA=1;}

else if(TongDao==3) {ADC=0;ADB=1;ADA=0;}

else if(TongDao==4) {ADC=0;ADB=1;ADA=1;}

}

main()

{

unsigned char AdCount=0; //用来存放AD采集次数

InitLCD();

TMOD=0x11; //定时器0初始化

TH0=THC0;

TL0=TLC0;

TR0=1;

ET0=1;

EA=1;

P2|=0x07; //按键初始为高

while(1)

{

ADWR=1; /************/

ADCS=0; /************/

ADWR=0; /**AD初始化**/

ADWR=1; /************/

while(!EOC); //等待转换结束

ADRD=0;

GetAdData[AdCount]=P0; //读取转换结果

AdCount++;

if(AdCount>=10) //连续采集10次值

{

AdCount=0;

search(); //查表

LED1=!LED1;

LcdDisplay(); //显示

}

}

}

void Timer0() interrupt 1

{

static unsigned char count=0,UPFlag=1,DOWNFlag=1; //按键标志位 static unsigned int TimeCount=0;

TH0=THC0;

TL0=TLC0;

8

if(MODE==0||UP==0||DOWN==0)

{

count++;

if(count>=30) //消抖处理

{

count=0;

if(MODE==0) //按键按下

{

MODESelect++;

if(MODESelect>=4) MODESelect=1; }

else if(UP==0)

{

UPFlag=0;

if(MODESelect==2)

{

TongDao++;

TDSelect();

}

}

else if(DOWN==0)

{

DOWNFlag=0;

if(MODESelect==2)

{

TongDao--;

TDSelect();

}

}

}

}

else count=0;

if(MODESelect==1)

{

TimeCount++;

if(TimeCount>=(ChangeTime*1000/5)) {

TimeCount=0;

TongDao++;

TDSelect();

}

}

else if(MODESelect==3)

9

{

if(UPFlag==0) {UPFlag=1;ChangeTime++;} else if(DOWNFlag==0)

{

DOWNFlag=1;

ChangeTime--;

if(ChangeTime<=0) ChangeTime=1; }

}

}

10

相关推荐