本程序为采用mega8 和ds18b20的温度采集程序 选用mega8内部8M RC震荡,ds18b20 数据线接pd6,数据线和vcc间接一4.7k上拉电阻 感谢dfgeoff 嗜血蜗牛提供的资料*/ #include <iom8v.h> //和单片机类型相对应的头文件,选择Atmega8做实验; #include <macros.h> #define uchar unsigned char #define uint unsigned int void init_1820(); write_1820(uchar x); uchar read_1820(); void send_byte(uchar x); void delay(uint x); void disp_led(uchar buffer,uchar control); uchar disp_table[16] = { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; uchar dp; long count; void main(void) //主函数 { disp_led(0,0); delay(2000); OSCCAL=0X9d;//系统时钟校准,不同的芯片和不同的频率, DDRC=0xff; DDRD=0XFF; PORTD=0XFF; WDR(); //看门狗计数清零 WDTCR=0x0F; PORTC=0xff; while(1) { uchar i,temh,teml; init_1820(); //复位18b20 write_1820(0xcc); // 发出转换命令 write_1820(0x44); delay(400); init_1820(); WDR(); write_1820(0xcc); //发出读命令 write_1820(0xbe); teml=read_1820(); //读数据 temh=read_1820(); //for(i=0;i<7;i++) //测试用 //{ //send_byte(0x40); //send_byte(disp_table[0&0x0f]); //} //send_byte(disp_table[temh>>4]); //send_byte(disp_table[temh&0x0f]); //send_byte(disp_table[teml>>4]); //send_byte(disp_table[teml&0x0f]); count=(temh*256+teml)*6.25; //计算具体温度 WDR(); disp_led(0,1); //显示温度 for(i=0;i<100;i++) //每次转换需要延时200ms以上 delay(1000); } } void delay(uint x) //1.5us左右 { while(x) { x--; } } void init_1820() { PORTD|=(1<<6); PORTD&=~(1<<6); delay(3000); //480us以上 PORTD|=(1<<6); DDRD&=~(1<<6); delay(40); //15~60us while(PIND&(1<<6)) { // disp_led(3,0); // for(;;) //{} } DDRD|=(1<<6); PORTD|=(1<<6); delay(150); //60~240us } write_1820(uchar x) { uchar m; for(m=0;m<8;m++) { PORTD&=~(1<<6); if(x&(1<<m)) //写数据,从低位开始 PORTD|=(1<<6); else PORTD&=~(1<<6); delay(40); //15~60us PORTD|=(1<<6); } PORTD|=(1<<6); } uchar read_1820() { uchar temp,k,n; temp=0; for(n=0;n<8;n++) { PORTD&=~(1<<6); //delay(2); PORTD|=(1<<6); //delay(3); DDRD&=~(1<<6); k=(PIND&(1<<6)); //读数据,从低位开始 if(k) temp|=(1<<n); else temp&=~(1<<n); delay(50); //60~120us DDRD|=(1<<6); } return (temp); }
void send_byte(uchar x) //以下为显示程序 { uchar i; for(i=0;i<8;i++) { PORTC&=~(1<<5); // PC5为底 为164提供时钟信号 if((x&(1<<(7-i)))||((dp==1)&&(i==0))) //判断每位数据的电平,及小数点判断 PORTC|=(1<<4); //若为高着PC4输出高电平 else PORTC&=~(1<<4); //若为低着输出低电平 PORTC|=(1<<5); //PC5 提供始终信号 } //PORTC|=((1<<0)|(1<<1)|(1<<2)); } //显示程序 CONTROL为控制显示 BUFFER为显示数据 void disp_led(uchar buffer,uchar control) { uchar i,temp[6]; uint tempcount; dp=0; switch(control) { case 0: //CONTROL为零全部数码管显示buffer { for(i=0;i<11;i++) send_byte(disp_table[buffer%10]);//显示数字 break; } case 1: //control为1,显示count中的数据为6位 { tempcount=count; for(i=0;i<6;i++) //取出每位中的数据 { temp[i]=tempcount%10; tempcount/=10; } send_byte(disp_table[buffer/10]); //最开始显示buffer数据 send_byte(disp_table[buffer%10]); send_byte(0x00); send_byte(0x00); send_byte(0x00); for(i=0;i<6;i++) { if(i==3) dp=1; //小数点控制位 send_byte(disp_table[temp[5-i]]); dp=0; } break; } } PORTC|=(1<<4); }
|