#define uchar unsigned char #define uint unsigned int
sbit RS = P3^0; //数据/命令选择端(H/L) sbit LCDEN = P3^2; //使能端
sbit deng=P1^6; //超过温度指示灯 sbit beep=P1^7; //超过温度报警器
uchar high=30; //最高温度 uchar low=10; //最低温度
unsigned char r;
void delayUs() //短延时 {
_nop_(); }
void delayMs(uint a) //长延时 {
uint i, j;
for(i = a; i > 0; i--) for(j = 100; j > 0; j--); }
//第一行开始地址为0x80, 第二行开始地址为0xc0; //写命令:RS=0, RW=0; void writeComm(uchar comm) {
RS = 0; P2 = comm; LCDEN = 1; delayUs(); LCDEN = 0; delayMs(1);
- 10 -
单片机原理及系统课程设计报告
}
//写数据:RS=1, RW=00 void writeData(uchar dat) {
RS = 1; P2 = dat; LCDEN = 1; delayUs(); LCDEN = 0; delayMs(1); }
//初始化函数
//显示模式, 固定指令为=0x38, 16*2显示, 5*7点阵,8位数据接口 //显示开/关及光标设置=0x0c
//指令1: 00001DCB : D:开显示/关显示(H/L); C:显示光标/不显示(H/L), B:光标闪烁/不闪烁(H/L) //指令2: NS :
//N=1, 当读/写一个字符后地址指针加1, 且光标也加1; N=0则相反
//S=1, 当写一个字符, 整屏显示左移(N=1)或右移(N=0), 但光标不移动; S=0, 整屏不移动 void init() {
writeComm(0x38); //显示模式 writeComm(0x0c); //开显示, 关光标
writeComm(0x06); //写字符后地址加1, 光标加1 writeComm(0x01); //清屏 }
void writeString(uchar * str, uchar length) {
uchar i;
for(i = 0; i < length; i++) {
writeData(str[i]); }
- 11 -
}
/*****************************DS18B20*******************************/ sbit ds = P3^7; //初始化DS18B20
//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动 void dsInit() {
//对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于为8us unsigned int i; ds = 0;
i = 100; //拉低约800us, 符合协议要求的480us以上 while(i>0) i--;
ds = 1; //产生一个上升沿, 进入等待应答状态 i = 4; while(i>0) i--; }
void dsWait() {
unsigned int i; while(ds);
while(~ds); //检测到应答脉冲 i = 4;
while(i > 0) i--; }
//向DS18B20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平, //之后DS18B20则会输出持续一段时间的一位数据 bit readBit() {
unsigned int i; bit b; ds = 0;
i++; //延时约8us, 符合协议要求至少保持1us ds = 1;
i++; i++; //延时约16us, 符合协议要求的至少延时15us以上 b = ds; i = 8;
while(i>0) i--; //延时约us, 符合读时隙不低于60us要求 return b; }
//读取一字节数据, 通过调用readBit()来实现 unsigned char readByte() {
- 12 -
单片机原理及系统课程设计报告
unsigned int i; unsigned char j, dat; dat = 0; for(i=0; i<8; i++) {
j = readBit();
//最先读出的是最低位数据 dat = (j << 7) | (dat >> 1); } return dat; }
//向DS18B20写入一字节数据 void writeByte(unsigned char dat) {
unsigned int i; unsigned char j; bit b;
for(j = 0; j < 8; j++) {
b = dat & 0x01;
dat >>= 1;//写\"1\将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1 if(b) {
ds = 0;
i++; i++; //拉低约16us, 符号要求15~60us内 ds = 1;
i = 8; while(i>0) i--; //延时约us, 符合写时隙不低于60us要求 }
else //写\"0\将DQ拉低60us~120us {
ds = 0;
i = 8; while(i>0) i--; //拉低约us, 符号要求 ds = 1;
i++; i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时us了
- 13 -
} } }
//向DS18B20发送温度转换命令 void sendChangeCmd() {
dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化 dsWait(); //等待DS18B20应答
delayMs(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号 writeByte(0xcc); //写入跳过序列号命令字 Skip Rom writeByte(0x44); //写入温度转换命令字 Convert T }
//向DS18B20发送读取数据命令 void sendReadCmd() {
dsInit(); dsWait(); delayMs(1);
writeByte(0xcc); //写入跳过序列号命令字 Skip Rom writeByte(0xbe); //写入读取数据令字 Read Scratchpad }
//获取当前温度值 int getTmpValue() {
unsigned int tmpvalue; int value; //存放温度数值 float t;
unsigned char low, high; sendReadCmd(); //连续读取两个字节数据 low = readByte(); high = readByte();
//将高低两个字节合成一个整形变量 //计算机中对于负数是利用补码来表示的
//若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的value tmpvalue = high; tmpvalue <<= 8; tmpvalue |= low; value = tmpvalue;
//使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度
t = value * 0.0625;
- 14 -
单片机原理及系统课程设计报告
//将它放大10倍, 使显示时可显示小数点后一位, 并对小数点后第二位进行4舍5入 //如t=11.0625, 进行计数后, 得到value = 111, 即11.1 度 //如t=-11.0625, 进行计数后, 得到value = -111, 即-11.1 度 value = t * 10 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5 return value; }
//显示温度 void display(int v) {
unsigned char count;
unsigned char datas[] = {0, 0, 0, 0}; unsigned int tmp = abs(v); datas[0] = tmp / 1000; datas[1] = tmp % 1000 / 100; datas[2] = tmp % 100 / 10; datas[3] = tmp % 10;
r= tmp/10;
writeComm(0xc0+3); if(v < 0) {
writeString(\"- \ } else {
writeString(\"+ \ }
if(datas[0] != 0) {
writeData('0'+datas[0]); }
for(count = 1; count != 4; count++) {
writeData('0'+datas[count]); if(count == 2) {
- 15 -
writeData('.'); } } }
/******************************报警*******************************/ void BEEP()//报警 {if((r>=high&&r<129)||rbeep=!beep; deng=1; } else {beep=1; deng=0; } }void main() {
uchar table[] = \"Now Temperature \"; delayMs(1);
sendChangeCmd(); init();
writeComm(0x80); writeString(table, 16); while(1) {
delayMs(1000); //温度转换时间需要750ms以上 writeComm(0xc0); display(getTmpValue()); sendChangeCmd(); }
/******************************DS18B20*******************************/
BEEP();
}
- 16 -