📄 ds18b20.c
字号:
/*
数字温度传感器DS18b20试验
试验准备:用连接线将JH端子的DS12B80位与CN7或CN8的P37口相连
运行此程序,温度值将在数码管上显示.用手触摸T1芯片(DS18B20)
观察温度变化.
*/
#include <c8051f020.h> // SFR declarations
#include <intrins.h>
#define WRITE 0x00 // WRITE direction bit
#define READ 0x01 // READ direction bit
#define CHIP_B 0x70
#define SMB_START 0x08 // (MT & MR) START transmitted
#define SMB_RP_START 0x10 // (MT & MR) repeated START
#define SMB_MTADDACK 0x18 // (MT) Slave address + W transmitted;
// ACK received
#define SMB_MTADDNACK 0x20 // (MT) Slave address + W transmitted;
// NACK received
#define SMB_MTDBACK 0x28 // (MT) data byte transmitted; ACK rec'vd
#define SMB_MTDBNACK 0x30 // (MT) data byte transmitted; NACK rec'vd
#define SMB_MRADDACK 0x40 // (MR) Slave address + R transmitted;
// ACK received
#define SMB_MRADDNACK 0x48 // (MR) Slave address + R transmitted;
// NACK received
#define SMB_MRDBNACK 0x58 // (MR) data byte rec'vd; NACK transmitted
//-----------------------------------------------------------------------------------
//Global VARIABLES
//-----------------------------------------------------------------------------------
char COMMAND; // Holds the slave address + R/W bit for
char COMMAND1; // use in the SMBus ISR.
char WORD; // Holds data to be transmitted by the SMBus
unsigned char totalnumber,sendnumber; // OR data that has just been received.
unsigned char xdata SENDMODE; // that has just been received.
bit SM_BUSY; // This bit is set when a send or receive
// is started. It is cleared by the
// ISR when the operation is finished.
sbit DataPortDS1820 = P3^5;
unsigned char wr_data[8];
unsigned char rd_data[8];
void Delay1us(unsigned char us)
{
while (us)
{
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
--us;
}
/*
TCON &= ~0xc0; // STOP Timer1 and clear overflow flag
TMOD &= ~0xf0; // configure Timer1 to 16-bit mode
TMOD |= 0x10;
CKCON |= 0x10; // Timer1 counts SYSCLKs
TR1 = 0; // STOP Timer1
TH1 = (-SYSCLK/us) >> 8; // set Timer1 to overflow in us
TL1 = -SYSCLK/us;
TR1 = 1; // START Timer1
while (TF1 == 0); // wait for overflow
TF1 = 0; // clear overflow indicator
*/
}
void Delay15us(void)
{
Delay1us(15);
}
void Delay10us(void)
{
Delay1us(10);
}
bit RstDS1820(void) //返回0-有设备连接1-无设备连接
{
unsigned char i;
bit RstFlag;
RstFlag=1;
DataPortDS1820=0;
for (i=0;i<100/*40*/;i++) //480us
Delay15us();
DataPortDS1820=1;
for(i=0;i<4;i++) //15us-60us
{
Delay15us();
}
for (i=0;i<16;i++) //60us-240us
{
Delay15us();
if (DataPortDS1820==0) RstFlag=0;
}
for (i=0;i<16;i++) //240us
{
Delay15us();
}
return RstFlag;
}
void WriteDS1820(unsigned char ch)
{
unsigned char i;
DataPortDS1820=1;
Delay1us(1);
for (i=0;i<8;i++)
{
EA=0;
DataPortDS1820=0;
Delay15us();
DataPortDS1820=ch&0x1;
EA=1;
Delay15us();Delay15us();Delay15us();
DataPortDS1820=1;
ch=ch>>1;
Delay1us(1);
}
}
unsigned char ReadDS1820(void)
{
unsigned char i,ch;
ch=0;
DataPortDS1820=1;
Delay1us(1);
for (i=0;i<8;i++)
{
EA=0;
DataPortDS1820=0;
Delay10us();
DataPortDS1820=1;
Delay1us(2);
ch=ch>>1;
if (DataPortDS1820==1)
{
ch=ch+0x80;
}
EA=1;
Delay15us();Delay15us();Delay15us();
}
return ch;
}
void SkipROMCode(void)
{
RstDS1820();
WriteDS1820(0xcc);
}
void StartADC(void)
{
RstDS1820(); //复位
WriteDS1820(0xcc); //广播
WriteDS1820(0x44); //启动AD转换 12bit700ms
}
unsigned int GetTempValue(void)
{
unsigned char i,j;
unsigned int T;
SkipROMCode();
WriteDS1820(0xBE);
i=ReadDS1820();
j=ReadDS1820();
StartADC();
T=i+j*256;
if (T==0xffff) return 0xffff;
if (T>0x8000)
{
T=-T;
return(0x8000+T*5/8);
}
else
return(T*5/8);
}
void sleep_ms(unsigned int count)
{
unsigned char ii,jj;
for(ii=0;ii<count;ii++)
{
for(jj=0;jj<250;jj++)
_nop_();
}
}
void SYSCLK_Init (void)
{
int i; // delay counter
OSCXCN = 0x67; // start external oscillator with
// 18.432MHz crystal
for (i=0; i < 256; i++); // Wait for osc. to start up
while (!(OSCXCN & 0x80)); // Wait for crystal osc. to settle
OSCICN = 0x88; // select external oscillator as SYSCLK
// source and enable missing clock
// detector
//OSCICN = 0x07; //interal 16MHZ
}
void PORT_Init (void)
{
XBR0 = 0x07; // Enable SMBus, SPI0, and UART0
XBR2 = 0x44; // Enable crossbar and weak pull-ups
P0MDOUT = 0x15;
}
void SLA_SEND(char chip_select, char *wr_data, char number)
{
SENDMODE=0x01;
totalnumber=number;
sendnumber=number;
while(SM_BUSY); // Wait while SMBus is busy.
SM_BUSY = 1; // SMBus busy flag set.
SMB0CN = 0x44; // SMBus enabled, ACK low.
COMMAND = (chip_select | WRITE); // COMMAND = 7 address bits + WRITE.
//OP_CODE = out_op; // WORD = OP_CODE to be transmitted.
//WORD = out_data; // DATA = data to be transmitted.
STO = 0;
STA = 1; // Start transfer.
while(SM_BUSY);
}
void Init18b20(void)
{
SkipROMCode();
WriteDS1820(0x4e);
WriteDS1820(38);
WriteDS1820(20);
WriteDS1820(0x7f);
}
void main (void)
{
unsigned char temp;
unsigned int w;
unsigned char data Number[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
WDTCN = 0xde;
WDTCN = 0xad; //关看门狗
SYSCLK_Init (); //初始化时钟
PORT_Init (); //初始化IO口
Init18b20();
SMB0CN = 0x44; // Enable SMBus with acknowledge low (AA = 1)
SMB0CR = -80; // SMBus clock rate = 100 kHz
//SMB0ADR = MY_ADD; // Set own slave address.
EIE1 |= 2; // SMBus interrupt enable
SM_BUSY = 0; // Free bus for first transfer.
SI = 0;
EA=1; //开中断
for (;;)
{
sleep_ms(250);
sleep_ms(250);
sleep_ms(250);
w = GetTempValue();
wr_data[0] = 0x00;
wr_data[1] = 0x17;
wr_data[2] = 0x00;
temp = (w%1000)/100;
wr_data[3] = Number[temp];
temp = (w%100)/10;
wr_data[4] = Number[temp]|0x80;
temp = (w%10);
wr_data[5] = Number[temp];
SLA_SEND(CHIP_B,wr_data,0x06);
sleep_ms(250);
sleep_ms(250);
_nop_();
sleep_ms(250);
sleep_ms(250);
}
}
//------------------------------------------------------------------------------------
// SMBus Interrupt Service Routine
//------------------------------------------------------------------------------------
void SMBUS_ISR (void) interrupt 7
{
switch (SMB0STA){ // Status code for the SMBus
// (SMB0STA register)
// Master Transmitter/Receiver: START condition transmitted.
// Load SMB0DAT with slave device address. Mask out R/W bit since all transfers
// start with an OP_CODE write.
case SMB_START: //0x08
SMB0DAT = COMMAND ; // Load address of the slave to be accessed.
// Mask out R/W bit because first transfer
// will always be a write of the OP_CODE.
STA = 0; // Manually clear STA bit
SI = 0; // Clear interrupt flag
break;
// Master Transmitter/Receiver: Repeated START condition transmitted.
// This state only occurs during a READ, after the OP_CODE has been sent. Load
// device address + READ into SMB0DAT.
case SMB_RP_START: //0x10
SMB0DAT = COMMAND1;
STA = 0; // Manually clear START bit.
SI = 0;
break;
// Master Transmitter: Slave address + WRITE transmitted. ACK received.
// Load OP_CODE into SMB0DAT.
case SMB_MTADDACK: //0x18
SMB0DAT = wr_data[0];
SI = 0; // Clear interrupt flag
break;
// Master Transmitter: Slave address + WRITE transmitted. NACK received.
// The slave is not responding. Use ACK polling to retry.
case SMB_MTADDNACK: //0x20
STO = 1;
STA = 1;
SI = 0; // Clear interrupt flag
break;
// Master Transmitter: Data byte transmitted. ACK received.
// Check OP_CODE - If it is a READ code, send repeated START to begin
// read. If it is a WRITE code, load WORD into SMB0DAT for transfer.
// If it is not a valid code, then either 1) data has been transmitted
// and the transfer is finished, or 2) there is an error. In either case,
// send STOP and end transfer.
case SMB_MTDBACK: //0x28
switch (SENDMODE){ // Check only lower 4 bits.
// OP_CODE is a READ. Send repeated START.
case 1:
sendnumber--;
if(sendnumber)
SMB0DAT = wr_data[totalnumber-sendnumber];
else{
STO=1;
SM_BUSY=0;
}
//OP_CODE = 0; // Clear OP_CODE so transfer ends the next
break; // time this state occurs
case 0:
STO = 0;
STA = 1;
break; // (after data is sent).
default: // No valid OP_CODE. End transfer.
STO = 1;
SM_BUSY = 0;
break;
}
SI = 0;
break;
// Master Transmitter: Data byte transmitter. NACK received.
// Use ACK polling to retry transfer.
case SMB_MTDBNACK: //0x30
STO = 1;
STA = 1;
SI = 0; // Clear interrupt flag
break;
// Master Receiver: Slave address + READ transmitted. ACK received.
// Set to transmit NACK after next transfer since it will be the
// last (only) byte.
case SMB_MRADDACK: //0x40
AA = 0; // NACK sent during acknowledge cycle.
SI = 0;
break;
// Master Receiver: Slave address + READ transmitted. NACK received.
// Slave not responding. Send repeated START to try again.
case SMB_MRADDNACK: //0x48
STO = 0;
STA = 1;
SI = 0;
break;
// Master Receiver: Data byte received. NACK transmitted.
// Read operation has completed. Read data register and send STOP.
case SMB_MRDBNACK: //0x58
rd_data[0] = SMB0DAT;
STO = 1;
SM_BUSY = 0;
AA = 1; // Set AA for next transfer
SI = 0;
break;
// All other status codes invalid. Reset communication.
default:
STO = 1;
SM_BUSY = 0;
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -