📄 ds18b20._c
字号:
/*************************************
ds18b20测温程序
文 件 名 :ds18b20.c
设 计 :毕京鹏
最后修改日期:2008.11.13
版 本 :V1.0
主控芯片 :ATMEGA48V
工作频率 :外部16MHz晶振
备注 : 初步:实时测温并显示
1.读数据时的处理方式
2.数据口上需带上拉(5.1K)
3.配置成9位时后三位始终为0,以此类推
4.1s更新一次
*************************************/
#include<iom48v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
/*DQ 接在PC0上*/
#define DQ(x) x ? (PORTC |= 0x01) : (PORTC &= 0xfe)
#define DRC(y) y ? (DDRC |= 0x01 ) : (DDRC &= 0xfe)
uchar flag;
void Init_1wire(void);
void WriteByte_1wire(uchar data);
uchar ReadByte_1wire(void);
void PortInit(void);
void delay_1us(void);
void delay_10us(uchar n);
/*显示有关*/
#pragma interrupt_handler display_int:17
const uchar distable[]={0x27,0x2f,0x37,0x3f,0x67,0x6f,0x77,0x7f,0xa7,0xaf};
// 0 1 2 3 4 5 6 7 8 9
uchar time1,time2;
uchar count2=0;
uchar timeb1,timeb2,timeb3,timeb4,timeb5,timeb6;
void convert(void);
/*定时有关*/
uchar count1=0;
#pragma interrupt_handler timer1_int:14
/*通信有关*/
uchar Rece[2],Send[3];
uchar count3=0;
uchar flag1=0;
void UartInit(void);
void UartSend(uchar a[],uchar length);
#pragma interrupt_handler UartRece_int:19
/*******************主函数********************************/
main()
{ uchar tempH,tempL;
PortInit();
/***********此部分在初次配置完成后可略去*****************/
Init_1wire();
WriteByte_1wire(0xcc);
WriteByte_1wire(0x4e); //Write Scratchpad
WriteByte_1wire(0x7f); //TH
WriteByte_1wire(0xff); //TL
WriteByte_1wire(0x1f); //CONFIGURATION REGISTER 9位
Init_1wire();
WriteByte_1wire(0xcc);
WriteByte_1wire(0x48); //Copy Scratchpad
/***********************************************/
SEI();
while(1)
{if(count1==100)
{count1=0;
Init_1wire();
WriteByte_1wire(0xcc);
WriteByte_1wire(0x44);
DRC(0); //判断转换是否完成
if(!(PINC&0x01));
Init_1wire();
WriteByte_1wire(0xcc);
WriteByte_1wire(0xbe);
tempL = ReadByte_1wire();
tempH = ReadByte_1wire();
time1=tempH;
time2=tempL;
convert();
}
if(flag1==1)
{flag1=0;
if((Rece[0]=='S')&&(Rece[1]=='T'))
{Send[0]='#'
Send[1]=tempH;
Send[2]=tempL;
UartSend(Send,3); //向上位机发送数据
}
}
}
}
/*******************中断函数****************************/
/*定时中断*/
void timer1_int(void)
{TCNT1=0xfd8f; //重赋初值
if(count1!=100)count1++;
}
/*显示中断*/
void display_int(void)
{count2++;
TCNT0=0xce; //重赋初值
PORTC|=0x0e; //0000 1110
PORTD|=0xd8; //1101 1000
switch(count2)
{case 1:
PORTC&=0xf1; //L6 1111 0001
PORTD&=distable[timeb6];
break;
case 2:
PORTC&=0xf3; //L5 1111 0011
PORTD&=distable[timeb5];
break;
case 3:
PORTC&=0xf5; //L4 1111 0101
PORTD&=distable[timeb4];
break;
case 4:
PORTC&=0xf7; //L3 1111 0111
PORTD&=distable[timeb3];
break;
case 5:
PORTC&=0xf9; //L2 1111 1001
PORTD&=distable[timeb2];
break;
case 6:
count2=0;
PORTC&=0xfb; //L1 1111 1011
PORTD&=distable[timeb1];
break;
}
}
/*******************子函数***********************************/
/*端口及中断初始化*/
void PortInit(void)
{DDRC = 0xff;
PORTC=0xff;
DDRD=0xff;
PORTD=0x00;
/*T/C0*/
TCCR0A=0x00;
TIMSK0=0x01;
TCNT0=0xce; // (1024/16,000,000)*50=3.2ms
TCCR0B=0x05; // clk/1024
/*T/C1*/
TCCR1A=0x00;
TIMSK1=0x01;
TCNT1=0xfd8f; //10ms
TCCR1B=0x04; // clk/256
/*通信口初始化*/
UartInit();
}
/*数据转换函数*/
void convert(void)
{timeb1=time1/100;
timeb2=time1%100/10;
timeb3=time1%10;
timeb4=time2/100;
timeb5=time2%100/10;
timeb6=time2%10;
}
/*****************单总线时序**************/
/*初始化*/
void Init_1wire(void)
{flag = SREG; /*中断保护*/
CLI();
/*关中断*/
DRC(1); //Out
DQ(1);
NOP(); //DQ拉低480-960US,接着将数据线拉高15-60US
DQ(0);
delay_10us(56);
DQ(1);
DRC(0); //In 释放总线 此时上拉电阻使能
delay_10us(7);
while(PINC & 0x01);
delay_10us(50); //presence pulse 60-240us 480us min
if (flag & 0x80)
{SEI(); /*恢复中断状态*/
}
}
/*写字节*/
void WriteByte_1wire(uchar data)
{uchar i,temp;
temp=data;
flag = SREG; /*中断保护*/
CLI();
DRC(1);
for(i=0;i<8;i++)
{DQ(1);
NOP();
DQ(0); //写时间隙开始
delay_10us(1);
if(temp&0x01)DQ(1);
//else DQ(0);
temp>>=1; //LSB First
delay_10us(7);
}
DQ(1);
if (flag & 0x80)
{SEI(); /*恢复中断状态*/
}
}
/*读字节*/
uchar ReadByte_1wire(void)
{uchar i,data=0;
flag = SREG; /*中断保护*/
CLI();
for(i=0;i<8;i++)
{data>>=1; //处理方法:先右移 后将最高位与 0x80相或 !!!
DRC(1);
DQ(1);
NOP();
DQ(0);
delay_1us(); //delay 3us
delay_1us();
//DQ(1);
DRC(0);
delay_10us(1);
if(PINC&0x01)data|=0x80;
delay_10us(6);
}
DRC(1);
DQ(1);
if (flag & 0x80)
{SEI(); /*恢复中断状态*/
}
return(data);
}
/********************************************************/
/* n*10us
通过AVR Studio仿真*/
void delay_10us(uchar n)
{uchar i,j;
for(i=0;i<n;i++)
for(j=0;j<38;j++);
}
/* 1.75us */
void delay_1us(void)
{uchar i;
for(i=0;i<4;i++);
}
/********************************通信部分*************************/
void UartRece_int(void)
{if(count3<2)Rece[count3++]=UDR0;
else
{count3=0;
flag1=1;
}
}
/**************串口初始化函数*****************/
void UartInit(void)
{
/* 设置波特率*/
UBRR0H = 0x00; /*9600 U2X0=0 103*/
UBRR0L = 0x67;
/* 接收中断使能 接收器与发送器使能*/
UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
/* 设置帧格式: 8 个数据位, 1 个停止位 */
UCSR0C = (3<<UCSZ00);
}
/****************串行发送函数****************/
void UartSend(uchar a[],uchar length)
{uchar i;
for(i=0;i<length;i++)
{/* 等待发送缓冲器为空*/
while ( !( UCSR0A & (1<<UDRE0)) );
/* 将数据放入缓冲器,发送数据*/
UDR0=a[i];
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -