打印

单片机定时器输出PWM波与DS18B20时序冲突

[复制链接]
3357|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zx890129|  楼主 | 2012-3-27 11:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#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的输出,请哪位大侠帮帮忙

相关帖子

沙发
老鱼探戈| | 2012-3-27 11:47 | 只看该作者
我是打酱油的,什么都没看见。。。。

使用特权

评论回复
板凳
ayb_ice| | 2012-3-27 11:55 | 只看该作者
长城长

使用特权

评论回复
地板
coody| | 2012-3-27 16:28 | 只看该作者
用带硬件PWM的MCU吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

2

帖子

0

粉丝