帮我写一个51单片机,采用硬件定时器,每隔5S通过DS18B20采集温度,温度数值通过窜口发送到虚拟机,波特率9600bps,晶振设置为11.0592MHz,温度数值通过UG-2864HSWEG01显示
时间: 2023-11-27 18:03:24 浏览: 117
C51单片机实现DS18B20温度数据的采集,通过串口传至上位机以及PID控制温度软件设计源代码.zip
5星 · 资源好评率100%
好的,以下是51单片机程序的代码:
```c
#include <reg51.h>
#include <intrins.h>
#define FOSC 11059200UL // 定义晶振频率
#define BAUD 9600 // 定义波特率
#define TH 0x3C // 定时器初值高位
#define TL 0xB0 // 定时器初值低位
#define DS18B20_DQ P1_4 // DS18B20数据线
sbit DQ = P1^4; // 定义DQ口线
sbit RS = P0^0; // 定义LCD数据口的RS口线
sbit RW = P0^1; // 定义LCD数据口的RW口线
sbit EN = P0^2; // 定义LCD数据口的EN口线
unsigned char code table[] = "0123456789"; // 数码管显示表
void InitTimer0() // 初始化定时器0
{
TMOD &= 0xF0;
TMOD |= 0x01; // 16位定时器模式
TH0 = TH;
TL0 = TL; // 装载定时器初值
ET0 = 1; // 允许定时器0中断
TR0 = 1; // 启动定时器0
EA = 1; // 允许CPU中断
}
void InitUART() // 初始化串口
{
SCON = 0x50; // 8位数据,可变波特率
TMOD &= 0x0F;
TMOD |= 0x20; // 8位自动重装载定时器1
TH1 = TL1 = -(FOSC/12/32/BAUD); // 设定波特率重装载值
TR1 = 1; // 启动定时器1
ES = 1; // 开启串口中断
}
void DelayUs(unsigned int t) // 微秒级延时函数
{
while (t--);
}
void DelayMs(unsigned int t) // 毫秒级延时函数
{
unsigned char i, j;
while (t--)
{
i = FOSC / 12000;
j = 29;
do
{
while (--j);
} while (--i);
}
}
void WriteCommand(unsigned char com) // 写LCD指令
{
RS = 0;
RW = 0;
DelayUs(5);
EN = 1;
P2 = com;
DelayUs(5);
EN = 0;
}
void WriteData(unsigned char dat) // 写LCD数据
{
RS = 1;
RW = 0;
DelayUs(5);
EN = 1;
P2 = dat;
DelayUs(5);
EN = 0;
}
void LCDInit() // LCD初始化
{
WriteCommand(0x38); // 显示模式设定
WriteCommand(0x0C); // 显示开,光标关,光标闪烁关
WriteCommand(0x06); // 光标移动设定,不卷屏
WriteCommand(0x01); // 显示清屏
}
void LCDShow(unsigned char dat) // LCD显示一个数字
{
unsigned char temp;
temp = dat / 10;
WriteData(table[temp]);
temp = dat % 10;
WriteData(table[temp]);
}
void DS18B20Init() // DS18B20初始化
{
DQ = 1;
DelayUs(5);
DQ = 0;
DelayUs(500);
DQ = 1;
DelayUs(60);
if (!DQ)
{
DelayUs(500);
DQ = 1;
}
}
unsigned char DS18B20ReadByte() // DS18B20读取一个字节
{
unsigned char i, j;
unsigned char dat = 0;
for (i = 0; i < 8; i++)
{
DQ = 0;
_nop_();
_nop_();
dat >>= 1;
DQ = 1;
_nop_();
_nop_();
j = DQ;
if (j)
{
dat |= 0x80;
}
DelayUs(5);
}
return dat;
}
void DS18B20WriteByte(unsigned char dat) // DS18B20写入一个字节
{
unsigned char i;
for (i = 0; i < 8; i++)
{
DQ = 0;
_nop_();
_nop_();
if (dat & 0x01)
{
DQ = 1;
}
DelayUs(5);
DQ = 1;
dat >>= 1;
}
DelayUs(5);
}
unsigned int DS18B20ReadTemp() // DS18B20读取温度
{
unsigned char TL, TH;
unsigned int Temp;
DS18B20Init();
DS18B20WriteByte(0xCC); // 跳过ROM指令
DS18B20WriteByte(0x44); // 启动温度转换指令
DelayMs(750); // 等待转换完成
DS18B20Init();
DS18B20WriteByte(0xCC);
DS18B20WriteByte(0xBE); // 读取温度寄存器指令
TL = DS18B20ReadByte(); // 读取温度低位
TH = DS18B20ReadByte(); // 读取温度高位
Temp = TH;
Temp <<= 8;
Temp |= TL; // 合成温度值
return Temp;
}
void SendTemp(unsigned int temp) // 发送温度值到虚拟机
{
SBUF = (unsigned char)(temp >> 8);
while (!TI);
TI = 0;
SBUF = (unsigned char)temp;
while (!TI);
TI = 0;
}
void main()
{
unsigned int temp;
InitTimer0(); // 初始化定时器0
InitUART(); // 初始化串口
LCDInit(); // LCD初始化
while (1)
{
temp = DS18B20ReadTemp(); // 读取温度值
SendTemp(temp); // 发送温度值到虚拟机
LCDShow(temp >> 4); // LCD显示温度值
DelayMs(1000); // 延时1s
}
}
void Timer0_ISR() interrupt 1 // 定时器0中断服务程序
{
static unsigned char count = 0;
TH0 = TH;
TL0 = TL; // 重新装载定时器初值
count++; // 计数器加1
if (count == 10) // 5s到达
{
count = 0;
TR0 = 0; // 停止定时器0
DS18B20Init();
DS18B20WriteByte(0xCC); // 跳过ROM指令
DS18B20WriteByte(0x44); // 启动温度转换指令
DelayMs(750); // 等待转换完成
DS18B20Init();
DS18B20WriteByte(0xCC);
DS18B20WriteByte(0xBE); // 读取温度寄存器指令
SendTemp(DS18B20ReadTemp()); // 发送温度值到虚拟机
TR0 = 1; // 启动定时器0
}
}
void UART_ISR() interrupt 4 // 串口中断服务程序
{
if (RI)
{
RI = 0;
}
if (TI)
{
TI = 0;
}
}
```
在程序中,我们首先定义了晶振频率和波特率,然后初始化了定时器0和串口,以及LCD。在主循环中,我们不断读取温度值并通过串口发送到虚拟机,并在LCD上显示温度值。定时器0被用来定时5s,每5s通过DS18B20采集温度值并发送到虚拟机。串口中断服务程序用来处理串口中断。
阅读全文