运行程序 15f104e是1T运行速度,晶体速度11.0529M 使用12T芯片延时降低10倍 #include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
bit flag1s = 0; //1s 定时标志
unsigned char T0RH = 0; //T0 重载值的高字节
unsigned char T0RL = 0; //T0 重载值的低字节
void ConfigTimer0(unsigned int ms);
unsigned char code disp1[]={0xfe,0xb0,0xed,0xf9,0xb3,0xdb,0xdf,0xf0,0xff,0xfb}; //数字带点
unsigned char code disp2[]={0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b}; //数字不带点
unsigned char code disp3[]={0x0}; //不显示
unsigned char code disp4[]={0x4f}; //显示E
unsigned char code disp5[]={0x01}; //显示-
sbit Max7219_pinCLK = P3^2;
sbit Max7219_pinCS = P3^5;
sbit Max7219_pinDIN = P3^4;
sbit IO_18B20 = P3^3; //DS18B20 通信引脚
/* 软件延时函数,延时时间(t*10)us */
void DelayX10us(unsigned char t)
{
do {
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
while (--t);
}
//向MAX7219(U3)写入字节
void Write_Max7219_byte(uchar DATA)
{
uchar i;
Max7219_pinCS=0; //CS=0有效,CS=1锁存
for(i=8;i>=1;i--)
{
Max7219_pinCLK=0;
Max7219_pinDIN=DATA&0x80; //&10000000, 编译器对位操作的理解:非0即为1
DATA=DATA<<1;
Max7219_pinCLK=1; //上升沿把数据送出去
}
}
/*向M第一片MAX7219写入数据*/
void Write_Max7219(uchar add1,uchar dat1)
{
Max7219_pinCS=0;
Write_Max7219_byte(add1); //写入地址,即数码管编号
Write_Max7219_byte(dat1); //写入数据,即数码管显示数字
Max7219_pinCS=1;
}
/*初始化芯片*/
void Init_MAX7219(void)
{
Write_Max7219(0x09, 0x00); //译码方式:BCD码
Write_Max7219(0x0a, 0x03); //亮度
Write_Max7219(0x0b, 0x07); //扫描界限;8个数码管显示
Write_Max7219(0x0c, 0x01); //掉电模式:0,普通模式:1
Write_Max7219(0x0f, 0x00); //显示测试:1;测试结束,正常显示:0
Write_Max7219(1,disp3[0]);
Write_Max7219(2,disp3[0]);
Write_Max7219(3,disp3[0]);
Write_Max7219(4,disp3[0]);
}
/* 复位总线,获取存在脉冲,以启动一次读写操作 */
bit Get18B20Ack()
{
bit ack;
EA = 0; //禁止总中断
IO_18B20 = 0; //产生 500us 复位脉冲
DelayX10us(500);//50
IO_18B20 = 1;
DelayX10us(60); //延时 60us 6
ack = IO_18B20; //读取存在脉冲
while(!IO_18B20); //等待存在脉冲结束
EA = 1; //重新使能总中断
return ack;
}
/* 向 DS18B20 写入一个字节,dat-待写入字节 */
void Write18B20(unsigned char dat)
{
unsigned char mask;
EA = 0; //禁止总中断
for (mask=0x01; mask!=0; mask<<=1) //低位在先,依次移出 8 个 bit
{
IO_18B20 = 0; //产生 2us 低电平脉冲
_nop_();
_nop_();
if ((mask&dat) == 0) //输出该 bit 值
IO_18B20 = 0;
else
IO_18B20 = 1;
DelayX10us(60); //延时 60us
IO_18B20 = 1; //拉高通信引脚
}
EA = 1; //重新使能总中断
}
/* 从 DS18B20 读取一个字节,返回值-读到的字节 */
unsigned char Read18B20()
{
unsigned char dat;
unsigned char mask;
EA = 0; //禁止总中断
for (mask=0x01; mask!=0; mask<<=1) //低位在先,依次采集 8 个 bit
{
IO_18B20 = 0; //产生 2us 低电平脉冲
_nop_();
_nop_();
IO_18B20 = 1; //结束低电平脉冲,等待 18B20 输出数据
_nop_(); //延时 2us
_nop_();
if (!IO_18B20) //读取通信引脚上的值
dat &= ~mask;
else
dat |= mask;
DelayX10us(60); //再延时 60us
}
EA = 1; //重新使能总中断
return dat;
}
/* 启动一次 18B20 温度转换,返回值-表示是否启动成功 */
bit Start18B20()
{
bit ack;
ack = Get18B20Ack(); //执行总线复位,并获取 18B20 应答
if (ack == 0) //如 18B20 正确应答,则启动一次转换
{
Write18B20(0xCC); //跳过 ROM 操作
Write18B20(0x44); //启动一次温度转换
}
return ~ack; //ack==0 表示操作成功,所以返回值对其取反
}
/* 读取 DS18B20 转换的温度值,返回值-表示是否读取成功 */
bit Get18B20Temp(int *temp)
{
bit ack;
unsigned char LSB, MSB; //16bit 温度值的低字节和高字节
ack = Get18B20Ack(); //执行总线复位,并获取 18B20 应答
if (ack == 0) //如 18B20 正确应答,则读取温度值
{
Write18B20(0xCC); //跳过 ROM 操作
Write18B20(0xBE); //发送读命令
LSB = Read18B20(); //读温度值的低字节
MSB = Read18B20(); //读温度值的高字节
*temp = ((int)MSB << 8) + LSB; //合成为 16bit 整型数
}
return ~ack; //ack==0 表示操作应答,所以返回值为其取反值
}
/*****************************main.c 文件程序源代码******************************/
void main()
{
bit res;
int temp; //读取到的当前温度值
// int intT, decT; //温度值的整数和小数部分
unsigned char qian,bai,shi,ge;
float tp;
Init_MAX7219();
EA = 1; //开总中断
ConfigTimer0(10); //T0 定时 10ms
Start18B20(); //启动 DS18B20
while (1)
{
if (flag1s) //每秒更新一次温度
{
flag1s = 0;
res = Get18B20Temp(&temp); //读取当前温度
if (res) //读取成功时,刷新当前温度显示
{
if(temp< 0) //温度低于0度
{
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
qian = temp % 10000 / 1000;
bai = temp % 1000 / 100;
shi = temp % 100 / 10;
ge = temp % 10;
Write_Max7219(1,disp5[0]); // 显示 "-"
Write_Max7219(2,disp2[qian]);
Write_Max7219(3,disp1[bai]);
Write_Max7219(4,disp2[shi]);
}
else // 温度大于0度
{
tp=temp;
temp=tp*0.0625*100+0.5;
qian = temp % 10000 / 1000;
bai = temp % 1000 / 100;
shi = temp % 100 / 10;
ge = temp % 10;
if(qian>0) // 温度10度显示十位
{
Write_Max7219(1,disp2[qian]);
Write_Max7219(2,disp1[bai]);
Write_Max7219(3,disp2[shi]);
Write_Max7219(4,disp2[ge]);
}
if(qian<=0) // 温度10度以下显示个位不显示十位
{
Write_Max7219(1,disp3[qian]);
Write_Max7219(2,disp1[bai]);
Write_Max7219(3,disp2[shi]);
Write_Max7219(4,disp2[ge]);
}
}
}
else //读取失败时,提示错误信息
{
Write_Max7219(1,disp4[0]);
Write_Max7219(2,disp3[0]);
Write_Max7219(3,disp3[0]);
Write_Max7219(4,disp3[0]);
}
Start18B20(); //重新启动下一次转换
}
}
}
/* 配置并启动 T0,ms-T0 定时时间 */
void ConfigTimer0(unsigned int ms)
{
unsigned long tmp; //临时变量
tmp = 11059200 / 12; //定时器计数频率
tmp = (tmp * ms) / 1000; //计算所需的计数值
tmp = 65536 - tmp; //计算定时器重载值
tmp = tmp + 12; //补偿中断响应延时造成的误差
T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
T0RL = (unsigned char)tmp;
TMOD &= 0xF0; //清零 T0 的控制位
TMOD |= 0x01; //配置 T0 为模式 1
TH0 = T0RH; //加载 T0 重载值
TL0 = T0RL;
ET0 = 1; //使能 T0 中断
TR0 = 1; //启动 T0
}
/* T0 中断服务函数,完成 1 秒定时 */
void InterruptTimer0() interrupt 1
{
static unsigned char tmr1s = 0;
TH0 = T0RH; //重新加载重载值
TL0 = T0RL;
tmr1s++;
if (tmr1s >= 100) //定时 1s
{
tmr1s = 0;
flag1s = 1;
}
}
|