单片机小白
边学边写,学艺不精,技术有限,仅为记录,欢迎指教
运行效果:
主函数main.c:
#include#include "ds18b20.h" #include "lcd1602.h" u8 code cg_addr[]={0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78}; //其中八个CGRom的地址 u8 code read_cg[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; //以上八个CGRom的编号 u8 code kai[] = {0x1F,0x0A,0x0A,0x1F,0x0A,0x0A,0x12,0x02}; //开 u8 code x[] = {0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x00}; u8 code ing[] = {0x00,0x00,0x04,0x01,0x10,0x11,0x1F,0x00}; //心 u8 code dian[] = {0x07,0x05,0x07,0x00,0x00,0x00,0x00,0x00}; //〬 u8 code xiao1[]={0x03,0x04,0x0A,0x08,0x0A,0x09,0x04,0x03}; //左部笑脸 u8 code xiao2[]={0x18,0x04,0x12,0x02,0x0A,0x12,0x04,0x18}; //右部笑脸 u8 code str[]="tempereture :"; //自定义图形函数 void user_xie(u8 x,u8 y,u8 cg,u8 *User) { u8 i; LcdWriteCmd(cg_addr[cg]); //设定 CGRAM 地址 for(i=0;i<8;i++ ) { LcdWriteData(User[i]); //写入自定义图形 } LcdSetCursor(x,y); //显示的位置,x为列,y为行 LcdWriteData(read_cg[cg]); //从 CGRAM 里取出自定义图形显示 } //延时函数,温度的刷新时间 //主要是引脚P2^5与蜂鸣器共用,不设置一下太吵人了 void delay_ds(unsigned short ms) { u8 T; while(ms--) { for(T=0;T<250;T++); } } //主函数 void main() { u8 df[8]; s16 qw; InitLcd1602(); //lcd1602初始化 while(1) { qw=datapros(DS18B20temp_data()); //DS18B20温度数据 tostring(df,qw); //数字转字符串函数,保留一位小数 LcdShowStr(2,0,str); //从CGROM中选中相应字符显示 LcdShowStr(5,1,df); LcdShowStr(11,1,"C"); user_xie(0,1,0,kai); //自定义图形函数 user_xie(1,1,1,x); user_xie(2,1,2,ing); user_xie(10,1,3,dian); user_xie(14,1,5,xiao1); user_xie(15,1,6,xiao2); delay_ds(450); //延时函数 } }
ds18b20.h:
#include#include #define u8 unsigned char #define u16 unsigned int #define s16 signed int sbit IO_18B20=P3^7; u8 DQ; void Delay(u16 i)//延时 { while(i--); } void init_18B20()//DS18B20初始化 { IO_18B20=0; Delay(100); IO_18B20=1; Delay(5); DQ=IO_18B20; Delay(80); } void write_cmd(u8 cmd)//DS18B20写时序 { u8 i; for(i=0;i<8;i++) { IO_18B20=0; _nop_(); IO_18B20=cmd&0x01; Delay(6); IO_18B20=1; cmd>>=1; } } u8 read_cmd()//DS18B20读时序 { u8 j,by,byte; for(j=0;j<8;j++) { IO_18B20=0; _nop_(); IO_18B20=1; _nop_(); _nop_(); by=IO_18B20; byte=(byte>>1)|(by<<7); Delay(4); } return byte; } void change_temper()//温度转换 { init_18B20(); if(DQ==0) { write_cmd(0xcc);//跳过ROM write_cmd(0x44);//温度转换后存储在暂存寄存器的2个字节长度的温度寄存器中 } } void read_temper()//读温度 { init_18B20(); if(DQ==0) { write_cmd(0xcc);//跳过ROM write_cmd(0xbe);//读取暂存寄存器 } } s16 DS18B20temp_data()//采集DS18B20中cache温度数据 { s16 temp; u8 temph,templ; change_temper(); read_temper(); templ=read_cmd(); temph=read_cmd(); temp=temph; temp<<=8; temp|=templ; return temp; } s16 datapros(s16 temp)//将采集的数据按照规定的分辨率转化为数字 { s16 tp; if(temp<0) { temp=~temp; temp+=1; tp=temp; temp=tp*0.0625*10+0.5; } else { tp=temp; temp=tp*0.0625*10+0.5; //0.0625为分辨率 10:保留一位小数 0.5:精度 } return temp; }
lcd1602.h:
#include#include #define LCD1602_DB P0 sbit LCD1602_RW=P2^5; sbit LCD1602_RS=P2^6; sbit LCD1602_E=P2^7; //lcd1602忙闲状态判断 void LcdWaitReady() { u8 sta; LCD1602_DB=0xFF; LCD1602_RS=0; LCD1602_RW=1; do{ LCD1602_E=1; sta=LCD1602_DB; LCD1602_E=0; }while(sta&0x80); } //写命令 void LcdWriteCmd(u8 cmd) { LcdWaitReady(); LCD1602_RS=0; LCD1602_RW=0; LCD1602_DB=cmd; LCD1602_E=1; LCD1602_E=0; } //写数据(1602字符输入(CGROM固定字库)) void LcdWriteData(u8 dat) { LcdWaitReady(); LCD1602_RS=1; LCD1602_RW=0; LCD1602_DB=dat; LCD1602_E=1; LCD1602_E=0; } //lcd1602初始化 void InitLcd1602() { LcdWriteCmd(0x38); //功能设置命令 、 LcdWriteCmd(0x0C); //显示开/关及光标设置 、 LcdWriteCmd(0x06); //显示模式设置 LcdWriteCmd(0x01); //清屏指令 } //显示的位置设置 void LcdSetCursor(u8 x,u8 y)//x为列,y为行 { u8 addr; if(y==0) addr=0x80+x;//第一行 else addr=0xC0+x;//第二行 LcdWriteCmd(addr); } //显示 void LcdShowStr(u8 x,u8 y,u8 *str) { LcdSetCursor(x,y); while(*str!=' ') { LcdWriteData(*str++); } } void tostring(u8 *str, int dat)//数字转字符串并添加小数点 { signed char i = 0; u8 buf[6]; if (dat < 0) { dat = -dat; *str++ = '-'; } do { buf[i++] = dat % 10; dat /= 10; } while (dat > 0); while (i-- > 0) { if(i==0) { *str++='.'; *str++ = buf[i] + '0'; } else *str++ = buf[i] + '0'; } *str = ' '; }



