?? main.c
字號(hào):
// ICC-AVR application builder : 2007-6-12 17:11:46
// Target : M16
// Crystal: 7.3728Mhz
// AVR與虛擬儀器 http://www.avrvi.com
// 用途: DS18B20 演示程序
// 連接: 電源跳線,晶振跳線(一定要使用7.3728M晶振),DS18B20 接PD3,串口跳線連接
// 使用串口延長線連接PC和開發(fā)板,在串口調(diào)試助手里面觀察,發(fā)回的值,用手捏住18B20,可以看到值變大
#include <iom16v.h>
#include <macros.h>
#define F_CPU 7372800
//數(shù)據(jù)類型的定義
#define uint8 unsigned char
#define uint16 unsigned int
//位變量操作宏定義
#define BIT_SET(a,b) a|=BIT(b)
#define BIT_CLR(a,b) a&=~BIT(b)
#define BIT_INV(a,b) a^=BIT(b)
#define BIT_STATUS(a,b) a&BIT(b)
//DS18B20操作定義
#define CLR_DS18B20 BIT_CLR(PORTD,PD3) //數(shù)據(jù)線強(qiáng)制拉低
#define SET_DS18B20 BIT_SET(PORTD,PD3) //數(shù)據(jù)線強(qiáng)制拉高,上拉
#define HLD_DS18B20 BIT_SET(DDRD,PD3) //Mega16控制總線
#define RLS_DS18B20 BIT_CLR(DDRD,PD3) //釋放總線
#define STU_DS18B20 BIT_STATUS(PIND,PD3) //數(shù)據(jù)線的狀態(tài)
void port_init(void)
{
PORTA = 0xFF;
DDRA = 0x00;
PORTB = 0xFF;
DDRB = 0xFF; //輸出
PORTC = 0xFF; //m103 output only
DDRC = 0xFF; //輸出
DDRD = 0xFF;
PORTD = 0xFF;
}
/**********************************************************************
functionName: void delayUs(BYTE temp)
description :延時(shí)函數(shù) 晶振頻率:7.3728MHZ
delayUs(1); //2.71us
delayUs(2); //3.53us
delayUs(4); //5.15us
delayUs(8); //8.41us
delayUs(16); //14.92us
delayUs(32); //27.94us
delayUs(64); //53.98us
delayUs(128); //106.07us
delayUs(255); //209.42us
delayUs(18); //16.55us
delayUs(34); //29.57us
delayUs(35); //30.38us
delayUs(100); //83.28
_NOP(); //0.14us
**********************************************************************/
void delayUs(uint8 temp)
{
while(temp--);
}
//延時(shí)約1s
void longdelay(void)
{
unsigned int i;
for(i=4761;i!=0;i--)
delayUs(255);
}
/*******************************************************************************
functionName: uint8 resetDS18B20(void)
description :DS18B20初始化
********************************************************************************/
uint8 resetDS18B20(void)
{
uint8 errTime=0;
RLS_DS18B20; //釋放總線
_NOP();
HLD_DS18B20; //Maga16控制總線
CLR_DS18B20; //強(qiáng)制拉低
delayUs(255); //209.42us
delayUs(255); //209.42us
delayUs(255); //83.28us
//以上的三個(gè)延時(shí)大于480us
RLS_DS18B20; //釋放總線,總線自動(dòng)上拉
_NOP();
while(STU_DS18B20)
{
delayUs(4); //5.15us
errTime++;
if(errTime>20)
return(0x00); //如果等帶大于約 5.15us*20就返回0x00,報(bào)告復(fù)位失敗(實(shí)際上只要等待15-60us)
}
errTime=0;
while(!(STU_DS18B20))
{
delayUs(4); //5.15us
errTime++;
if(errTime>50)
return(0x00); //如果等帶大于約 5.15us*50就返回0x00,報(bào)告復(fù)位失敗(實(shí)際上只要等待60-240us)
}
return(0xff);
}
/**********************************************************************
functionName: uint8 readuint8DS18B20(void)
description :讀DS18B20一個(gè)字節(jié)
**********************************************************************/
uint8 readuint8DS18B20(void)
{
uint8 i;
uint8 retVal=0;
RLS_DS18B20; //釋放總線
for(i=8;i>0;i--)
{
retVal>>=1;
HLD_DS18B20; //Maga16控制總線
CLR_DS18B20; //強(qiáng)制拉低
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP(); //延時(shí)大于1us
RLS_DS18B20; //釋放總線,DS18B20會(huì)將總線強(qiáng)制拉低
NOP();
NOP();
NOP();
if(STU_DS18B20)
retVal|=0x80;
delayUs(16); //14.92us
delayUs(16); //14.92us
RLS_DS18B20; //釋放總線
delayUs(35); //30.38us
}
delayUs(1); //2.71us(大于1us就行了)
return(retVal);
}
/*******************************************************************************
functionName: uint8 readuint8DS18B20(void)
description :寫DS18B20一個(gè)字節(jié)
********************************************************************************/
void writeuint8DS18B20(uint8 wb)
{
uint8 i;
uint8 temp;
RLS_DS18B20; //釋放總線
for(i=0;i<8;i++)
{
HLD_DS18B20; //Maga16控制總線
CLR_DS18B20; //強(qiáng)制拉低
delayUs(16); //14.92us
temp=wb>>i;
temp&=0x01;
if(temp)
RLS_DS18B20; //釋放總線
else
CLR_DS18B20; //強(qiáng)制拉低
delayUs(16); //14.92us
delayUs(35); //30.38us
RLS_DS18B20; //釋放總線
delayUs(1); //2.71us(大于1us就行了)
}
}
/*******************************************************************************
functionName: unsigned int readTempDS18B20(void)
description :讀DS18B20溫度
********************************************************************************/
unsigned int readTempDS18B20(void)
{
uint8 tempL,tempH;
uint16 x;
resetDS18B20();
writeuint8DS18B20(0xcc); //跳過ROM
writeuint8DS18B20(0x44); //啟動(dòng)溫度轉(zhuǎn)換
delayUs(1);
resetDS18B20();
writeuint8DS18B20(0xcc); //跳過ROM
writeuint8DS18B20(0xbe); //讀數(shù)據(jù)
tempL=readuint8DS18B20();
tempH=readuint8DS18B20();
x=(tempH<<8)|tempL;
return(x);
}
/*******************************************************************************
串口操作相關(guān)函數(shù)
*******************************************************************************/
void USART_Init( unsigned int baud )
{
unsigned int tmp;
/* 設(shè)置波特率*/
tmp= F_CPU/baud/16-1;
UBRRH = (unsigned char)(tmp>>8);
UBRRL = (unsigned char)tmp;
/* 接收器與發(fā)送器使能*/
UCSRB = (1<<RXEN)|(1<<TXEN);
/* 設(shè)置幀格式: 8 個(gè)數(shù)據(jù)位, 2 個(gè)停止位*/
UCSRC = (1<<URSEL)|(1<<USBS)|(1<<UCSZ0)|(1<<UCSZ1);
}
// 數(shù)據(jù)發(fā)送【發(fā)送5 到8 位數(shù)據(jù)位的幀】
void USART_Transmit( unsigned char data )
{
/* 等待發(fā)送緩沖器為空 */
while ( !( UCSRA & (1<<UDRE)) )
;
/* 將數(shù)據(jù)放入緩沖器,發(fā)送數(shù)據(jù) */
UDR = data;
}
uint16 i; //讀溫度值的暫存變量
void main(void)
{
unsigned char temp=0;
port_init();
USART_Init(9600); //波特率9600 初始化串口
USART_Transmit('O');
USART_Transmit('K');
while(1)
{
i=resetDS18B20();
i=readTempDS18B20();
//下面開始對讀到的數(shù)進(jìn)行處理,說明,這里用的一位精度
if(i&(1<<3)) //判斷倒數(shù)第四位是1還是0
{
temp=i>>4+1;
}
else
{
temp=i>>4;
}
USART_Transmit(temp); //結(jié)果發(fā)到串口中
longdelay(); //等待1S
}
}
/*
假設(shè)你只要精確到1度
換算溫度用很簡單的方法就可以處理:
首先判斷是正溫度還是負(fù)溫度
然后判斷倒數(shù)第四位是1還是0
如果是1且溫度為正,那么 溫度=x>>4+1;
如果是1且溫度為負(fù),那么 溫度=x>>4-1;
如果是0,溫度=x>>4;
這樣的操作可以節(jié)省很多的flah空間。
*/
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -