📄 temperature.c
字号:
#include "c8051f020.h"
#include "stdio.h"
#include "intrins.h"
#define READ_ROM 0x33 //读ROM
#define MATCH_ROM 0x55 //匹配ROM
#define SKIP_ROM 0xcc //跳过ROM
#define SEARCH_ROM 0xf0 //搜索ROM
#define ALARM_SEARCH 0xec //ROM发出警告
#define CONVERT_T 0x44 //启动温度转化
#define READ_SRAM 0xbe //读暂存存储器
#define WRITE_SRAM 0x4e //写暂存存储器
#define COPY_SRAM 0x48 //拷贝暂存存储器内容
#define RECALL_E2RAM 0xb8 //重新调用E2RAM
#define READ_POWER 0xb4 //读电源方式
#define SYSCLK 25000000
#define BAUDRATE 9600 //波特率默认为9600
#define BUFSIZE 256
#define RX0BUFSIZE 256 //缓冲区默认为256字节
#define TX0BUFSIZE 256
bit symbol=0; //温度的正负号 symbol=0 为正;symbol=1 为负
sbit Ds18b20_DQ=P0^4;
unsigned char SN[8];
unsigned char Rx0Buf[RX0BUFSIZE],Tx0Buf[TX0BUFSIZE];//串口0接收和发送缓冲区
int Rx0In, Rx0Out, Tx0In, Tx0Out; //循环缓冲区指针
int Tx0Count; //已发送的字节数
void Close_WDG(void);
void SYSCLK_Init(void);
void UART_Init(void);
void DispLED(char *DispBuf,char ShowDot);
void startConvertT(void);
unsigned int getT_matchDs18b20(char ID);
bit getSymbol();
void readSN(unsigned char SN[]);
void UART0_Init(void);
int ReadCom(char * buf, int num);
int WriteCom(char * buf, int num);
/*****************************************
*串口0读取函数
*第一个参数:指向读回的字符串存放的位置的指针
*第二个参数:要读取的字符个数
*返回成功读取的字符个数
*****************************************/
int ReadCom(unsigned char * buf, int num)
{
int count = 0;
while ((Rx0In != Rx0Out) && (count != num))
{
buf[count] = Rx0Buf[Rx0Out];
Rx0Out = (Rx0Out + 1) % RX0BUFSIZE;
count ++;
}
return count;
}
/*****************************************
*串口0发送函数
*第一个参数:要发送的字符串的首地址(指向要发送的字符串的指针)
*第二个参数:要发送的字节个数
*返回成功读取的字符个数
*****************************************/
int WriteCom(unsigned char * buf, int num)
{
int count = 0;
long i = 0;
if(num != 0)
{
for (count = 0; count < num; count ++)
{
Tx0Buf[Tx0In] = buf[count];
if((Tx0In + 1) % TX0BUFSIZE == Tx0Out) //the buffer is full
Tx0Out = (Tx0Out + 1) % TX0BUFSIZE; //replace the oldest data
Tx0In = (Tx0In + 1) % TX0BUFSIZE;
}
//begin to transmit
REN0 = 0;
TI0 = 1;
Tx0Count = 0;
while((Tx0In != Tx0Out) && (i < 60000000)) //wait for all the datas in transmit buffer sent out; or overtime
i ++;
//transmit has completed
REN0 = 1;
}
else{}
return Tx0Count;
}
//串口0中断服务程序
void UART0_ISR(void) interrupt 4
{
if (RI0 == 1) // handle receive function
{
RI0 = 0; // clear RX complete indicator
Rx0Buf[Rx0In] = SBUF0;
if((Rx0In + 1) % RX0BUFSIZE == Rx0Out) //如果满 则覆盖以前的数据
Rx0Out = (Rx0Out + 1) % RX0BUFSIZE; //保证有效数据的位数
Rx0In = (Rx0In + 1) % RX0BUFSIZE;
}
else if(TI0 == 1)
{
TI0 = 0;
if( Tx0Out != Tx0In ) //Transmit Buffer is not empty
{
SBUF0 = Tx0Buf[Tx0Out];
Tx0Out = (Tx0Out + 1) % TX0BUFSIZE;
Tx0Count ++; //calculate the number of the bytes having been sent
}
else{} //Transmit buffer is empty, do nothing
}
}
// 串口初始化函数
void UART0_Init()
{
//初始化缓冲区
Rx0In = Rx0Out = 0;
Tx0In = Tx0Out = 0;
//波特率初始化 使用timer1,两个串口波特率相同
TMOD |= 0x20; // timer1, mode2, 8-bit reload
TH1 = -(SYSCLK/BAUDRATE/16);// set Timer1 reload value for baudrate
//TL1 = TH1;
CKCON |= 0x10; // Timer1 uses SYSCLK as time base
PCON |= 0x80; // SMOD0 = 1;禁止UART0波特率/2功能
TR1 = 1; // start Timer1
//交叉开关分配
XBR0 |= 0x04; //UART0允许 RX0,TX0连到两端口上
XBR2 |= 0x40; //交叉开关允许
P0MDOUT |= 0x03;
P0 = 0;
SCON0 = 0x50; //UART0为方式1:8位,波特率由定时器1决定
T2CON &= ~(0x30); // use timer1 as bautrate generator
ES0 = 1; //允许串口0中断
}
void main(void)
{
long temperature=0;
unsigned int feedbackT;
unsigned char led[6];
bit sign;
int i;
int count;
// unsigned char getchar[256];
Close_WDG();//关闭看门狗
SYSCLK_Init();//系统时钟初始化
UART0_Init(); // 串口初始化函数
EA = 1;
UART_Init();//串口初始化
readSN(SN); //读取DS18B20序列号,写入SN[]
while(1)
{
temperature=0;
for(i=0;i<40;i++)
{
startConvertT(); //开始温度转换
feedbackT=getT_matchDs18b20(0);//获取温度值
sign =getSymbol();//获取温度的正、负
if(sign)
temperature -=feedbackT;
else
temperature +=feedbackT;
}
sprintf(led,"%6d",(int)(temperature/40));
count = WriteCom(led, sizeof(led));
DispLED(led,3);
}
}
void Delay1us(int us) //延时us毫秒
{
while (us)
{
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
--us;
}
}
//发复位脉冲
//返回: 0-有设备连接 1-无设备连接
bit resetDs18b20(void)
{
unsigned char i;
bit RstFlag;
RstFlag=1;
Ds18b20_DQ=0;
Delay1us(600);
Ds18b20_DQ=1;
Delay1us(60); //15us-60us
for (i=0;i<16;i++) //60us-240us
{
Delay1us(15);
if (Ds18b20_DQ==0) RstFlag=0;
}
Delay1us(240); //240us
return RstFlag;
}
//向DS18b20写一个字节ch
void writeByteToDs18b20(unsigned char ch)
{
unsigned char i;
Ds18b20_DQ=1;
Delay1us(1);
for (i=0;i<8;i++)
{
Ds18b20_DQ=0;
Delay1us(15);
Ds18b20_DQ=ch&0x1;
Delay1us(45);
Ds18b20_DQ=1;
ch=ch>>1;
Delay1us(1);
}
}
//接收DS18b20传送来的一个字节并返回
unsigned char readByteFromDs18b20(void)
{
unsigned char i,ch;
ch=0;
Ds18b20_DQ=1;
Delay1us(1);
for (i=0;i<8;i++)
{
Ds18b20_DQ=0;
Delay1us(10);
Ds18b20_DQ=1;
Delay1us(2);
ch=ch>>1;
if (Ds18b20_DQ==1)
{
ch=ch+0x80;
}
Delay1us(45);
}
return ch;
}
//跳过ROM区
void skipROMCode(void)
{
resetDs18b20();
writeByteToDs18b20(SKIP_ROM);
}
//启动DS18b20的温度转化功能
void startConvertT(void)
{
resetDs18b20(); //复位
writeByteToDs18b20(SKIP_ROM); //广播
writeByteToDs18b20(CONVERT_T); //启动AD转换12bit700ms
}
//读取DS18b20的序列号,更新SN[]
void readSN(unsigned char SN[])
{
char i;
while(resetDs18b20());
writeByteToDs18b20(READ_ROM); //读取ROM
for(i=0;i<8;i++)
{
SN[i]=readByteFromDs18b20();
}
}
//发送序列号并匹配
void matchDs18b20(char ID)
{
unsigned char i;
writeByteToDs18b20(MATCH_ROM); //匹配ROM
for ( i = 0; i < 8; i++ )
writeByteToDs18b20(SN[i]);
}
//获取温度值
unsigned int getTempValue(void)
{
unsigned char low,high;
unsigned int T;
writeByteToDs18b20(READ_SRAM);
low=readByteFromDs18b20();
high=readByteFromDs18b20();
T =low+high*256;
if((high & 0xf8)!=0)
symbol=1;
else symbol=0;
if(symbol) //温度为负
T =-T;
T =T&0x07ff;
T =(T/16.0)*100;
return T;
}
//读取与指定的DS18b20相匹配的温度值
unsigned int getT_matchDs18b20(char ID)
{
unsigned int T;
int i;
for(i=0;i<30000;i++);//延时等待转换结束
resetDs18b20(); //复位
skipROMCode();
writeByteToDs18b20(CONVERT_T);
Delay1us(2); //2us
resetDs18b20(); //复位
matchDs18b20(ID);
T=getTempValue();
return(T);
}
//返回温度的正负号
bit getSymbol()
{
return symbol;
}
void UART_Init(void)
{
//初始化缓冲区
Rx0In = Rx0Out = 0;
Tx0In = Tx0Out = 0;
//波特率初始化 使用timer1,两个串口波特率相同
TMOD |= 0x20; // timer1, mode2, 8-bit reload
TH1 = -(SYSCLK/BAUDRATE/16);// set Timer1 reload value for baudrate
//TL1 = TH1;
CKCON |= 0x10; // Timer1 uses SYSCLK as time base
PCON |= 0x80; // SMOD0 = 1;禁止UART0波特率/2功能
TR1 = 1; // start Timer1
XBR0=0x04;
XBR2=0x44;
SCON1=0x00;
P0MDOUT=0xFF;
SCON0 = 0x50; //UART0为方式1:8位,波特率由定时器1决定
T2CON &= ~(0x30); // use timer1 as bautrate generator
ES0 = 1; //允许串口0中断
}
/*********************************************************
功能:在六位数码管显示要求的字符串 含标点
*DispBuf:要显示的字符串,长度为6
ShowDot:标点的位置
0:不显示
1~6:标点显示在数码管的对应位
*********************************************************/
unsigned char code table[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,
0xf6,0xee,0x3e,0x9a,0x7c,0x9e,0x8e,0x04,0x00};
void DispLED(char *DispBuf,char ShowDot)//ShowDot 显示小数点位
{
char ch;
int i=0,j;
ShowDot=6-ShowDot; //显示小数点
SCON1=0x20;
for(i=5;i>=0;i--)
{
ch=DispBuf[i];
if ((ch>='a') && (ch<='f')) //转换ASCII码为对应段码
{ ch-='a';ch+=10;}
else if ((ch>='A') && (ch<='F'))
{ ch-='A';ch+=10;}
else if ((ch>='0') && (ch<='9'))
ch-='0';
else if (ch=='-') //显示负号
ch=16;
else
ch=17;
if (i==ShowDot) //显示小数点
SBUF1=table[ch]+1;
else
SBUF1=table[ch];
for(j=0;j<255;j++); //延时
if(i==0) //清除串口中断
SCON1=0;
}
}
/*****************************************
Function:initiate the system clock
*****************************************/
void SYSCLK_Init(void)
{
int i;
OSCXCN=0x67; // start external oscillator with 22.1184MHz crystal
for(i=0;i<256;i++); // XTLVLD blanking interval (>1ms)
while(!(OSCXCN&0x80)); // Wait for crystal osc. to settle
OSCICN=0x88; // select external oscillator as SYSCLK
// source and enable missing clock
}
void Close_WDG()
{
WDTCN=0xde; // disable watchdog timer
WDTCN=0xad;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -