📄 shiyan4.c
字号:
/**********************************************/
//
// 单个DS18B20数字温度计测温C程序
// (测温范围-30~110℃,误差在±0.0625℃)
// 2008.5.2通过调试
/**********************************************/
#include<math.h> /*数学函数库*/
#include<absacc.h> /*绝对地址访问函数*/
#include<intrins.h> /*内部函数*/
#include"C8051F040.h" /*C8051F040头文件*/
#define Decoding 0x09 /*译码模式*/
#define Brightness 0x0A /*亮度*/
#define BoundaryScan 0x0B /*扫描界限*/
#define Brownout 0x0C /*掉电模式*/
#define DisplayTest 0x0F /*显示测试*/
//#define tempp 0x00
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
//显示部分
uchar xdata dispbuff[7];
//uchar xdata pbuff[7];
uchar bit_sym=0,bit_int,bit_dec,bit_all; /*符号位,整数位,小数位及全部位数*/
float xdata part_dec; /*小数部分*/
ulong xdata part_int,part_dec_int;/*整数部分和小数部分取整*/
uchar num[13]={0x7E,0x30,0x6D,0x79,0x33,0x5B,0x5F,0x70,0x7F,0x7B,0x00,0xFF,0x01};/*从0~9及全灭,全亮和"-"*/
sbit dis_LOAD=P3^2; /*MAX7219 Load-Data Input: rising edge*/
sbit dis_DIN=P3^0; /*MAX7219 Serial-Data Input: rising edge*/
sbit dis_CLK=P3^3; /*MAX7219 Serial-Clock Input: maximum 10MHz*/
//DS18B20数据输入端定义
sbit DQ=P6^7;
sbit k1=P3^4;
sbit k2=P3^5;
sbit k3=P3^6;
uchar key=0;
bit enflash=0;
uchar n=0;
uchar tempp=20;
uchar h;
uchar l;
//uchar code tempp;
//延时纳秒
void delayns(void)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
//传送1字节(8位)
void SendChar (uchar ch)
{
uchar i,temp;
dis_CLK=0;
for (i=0;i<8;i++)
{
temp=ch&0x80;
ch=ch<<1;
if(temp)
{
dis_DIN=1;
delayns();
dis_CLK=1;
delayns();
dis_CLK=0;
}
else
{
dis_DIN=0;
delayns();
dis_CLK=1;
delayns();
dis_CLK=0;
}
}
}
//向MAX7219写入字(16位)
void WriteWord (uchar addr,uchar num)
{
dis_LOAD=0;
delayns();
SendChar(addr);
delayns();
SendChar(num);
delayns();
dis_LOAD=1;
delayns();
}
//数值显示
void dis_result()
{
WriteWord(0x01,dispbuff[5]);
WriteWord(0x02,dispbuff[4]);
WriteWord(0x03,dispbuff[3]);
WriteWord(0x04,dispbuff[2]);
WriteWord(0x05,dispbuff[1]);
WriteWord(0x06,dispbuff[0]);
}
//利用递归法实现指数运算
ulong power(ulong number,uint index)reentrant
{
ulong result;
if(index==0) result=1;
else result=number*power(number,index-1);
return(result);
}
//数值计算
void disp(float f)
{
int i,j;
if(f<0.0)
{
bit_sym=1;
f=-f;
}
part_int=(long)f;
part_dec=f-(float)part_int;
part_dec_int=(long)(part_dec*100000);/*小数部分取整*/
bit_dec=5;/*小数部分的最多位数*/
bit_int=1;/*整数部分的最少位数*/
bit_all=1;/*总显示的最少位数*/
//计算小数位数
for(i=1;i<=5;i++)
{
if(part_dec_int%(power(10,i))==0)
bit_dec=bit_dec-1;
}
//计算整数位数
for(i=0;i<=5;i++)
{
if(part_int>=power(10,i))
bit_int=i+1;
}
//总的显示位数最多为6
if(bit_dec+bit_int+bit_sym>6)
bit_dec=6-bit_int-bit_sym;
//总的有效显示位数
bit_all=bit_sym+bit_int+bit_dec;
//不足位小数位后添零
if(6-bit_all>0)
bit_dec=6-bit_int-bit_sym;
//总的显示位数
bit_all=bit_sym+bit_int+bit_dec;
//显示小数位
if(bit_dec>0)
{
for(i=bit_dec-1,j=5;i>=0,j>=1;i--,j--)
{
dispbuff[i]=num[(part_dec_int%(power(10,j)))/(power(10,j-1))];
//dispbuff[i]=num[pbuff[i]];
/*该语句实现对各位的求取*/
}
}
//显示整数位
for(i=bit_all-bit_sym-1,j=bit_int;i>=bit_dec,j>=1;i--,j--)
{
dispbuff[i]=num[(part_int%(power(10,j)))/(power(10,j-1))];
//dispbuff[i]=num[pbuff[i]];
}
//显示符号位
if(bit_sym==1)
dispbuff[bit_all-1]=12;
//小数点位置
if(bit_dec>0)
dispbuff[bit_dec]=dispbuff[bit_dec]+0x80;
}
//延时
void Delay1us(uchar us)
{
while(us)
{
_nop_();_nop_();_nop_();_nop_();_nop_();
--us;
}
}
//延时15uS
void Delay15us(void)
{
Delay1us(15);
}
void Delay10us(void)
{
Delay1us(10);
}
//返回0,有设备连接;返回1,无设备连接
bit RstDS18B20(void)
{
uchar i;
bit RstFlag=1;
DQ=0;
for(i=0;i<40;i++) /*延时480us*/
{
Delay15us();
}
DQ=1;
for(i=0;i<4;i++) /*延时15~60us*/
{
Delay15us();
}
for(i=0;i<16;i++) /*延时60~240us*/
{
Delay15us();
if(DQ==0) RstFlag=0;
}
for(i=0;i<16;i++) /*240us*/
{
Delay15us();
}
return RstFlag;
}
void WriteDS18B20(uchar val)
{
uchar i;
DQ=1;
Delay1us(1);
for(i=0;i<8;i++)
{
DQ=0;
Delay15us();
DQ=val&0x01;
Delay15us();Delay15us();Delay15us();
DQ=1;
val=val/2;
Delay1us(1);
}
}
uchar ReadDS18B20(void)
{
uchar i,value=0;
DQ=1;
Delay1us(1);
for(i=0;i<8;i++)
{
DQ=0;
Delay1us(4);
DQ=1;
Delay10us();
value>>=1;
if(DQ==1)
{
value|=0x80;
}
Delay15us();Delay15us();Delay15us();
}
return(value);
}
//主机发送跳过读序列号的操作命令:0xCC
void SkipROMCode(void)
{
RstDS18B20();
WriteDS18B20(0xCC);
}
void StartADC(void)
{
RstDS18B20(); /*复位*/
WriteDS18B20(0xCC); /*skip ROM*/
WriteDS18B20(0x44); /*启动温度转换12位700ms*/
}
//读取温度值的程序
float GetTempValue(void)
{
uchar i,j;
float T;
SkipROMCode();
WriteDS18B20(0xBE); /*发布读取温度值的命令(0xBE)*/
i=ReadDS18B20();
j=ReadDS18B20();
StartADC();
T=i+j*256;
if(T==0xFFFF) return 0xFFFF;
if(T>0x8000) /*温度为负号*/
return((T-65536)/16.0); /*计算温度值*/
else /*温度为正*/
return(T/16); /*计算温度值*/
}
void InitDS18B20(void)
{
SkipROMCode();
WriteDS18B20(0x44);
}
void sleep_ms(uint count)
{
int ii,jj;
for(ii=0;ii<count;ii++)
{
for(jj=0;jj<250;jj++)
_nop_();
}
}
void ConfigC8051F040()
{
int i; /*延时计数器*/
//看门狗禁止
WDTCN=0x07; /*设置看门狗超时间隔*/
WDTCN=0xDE;
WDTCN=0xAD;
//交叉开关使能配置,使得P0~P3口能输出
SFRPAGE=0x0F;
XBR0=0x00;
XBR1=0x00;
XBR2=0x40;
XBR3=0x00;
//管脚输出配置
SFRPAGE=0x0F;
P3MDOUT=0x0F; /*P3[3:0]推挽输出,用以显示部分*/
//晶振配置
SFRPAGE=0x0F;
OSCXCN=0x77;
/*配置为外部石英晶振2分频模式,且配置相应频率的驱动电流*/
for(i=0;i<256;i++); /*等待外部晶振稳定*/
while(!(OSCXCN & 0x80));
/*查询XTLVLD是否为1,若为1,表明外部晶振稳定,可切换到外部时钟*/
CLKSEL=0x01; /*选择外部晶振*/
OSCICN=0x00; /*将内部晶振关闭,也可不关闭,不关闭时MCU耗能高*/
}
//MAX7219初始化
void InitDis (void)
{
WriteWord(Brownout,0x00); /*设置电源工作模式*/
WriteWord(BoundaryScan,0x06); /*设置扫描界限*/
WriteWord(Brightness,0x05); /*设置亮度*/
WriteWord(Decoding,0x00); /*设置译码模式*/
WriteWord(DisplayTest,0x00); /*设置非测试模式*/
WriteWord(Brownout,0x01); /*设置电源工作模式*/
}
void flashtempp(uchar input_date)
{
uchar xdata *pDate=0x00;
//pDate=0x00;
FLSCL=0x01;
PSCTL|=0x07;
*pDate=0x01;
PSCTL=0x05;
*pDate=input_date;
PSCTL=0x04;
FLSCL=0x00;
}
uchar flash_read(void)
{
uchar xdata *pDate=0x00;
uchar t;
// PSCTL=0x04;
t=*pDate;
PSCTL=0x00;
return t;
}
void KeyScan(void)
{
bit k;
k=k1&k2&k3;
if(!k)
{
if(k1==0)
{
sleep_ms(100);
if(k1==0)do{}while(!k1);
key=1;
return;
}
if(k2==0)
{
sleep_ms(100);
if(k2==0)do{}while(!k2);
key=2;
return;
}
if(k3==0)
{
sleep_ms(100);
if(k3==0)do{}while(!k3);
key=3;
return;
}
}
}
void eflash(void)
{
if(enflash)
{
switch(n)
{
case 1:WriteWord(1,num[h]);
sleep_ms(400);
WriteWord(1,0x00);
sleep_ms(400);
break;
case 2:WriteWord(2,num[l]);
sleep_ms(400);
WriteWord(2,0x00);
sleep_ms(400);
break;
}
}
}
void k1_handle(void)
{
n++;
key=0;
if(n==3)enflash=0;
else enflash=1;
}
void k2_handle(void)
{
key=0;
switch(n)
{
case 1:h++;
if(h==0x0a)h=0x00;
//tempp+=10;
break;
case 2:l++;
if(l==0x0a)l=0x00;
//tempp+=1;
break;
}
}
void k3_handle(void)
{
key=0;
switch(n)
{
case 1:if(h==0)h=9;
else h--;
break;
case 2:if(l==0)l=9;
else l--;
break;
}
}
void KeyProcess(void)
{
KeyScan();
if(key==1)
{
disp(tempp);
dis_result();
do
{
tempp=h*10+l;
WriteWord(0x01,num[h]);
WriteWord(0x02,num[l]);
k1_handle();
if(n==3)
{
n=0;
break;
}
do
{
eflash();
KeyScan();
switch(key)
{
case 1:break;
case 2:k2_handle();
do
{
eflash();
KeyScan();
}while(key==0);
break;
case 3:k3_handle();
do
{
eflash();
KeyScan();
}while(key==0);
break;
}
}while(key!=1);
}while(n!=3);
return;
}
}
main()
{
float temp;
ConfigC8051F040();
WriteWord(0x07,0x04);/*LED灯显示*/
InitDis();
InitDS18B20();
//flashtempp(20);
for(;;)
{
tempp=flash_read();
h=tempp/10;
l=tempp%10;
sleep_ms(250);
sleep_ms(250);
sleep_ms(250);
temp=GetTempValue();
disp(temp);
dis_result();
KeyProcess();
flashtempp(tempp);
sleep_ms(250);
sleep_ms(250);
_nop_();
sleep_ms(250);
sleep_ms(250);
}
}
//***************************结束*******************************//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -