本程序为采用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);
}