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以下,不知道输出的是什么了,希望各位大神能不吝赐教,非常感谢。
下面是小弟画的电路图:
我写的代码如下:
//----------------------------------------------------------------------------
// 名称: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以下,不知道输出的是什么了,希望各位大神能不吝赐教,非常感谢。
下面是小弟画的电路图: