微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > DS18B20控制PWM输出占空比程序问题

DS18B20控制PWM输出占空比程序问题

时间:10-02 整理:3721RD 点击:
小弟刚接触单片机不久,正在看一些入门的教材,这两天正琢磨着配合书上的例子做一个DS18B20控制PWM输出占空比的方案
我写的代码如下:
//----------------------------------------------------------------------------
// 名称:DS18B20温度控制PWM输出
//----------------------------------------------------------------------------
// 说明:运行本例时,外界温度将显示在1602LCD上
//----------------------------------------------------------------------------
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP() {_nop_(); _nop_(); _nop_(); _nop_(); }
sbit DQ = P1^0;
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
sbit PWM = P2^7;

uchar code Temp_Disp_Title[] = {" Current Temp : "};
uchar Current_Temp_Display_Buffer[] = {" TEMP :        "};
//温度字符
uchar code df_Table[] = {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 9};
uchar CurrentT = 0;  //当前读取的温度整数部分;
uchar Temp_Value[] = {0x00, 0x00};  //从DS18B20读取的温度值;
uchar Display_Digit[] = {0, 0, 0, 0};  //待显示的各温度数位;
bit DS18B20_IS_OK = 1;  //传感器正常标志
//----------------------------------------------------------------------------
// 延时
//----------------------------------------------------------------------------
void DelayXus(int x)
{
    uchar i;
    while(x-- ) for(i = 0; i < 200; i++);
}
//----------------------------------------------------------------------------
// LCD忙等待
//----------------------------------------------------------------------------
bit LCD_Busy_Check()
{
    bit result;
    LCD_RS = 0; LCD_RW = 1; LCD_EN = 1; delayNOP();
    result = (bit)(P0 & 0x80);
    LCD_EN = 0;
    return result;
}
   
//----------------------------------------------------------------------------
// 写指令
//----------------------------------------------------------------------------
void Write_LCD_Command(uchar cmd)
{
    while(LCD_Busy_Check());
    LCD_RS = 0; LCD_RW = 0; LCD_EN = 0; _nop_(); _nop_();
    P0 = cmd; delayNOP();
    LCD_EN = 1; delayNOP(); LCD_EN = 0;
}
//----------------------------------------------------------------------------
// 写数据
//----------------------------------------------------------------------------
void Write_LCD_Data(uchar dat)
{
    while(LCD_Busy_Check());
    LCD_RS = 1; LCD_RW = 0; LCD_EN = 0;
    P0 = dat; delayNOP();
    LCD_EN = 1; delayNOP(); LCD_EN = 0;
}
//----------------------------------------------------------------------------
// 初始化
//----------------------------------------------------------------------------
void LCD_Initialise()
{
    Write_LCD_Command(0x01); DelayXus(5);
    Write_LCD_Command(0x38); DelayXus(5);
    Write_LCD_Command(0x0c); DelayXus(5);
    Write_LCD_Command(0x06); DelayXus(5);
}
//----------------------------------------------------------------------------
// 设置显示位置
//----------------------------------------------------------------------------
void Set_LCD_POS(uchar pos)
{
    Write_LCD_Command(pos | 0x80);
}
//----------------------------------------------------------------------------
// 延时2
//----------------------------------------------------------------------------
void Delay(uint x)
{
    while (--x);
}
//----------------------------------------------------------------------------
// 初始化DS18B20
//----------------------------------------------------------------------------
uchar Init_DS18B20()
{
    uchar status;
    DQ = 1; Delay(8); DQ = 0; Delay(90); DQ = 1; Delay(8);
    status = DQ; Delay(100);
    DQ = 1;
    return status;
}
//----------------------------------------------------------------------------
// 读一字节
//----------------------------------------------------------------------------
uchar ReadOneByte()
{
    uchar i, dat = 0;
    DQ = 1; _nop_();
    for(i = 0; i < 8; i++)
    {
        DQ = 0; dat >>=1; DQ = 1; _nop_(); _nop_();
        if(DQ) dat |= 0x80;
        Delay(30);
        DQ = 1;
    }
    return dat;
}
//----------------------------------------------------------------------------
// 写一字节
//----------------------------------------------------------------------------
void WriteOneByte(uchar dat)
{
    uchar i;
    for(i = 0; i < 8; i++)
    {
        DQ = 0; DQ = dat & 0x01; Delay(5); DQ = 1; dat >>= 1;
    }
}
//----------------------------------------------------------------------------
// 读取温度值
//----------------------------------------------------------------------------
void Read_Temperature()
{
    if(Init_DS18B20() == 1)
        DS18B20_IS_OK = 0;
    else
    {
        WriteOneByte(0xCC);  //跳过序列号
        WriteOneByte(0x44);  //启动温度转换
        Init_DS18B20();
        WriteOneByte(0xCC);  //跳过序列号
        WriteOneByte(0xBE);  //读取温度寄存器
        Temp_Value[0] = ReadOneByte();  //温度低8位
        Temp_Value[1] = ReadOneByte();  //温度高8位
        DS18B20_IS_OK = 1;
    }
}
//----------------------------------------------------------------------------
// 在LCD上显示当前温度
//----------------------------------------------------------------------------
void Display_Temperature()
{
    uchar i;
    //延时值与负数标示
    uchar ng = 0;
    //高5位全为1(0xF8)则为负数,为负数时取反加1,设置负数标示
    if((Temp_Value[1] & 0xF8) == 0xF8)
    {
        Temp_Value[1] = ~Temp_Value[1];
        Temp_Value[0] = ~Temp_Value[0] + 1;
        if (Temp_Value[0] == 0x00) Temp_Value[1]++;
        //负数标示置1
        ng = 1;
    }
    //查表得到温度小数部分
    Display_Digit[0] = df_Table[Temp_Value[0] & 0x0F];
    //获取温度整数部分(高字节中的低三位与低字节中的高四位,无符号)
    CurrentT = ((Temp_Value[0] & 0xF0) >> 4) | (Temp_Value[1] & 0x07) << 4;
    //将整数部分分解为3位待显示数字
    Display_Digit[3] = CurrentT / 100;
    Display_Digit[2] = CurrentT % 100 / 10;
    Display_Digit[1] = CurrentT % 10;
    //刷新LCD显示缓冲
    Current_Temp_Display_Buffer[11] = Display_Digit[0] + '0';
    Current_Temp_Display_Buffer[10] = '.';
    Current_Temp_Display_Buffer[9] = Display_Digit[1] + '0';
    Current_Temp_Display_Buffer[8] = Display_Digit[2] + '0';
    Current_Temp_Display_Buffer[7] = Display_Digit[3] + '0';
    //高位为0时不显示
    if(Display_Digit[3] == 0) Current_Temp_Display_Buffer[7] = ' ';
    //高位为0且次高位为0时,次高位不显示
    if(Display_Digit[2] == 0 && Display_Digit[3] == 0)
    Current_Temp_Display_Buffer[8] = ' ';
    //负数符号显示在恰当的位置
    if(ng)
    {
        if(Current_Temp_Display_Buffer[8] == ' ')
            Current_Temp_Display_Buffer[8] = '-';
        else
        if(Current_Temp_Display_Buffer[7] == ' ')
            Current_Temp_Display_Buffer[7] = '-';
        else
            Current_Temp_Display_Buffer[6] = '-';
    }
    //在第一行显示标题
    Set_LCD_POS(0x00);
    for(i = 0; i < 16; i++)
    {
        Write_LCD_Data( Temp_Disp_Title );
    }
    //在第二行显示当前温度
    Set_LCD_POS(0x40);
    for(i = 0; i < 16; i++)
    {
        Write_LCD_Data(Current_Temp_Display_Buffer);
    }
    //显示温度符号
    Set_LCD_POS(0x4D); Write_LCD_Data(0x00);
    Set_LCD_POS(0x4E); Write_LCD_Data('C');
}
//----------------------------------------------------------------------------
// 延时3
//----------------------------------------------------------------------------
void Delay3(uchar x)
{
    uchar i;
    while(x--) for(i = 0; i < 40; i++);
}
//----------------------------------------------------------------------------
// 主函数
//----------------------------------------------------------------------------
void main()
{
    LCD_Initialise();
    Read_Temperature();
    Delay(50000);
    Delay(50000);
    while(1)
    {
        Read_Temperature();
        DelayXus(50);
        if(DS18B20_IS_OK)
        {
            Display_Temperature();
            if(CurrentT > 40) //如果检测到温度大于40度
            {
                PWM = 1;
                DelayXus(149);
            }
            else
            {
                Read_Temperature();
                if((Temp_Value[1] & 0xF8) == 0xF8) //如果检测到温度小于0度
                {
                    PWM = 0;
                    DelayXus(149);
                }
                else
                {
                    PWM = 1;
                    DelayXus(CurrentT/40*149);
                    PWM = 0;
                    DelayXus(149-(CurrentT/40*149));
                }
            }
        }
    }
}
问题表现在,用proteus仿真的时候40度以上时,貌似输出了该有的波形,但是40以下,不知道输出的是什么了,希望各位大神能不吝赐教,非常感谢。
下面是小弟画的电路图:


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top