单片机实训_单片机实训台
单片机实训由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“单片机实训台”。
#include //用AT89C51时就用这个头文件
//#include //用华邦W78E58B时必须用这个头文件 #include /*Intrins.h文件包含只是编译器产生嵌入原有代码的程序的原型*/
//注意那个LCD_Wait()函数,它是判“忙”标志的,在实际硬件要把注掉的那种打开
//Port Definitions********************************************************** sbitLcdRs = P2^0;sbit:特殊功能寄存器,位寻址,位变量名=特殊功能寄存器名^位位置
sbitLcdRw = P2^1;sbitLcdEn = P2^2;sfrDBPort = 0x80;//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口
sfr特殊功能寄存器名=特殊功能寄存器地址常数
sfr16: 16位特殊功能寄存器,字寻址,低位在低字节,高
位在高字节
//内部等待函************************************************************************** unsigned char LCD_Wait(void){ LcdRs=0;LcdRw=1;_nop_();LcdEn=1;_nop_();
数 //while(DBPort&0x80);//在用Proteus仿真时,注意用屏蔽此语句,在调用GotoXY()时,会进入死循环,//可能在写该控制字时,该模块没有返回写入完备命令,即DBPort&0x80==0x80
//实际硬件时打开此语句
LcdEn=0;returnDBPort;} //向LCD写入命令或数据************************************************************ #define LCD_COMMAND
0
// Command #define LCD_DATA
// Data #define LCD_CLEAR_SCREEN 0x01
// 清屏 #define LCD_HOMING
0x02
// 光标返回原点 voidLCD_Write(bit style, unsigned char input){ LcdEn=0;LcdRs=style;LcdRw=0;_nop_();
} DBPort=input;_nop_();//注意顺序 LcdEn=1;_nop_();//注意顺序 LcdEn=0;_nop_();LCD_Wait();
//设置显示模式************************************************************ #define LCD_SHOW
0x04
//显示开 #define LCD_HIDE
0x00
//显示关
#define LCD_CURSOR
0x02 //显示光标 #define LCD_NO_CURSOR 0x00
//无光标
#define LCD_FLASH
0x01
//光标闪动 #define LCD_NO_FLASH 0x00
//光标不闪动
voidLCD_SetDisplay(unsigned char DisplayMode){ LCD_Write(LCD_COMMAND, 0x08|DisplayMode);}
//设置输入模式************************************************************ #define LCD_AC_UP
0x02 #define LCD_AC_DOWN 0x00
// default
#define LCD_MOVE
0x01
// 画面可平移 #define LCD_NO_MOVE 0x00
//default
voidLCD_SetInput(unsigned char InputMode){ LCD_Write(LCD_COMMAND, 0x04|InputMode);}
//初始化LCD************************************************************ voidLCD_Initial(){ LcdEn=0;LCD_Write(LCD_COMMAND,0x38);
//8位数据端口,2行显示,5*7点阵
LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);
//开启显示, 无光标
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);
//清屏
LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);
//AC递增, 画面不动 } //************************************************************************ voidGotoXY(unsigned char x, unsigned char y){ if(y==0)
LCD_Write(LCD_COMMAND,0x80|x);if(y==1)
LCD_Write(LCD_COMMAND,0x80|(x-0x40));}
void Print(unsigned char *str){ while(*str!=' '){
LCD_Write(LCD_DATA,*str);
str++;} } voidLCD_Print(unsigned char x, unsigned char y, unsigned char *str){ GotoXY(x,y);Print(str);}
#include //用AT89C51时就用这个头文件
//#include //用华邦W78E58B时必须用这个头文件 sbit DQ = P3^4;
//定义DQ引脚为P3.4 /***********ds18b20延迟子函数(晶振12MHz)*******/ /***********DS18B20对时间要求很严,但只能长不能短 ************在11.0592M下也行,因为时间长些********/ void delay_18B20(unsigned int i){ while(i--);
/**********ds18b20初始化函数**********************/
void Init_DS18B20(void){ unsigned char x=0;
DQ = 1;
//DQ复位
delay_18B20(8);//稍做延时
DQ = 0;
//单片机将DQ拉低
delay_18B20(80);//精确延时大于 480us
DQ = 1;
//拉高总线
delay_18B20(14);
x=DQ;
//稍做延时后如果x=0则初始化成功 x=1则初始化失败
delay_18B20(20);}
/***********ds18b20读一个字节**************/
unsigned char ReadOneChar(void){ unsigned char i=0;unsigned char dat = 0;for(i=8;i>0;i--)
{
DQ = 0;// 给脉冲信号
dat>>=1;
DQ = 1;// 给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(4);
} return(dat);}
/*************ds18b20写一个字节****************/
voidWriteOneChar(unsigned char dat){ unsigned char i=0;for(i=8;i>0;i--)
} } { DQ = 0;DQ = dat&0x01;delay_18B20(5);DQ = 1;dat>>=1;/**************读取ds18b20当前温度************/ unsigned char *ReadTemperature(char TH,charTL,unsigned char RS){ unsigned char tt[2];Init_DS18B20();
} WriteOneChar(0xCC);
// 跳过读序号列号的操作
WriteOneChar(0x4E);// //写入“写暂存器”命令,修改TH和TL和分辩率配置寄存器
//先写TH,再写TL,最后写配置寄存器 WriteOneChar(TH);//写入想设定的温度报警上限 WriteOneChar(TL);//写入想设定的温度报警下限 WriteOneChar(RS);//写配置寄存器,格式为0 R1 R0 1,1 1 1 1
//R1R0=00分辨率娄9位,R1R0=11分辨率为12位 delay_18B20(80);
// this meage is wery important Init_DS18B20();WriteOneChar(0xCC);
// 跳过读序号列号的操作 WriteOneChar(0x44);// 启动温度转换
delay_18B20(80);
// this meage is wery important Init_DS18B20();WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0xBE);//读取温度寄存器等(共可读9个寄存器)前两个就是温度 delay_18B20(80);tt[0]=ReadOneChar();
tt[1]=ReadOneChar();
return(tt);
//读取温度值低位
//读取温度值高位
#include //用AT89C51时就用这个头文件
//#include //用华邦W78E58B时必须用这个头文件 #include #include #include #include #include
//sbit DQ = P3^4;
//定义DQ引脚为P3.4 unsigned char t[2],*pt;
//用来存放温度值,测温程序就是通过这个数组与主函数通信的unsigned char TempBuffer1[9]={0x2b,0x31,0x32,0x32,0x2e,0x30,0x30,0x43,' '};
//显示实时温度,上电时显示+125.00C unsigned char TempBuffer0[17]={0x54,0x48,0x3a,0x2b,0x31,0x32,0x35,0x20,0x54,0x4c,0x3a,0x2b,0x31,0x32,0x34,0x43,' '};
//显示温度上下限,上电时显示TH:+125 TL:+124C
unsigned char code dotcode[4]={0,25,50,75};/***因显示分辨率为0.25,但小数运算比较麻烦,故采用查表的方法******* 再将表值分离出十位和个位后送到十分位和百分位********************/
void covert0(unsigned char TH, unsigned char TL)//将温度上下限转换为LCD显示的数据 {
if(TH>0x7F)
//判断正负,如果为负温,将其转化为其绝对值
{
TempBuffer0[3]=0x2d;
//0x2d为“-”的ASCII码
TH=~TH;TH++;
}
else TempBuffer0[3]=0x2b;//0x2B为“+”的ASCII码
if(TL>0x7f)
{
TempBuffer0[11]=0x2d;
//0x2d为“-”的ASCII码
TL=~TL+1;
}
else TempBuffer0[11]=0x2b;//0x2B为“+”的ASCII码
TempBuffer0[4]=TH/100+0x30;
//分离出TH的百十个位
if(TempBuffer0[4]==0x30)TempBuffer0[4]=0xfe;//百位数消隐
TempBuffer0[5]=(TH%100)/10+0x30;
//分离出十位
TempBuffer0[6]=(TH%100)%10+0x30;
//分离出个位
TempBuffer0[12]=TL/100+0x30;
//分离出TL的百十个位
if(TempBuffer0[12]==0x30)TempBuffer0[12]=0xfe;//百位数消隐
TempBuffer0[13]=(TL%100)/10+0x30;
//分离出十位
TempBuffer0[14]=(TL%100)%10+0x30;
//分离出个位 }
void covert1(void)//将温度转换为LCD显示的数据 { unsigned char x=0x00,y=0x00;t[0]=*pt;pt++;t[1]=*pt;
if(t[1]>0x07)
//判断正负温度
{
TempBuffer1[0]=0x2d;
//0x2d为“-”的ASCII码
t[1]=~t[1];
/*下面几句把负数的补码*/ t[0]=~t[0];
/* 换算成绝对值*********/ x=t[0]+1;
/***********************/ t[0]=x;
/***********************/ if(x>255)
/**********************/ t[1]++;
/*********************/
}
else TempBuffer1[0]=0x2b;//0xfe为变“+”的ASCII码
t[1]
t[1]=t[1]&0x70;//取出高字节的3个有效数字位
x=t[0];
//将t[0]暂存到X,因为取小数部分还要用到它
x>>=4;
//右移4位
x=x&0x0f;
//和前面两句就是取出t[0]的高四位
t[1]=t[1]|x;
//将高低字节的有效值的整数部分拼成一个字节
TempBuffer1[1]=t[1]/100+0x30;
//+0x30 为变 0~9 ASCII码
if(TempBuffer1[1]==0x30)TempBuffer1[1]=0xfe;//百位数消隐
TempBuffer1[2]=(t[1]%100)/10+0x30;
//分离出十位
TempBuffer1[3]=(t[1]%100)%10+0x30;
//分离出个位
t[0]=t[0]&0x0c;
//取有效的两位小数
t[0]>>=2;
//左移两位,以便查表
x=t[0];
y=dotcode[x];
//查表换算成实际的小数
TempBuffer1[5]=y/10+0x30;
//分离出十分位
TempBuffer1[6]=y%10+0x30;
//分离出百分位 }
void delay(unsigned char i){ while(i--);}
main(){ unsigned char TH=110,TL=-20;
//下一步扩展时可能通过这两个变量,调节上下限
//测温函数返回这个数组的头地址 while(1){
pt=ReadTemperature(TH,TL,0x3f);//上限温度-22,下限-24,分辨率10位,也就是0.25C
} }
delay(100);covert1();covert0(TH,TL);
//读取温度,温度值存放在一个两个字节的数组中, LCD_Initial();
//第一个参数列号,第二个为行号,为0表示第一行
//为1表示第二行,第三个参数为显示数据的首地址 LCD_Print(0,0,TempBuffer0);LCD_Print(0,1,TempBuffer1);