#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define KEYPORT P3 //键盘扫描端口
uchar sccode,recode;
unsigned int value;
unsigned int a0, b0,a1,b1,a2,b2;//PWM变量输出控制变量
//3路PWM输出端口
sbit PWMR=P2^0;
sbit PWMG=P2^1;
sbit PWMB=P2^2;
//DS18B20接口
sbit ds= P2^3;
//0-F数码管的编码(共阴极)
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//0-9数码管的编码(共阴极), 带小数点
unsigned char code tableWidthDot[]={0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd,
0x87, 0xff, 0xef};
//数码管选位短
unsigned char code table1[]={0x7f,0xbf,0xdf};
//延时函数, 例i=10,则大概延时10ms.
void delay(unsigned char i)
{
unsigned char j, k;
for(j = i; j > 0; j--)
{
for(k = 125; k > 0; k--);
}
}
static void vDelay_uint(uint m)
{
for (;m>0;m--);
}
//去抖延时函数,用作连续按键的延时
uchar ucKb4X4_Scan(void)
{ uint m;
//sccode表示行,recode表示列,ucKeyVal表示返回码
KEYPORT=0xf0; //付初值KEYPORT = 11110000
if ((KEYPORT&0xf0)!=0xf0) //判断是否有按键,有按键则不为初值
{
vDelay_uint(200); //延时去抖动
if ((KEYPORT&0xf0)!=0xf0)
{
sccode=0xfe; //使sccode = 11111110
while ((sccode&0x10)!=0) //用于循环4次因为是4*4键盘
{
KEYPORT=sccode;
if ((KEYPORT&0xf0)!=0xf0) //判断按键是否在此行
{
recode=(KEYPORT&0xf0)|0x0f; //确定列的位置
for (m=0;((KEYPORT&0xf0)!=0xf0)&&(m<10000);m++);
//用m做一个10000次的延迟,(P1&0xf0)!=0xf0用于判定是否还在按着,
//如果是延迟20000次返回一次值码
vDelay_uint(10000); //延时10000次,共20000次返回一次值码
return((~sccode)+(~recode)); //返回按键码
}
else
sccode=(sccode<<1)|0x01; //不在此行下移一行
}
}
}
return(0); //无按键返回0
}
//3路PWM定时器波形输出
void time0() interrupt 1
{
TL0 = (65536-200) % 256;
TH0 = (65536-200) / 256;
a0++;
if(a0 == 20)
a0 = 0; //在这里调整周期.
if(a0 < b0)
PWMR = 1; //在这里调整占空比.
else
PWMR=0;
}
void time1() interrupt 3
{
TL1 = (65536-200) % 256;
TH1 = (65536-200) / 256;
a1++;
if(a1 == 20)
a1 = 0; //在这里调整周期.
if(a1 < b1)
PWMG = 1; //在这里调整占空比.
else
PWMG = 0;
}
void time2() interrupt 5
{
TF2 = 0; //定时器2必须由软件对溢出标志位清零,硬件不能清零
TL2 = (65536-200) % 256;
TH2 = (65536-200) / 256;
a2++;
if(a2 == 20)
a2 = 0; //在这里调整周期.
if(a2 < b2)
PWMB = 1; //在这里调整占空比.
else
PWMB = 0;
}
//初始化DS18B20
//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动
void dsInit()
{
//一定要使用unsigned int型, 一个i++指令的时间, 作为与DS18B20通信的小时间间隔
//以下都是一样使用unsigned int型
unsigned int i;
ds = 0;
i = 103;
while(i>0) i--;
ds = 1;
i = 4;
while(i>0) i--;
}
//向DS18B20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,
//之后DS18B20则会输出持续一段时间的一位数据
bit readBit()
{
unsigned int i;
bit b;
ds = 0;
i++;
ds = 1;
i++; i++;
b = ds;
i = 8;
while(i>0) i--;
return b;
}
//读取一字节数据, 通过调用readBit()来实现
unsigned char readByte()
{
unsigned int i;
unsigned char j, dat;
dat = 0;
for(i=0; i<8; i++)
{
j = readBit();
//最先读出的是最低位数据
dat = (j << 7) | (dat >> 1);
}
return dat;
}
//向DS18B20写入一字节数据
void writeByte(unsigned char dat)
{
unsigned int i;
unsigned char j;
bit b;
for(j = 0; j < 8; j++)
{
b = dat & 0x01;
dat >>= 1;
//写"1", 让低电平持续2个小延时, 高电平持续8个小延时
if(b)
{
ds = 0;
i++; i++;
ds = 1;
i = 8; while(i>0) i--;
}
else //写"0", 让低电平持续8个小延时, 高电平持续2个小延时
{
ds = 0;
i = 8; while(i>0) i--;
ds = 1;
i++; i++;
}
}
}
//向DS18B20发送温度转换命令
void sendChangeCmd()
{
dsInit(); //初始化DS18B20
delay(1); //延时1ms
writeByte(0xcc); //写入跳过序列号命令字
writeByte(0x44); //写入温度转换命令字
}
//向DS18B20发送读取数据命令
void sendReadCmd()
{
dsInit();
delay(1);
writeByte(0xcc); //写入跳过序列号命令字
writeByte(0xbe); //写入读取数据令字
}
//获取当前温度值
unsigned int getTmpValue()
{
unsigned int value; //存放温度数值
float t;
unsigned char low, high;
sendReadCmd();
//连续读取两个字节数据
low = readByte();
high = readByte();
//将高低两个字节合成一个整形变量
value = high;
value <<= 8;
value |= low;
//DS18B20的精确度为0.0625度, 即读回数据的最低位代表0.0625度
t = value * 0.0625;
//将它放大10倍, 使显示时可显示小数点后一位, 并对小数点后第二2进行4舍5入
//如t=11.0625, 进行计数后, 得到value = 111, 即11.1 度
value = t * 10 + 0.5;
return value;
}
//显示当前温度值, 精确到小数点后一位
void display(unsigned int v)
{
unsigned char count;
unsigned char datas[] = {0, 0, 0};
datas[0] = v / 100;
datas[1] = v % 100 / 10;
datas[2] = v % 10;
for(count = 0; count < 3; count++)
{
if(count != 1)
{ P1=table1[count];
P0 = table[datas[count]]; //显示数字
delay(50);
}
else
{ P1=table1[count];
P0 = tableWidthDot[datas[count]]; //显示带小数点数字
delay(50);
}
}
}
void main()
{
TMOD = 0x01; //T0定时方式1
TR0 = 1;
TR1 = 1;
TR2 = 1;
ET0 = 1;
ET1 = 1;
ET2 = 1;
EA = 1;
a0 = 0;
a1 = 0;
a2 = 0;
while(1)
{
ucKb4X4_Scan();
switch((~sccode)+(~recode))
{
case 0x11:
b0=0;
b1=0;
b2=0;
break;
case 0x21:
b0=0;
b1=20;
b2=20;
break;
case 0x41:
b0=0;
b1=7;
b2=20;
break;
case 0x81:
b0=0;
b1=0;
b2=20;
break;
case 0x12:
b0=20;
b1=0;
b2=20;
break;
case 0x22:
b0=20;
b1=0;
b2=0;
break;
case 0x42:
b0=20;
b1=20;
b2=0;
break;
case 0x82:
b0=10;
b1=15;
b2=2;
break;
}
}
}
这个程序要怎么修改,才能正常的显示温度,也不影响PWM的输出,请哪位大侠帮帮忙 |