本程序为采用mega8 和ds18b20的温度采集程序
选用mega8内部8M RC震荡,ds18b20 数据线接pd6,数据线和vcc间接一4.7k上拉电阻
感谢dfgeoff 嗜血蜗牛提供的资料*/
#include < avr / io.h > #include <timer.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); uchardisp_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); }