51单片机PWM调速时遇到的问题,哪位大神帮我看看!

2019-07-15 14:32发布

下面是单片机PWM调速直流电机的程序,PWMOUT连接P2.4端口作为PWM输出口,依照程序,当温度在30度以下时,应该输出低电平,但是proteus仿真中却输出了方波,是为什么?


#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int  
unsigned char HighRH = 0; //高电平重载值的高字节
unsigned char HighRL = 0; //高电平重载值的低字节
unsigned char LowRH = 0; //低电平重载值的高字节
unsigned char LowRL = 0; //低电平重载值的低字节
sbit PWMOUT=P2^4;
sbit DQ=P1^0;

uint  tvalue;   //温度值
uchar tflag;    //温度正负标志  
/**********测温模块************/
void delay_18B20(unsigned int i)  //延时1微秒
  {
  while(i--);
  }
void ds1820rst()    /*ds1820复位*/
  {
  unsigned char x=0;
  DQ = 1;           //DQ复位
  delay_18B20(4);   //延时
  DQ = 0;           //DQ拉低
  delay_18B20(100); //精确延时大于          480us
  DQ = 1;           //拉高
  delay_18B20(40);
  }     
uchar ds1820rd()    /*读数据*/
  {
    unsigned char i=0;
    unsigned char dat = 0;
    for (i=8;i>0;i--)
    {
    DQ = 0;         //给脉冲信号     
    dat>>=1;
    DQ = 1;         //给脉冲信号     
    if(DQ)  dat|=0x80;     
    delay_18B20(10);
    }
  return(dat);
  }  
void ds1820wr(uchar wdata)   /*写数据*/
  {
  unsigned char i=0;     
  for (i=8; i>0; i--)   
    {
    DQ = 0;      
    DQ = wdata&0x01;      
    delay_18B20(10);      
    DQ = 1;      
    wdata>>=1;
    }
}  
read_temp()       /*读取温度值并转换*/
  {
  uchar a,b;
  ds1820rst();
  ds1820wr(0xcc); // 跳过读序列号
  ds1820wr(0x44); // 启动温度转换
  ds1820rst();
  ds1820wr(0xcc); // 跳过读序列号
  ds1820wr(0xbe); // 读取温度
  a=ds1820rd();
  b=ds1820rd();
  tvalue=b;
  tvalue<<=8;
  tvalue=tvalue|a;
    if(tvalue<0x0fff)
    tflag=0;
    else
    {
    tvalue=~tvalue+2; tflag=1;         //负温度  
    }
  tvalue=tvalue*(0.625);  //温度值扩大10倍,精确到1位小数
  return(tvalue);
  }

/***********温度显示模块*********/

unsigned char code str[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40} ; //共阴数码管字码表
unsigned char code wei[]={0x0f2,0x0f1}; //位选信号
uchar data disdata[5];
void ds1820disp()        //温度值显示
  {
  uchar i;
  disdata[0]=tvalue/1000;     //百位数
  disdata[1]=tvalue%1000/100; //十位数
  disdata[2]=tvalue%100/10;   //个位数
  disdata[3]=tvalue%10;       //小数位


for(i=0;i<150;i++)
    {P2=wei[0];
     P0=str[disdata[1]];
     delay_18B20(20);
     P2=wei[1];
     P0=str[disdata[2]];
         delay_18B20(20);
     }
}

void ConfigPWM(unsigned int fr, unsigned char dc);
void ClosePWM();
void main(){

    while (1){
         read_temp();
         ds1820disp();
       if(tvalue>=300)

            if(tvalue>=500)
             ClosePWM();
                         else
              ConfigPWM(100,50);

       else
       PWMOUT=0;
    }
}
/* 配置并启动 PWM,fr-频率,dc-占空比 */
void ConfigPWM(unsigned int fr, unsigned char dc){
    unsigned int high, low;
    unsigned long tmp;

    tmp = (11059200/12) / fr; //计算一个周期所需的计数值
        tmp = tmp/fr;
    high = (tmp*dc) / 100; //计算高电平所需的计数值
    low = tmp - high; //计算低电平所需的计数值
    high = 65536 - high + 12; //计算高电平的重载值并补偿中断延时
    low = 65536 - low + 12;//计算低电平的重载值并补偿中断延时

    HighRH = (unsigned char)(high>>8); //高电平重载值拆分为高低字节
    HighRL = (unsigned char)high;
    LowRH = (unsigned char)(low>>8); //低电平重载值拆分为高低字节
    LowRL = (unsigned char)low;

    TMOD &= 0xF0; //清零 T0 的控制位
    TMOD |= 0x01; //配置 T0 为模式 1
    TH0 = HighRH; //加载 T0 重载值
    TL0 = HighRL;
    ET0 = 1; //使能 T0 中断
    TR0 = 1; //启动 T0
        EA=1;
    PWMOUT = 1; //输出高电平
}
/* 关闭 PWM */
void ClosePWM(){
    TR0 = 0; //停止定时器
    ET0 = 0; //禁止中断
    PWMOUT = 1; //输出高电平
}

/* T0 中断服务函数,产生 PWM 输出 */
void Interrupttimer0() interrupt 1{
    if (PWMOUT == 1){ //当前输出为高电平时,装载低电平值并输出低电平
        TH0 = LowRH;
        TL0 = LowRL;
        PWMOUT = 0;
    }else{ //当前输出为低电平时,装载高电平值并输出高电平
        TH0 = HighRH;
        TL0 = HighRL;
        PWMOUT = 1;
    }
}

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
app。,
1楼-- · 2019-07-15 20:24
最好给出完整的程序
15720615150
2楼-- · 2019-07-16 01:13
 精彩回答 2  元偷偷看……
阿非
3楼-- · 2019-07-16 01:21
最近也开始学习pwm了
guihuafu123
4楼-- · 2019-07-16 05:32
进来看看,学习学习
当时已枉然
5楼-- · 2019-07-16 07:27
我才学到定时器的章节
小小怪兽
6楼-- · 2019-07-16 11:03
给出完整的程序

一周热门 更多>