两个stc89c52单片机进行串口通信主机显示温度从机测温
首先,需要确定主从机的串口通信参数,包括波特率、数据位、校验位等。假设主机和从机的串口通信参数均为9600波特率、8个数据位、无校验位和1个停止位。
主机的程序流程如下:
- 初始化串口通信,设置波特率、数据位、校验位等参数;
 - 循环发送请求测温命令给从机;
 - 等待从机回复测温数据;
 - 解析并显示从机回复的测温数据。
 
从机的程序流程如下:
- 初始化串口通信,设置波特率、数据位、校验位等参数;
 - 等待主机发送测温命令;
 - 收到测温命令后进行温度测量,并将数据发送给主机;
 - 循环等待主机发送下一次测温命令。
 
下面是主机和从机的部分代码实现:
主机代码:
#include <STC89C5xRC.H>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ = P1^3; // DS18B20数据线
sbit LED = P1^4; // LED指示灯
uchar temp[2]; // 存储温度数据
void InitUART()
{
    TMOD = 0x20; // 设置定时器1为模式2
    TH1 = 0xfd; // 波特率9600
    TL1 = 0xfd;
    TR1 = 1; // 启动定时器1
    SM0 = 0; // 设置串口为模式1
    SM1 = 1;
    REN = 1; // 允许接收
    EA = 1; // 允许全局中断
    ES = 1; // 允许串口中断
}
void SendData(uchar dat)
{
    SBUF = dat; // 将数据写入发送缓冲区
    while (!TI); // 等待发送完成
    TI = 0; // 清除发送完成标志位
}
void RequestTemp()
{
    uchar i;
    unsigned int j;
    for (i = 0; i < 8; i++) // 发送复位信号
    {
        DQ = 0;
        _nop_();
        _nop_();
        DQ = 1;
        _nop_();
        _nop_();
    }
    SendData(0x01); // 发送测温命令
    for (j = 0; j < 5000; j++); // 延时等待从机回复
}
void main()
{
    InitUART();
    while (1)
    {
        RequestTemp(); // 发送测温命令
        while (!RI); // 等待接收数据
        temp[0] = SBUF; // 读取高位温度数据
        RI = 0;
        while (!RI); // 等待接收数据
        temp[1] = SBUF; // 读取低位温度数据
        RI = 0;
        LED = 1; // 点亮LED指示灯
        // 解析并显示温度数据
        SendData(temp[0]);
        SendData(temp[1]);
        LED = 0; // 熄灭LED指示灯
    }
}
void UART_ISR() interrupt 4
{
    if (RI) // 接收中断
    {
        RI = 0; // 清除接收中断标志位
    }
    if (TI) // 发送中断
    {
        TI = 0; // 清除发送中断标志位
    }
}
从机代码:
#include <STC89C5xRC.H>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ = P1^3; // DS18B20数据线
uchar temp[2]; // 存储温度数据
void InitUART()
{
    TMOD = 0x20; // 设置定时器1为模式2
    TH1 = 0xfd; // 波特率9600
    TL1 = 0xfd;
    TR1 = 1; // 启动定时器1
    SM0 = 0; // 设置串口为模式1
    SM1 = 1;
    REN = 1; // 允许接收
    EA = 1; // 允许全局中断
    ES = 1; // 允许串口中断
}
void SendData(uchar dat)
{
    SBUF = dat; // 将数据写入发送缓冲区
    while (!TI); // 等待发送完成
    TI = 0; // 清除发送完成标志位
}
void ReadTemp()
{
    uchar i, j;
    unsigned int temp_value;
    for (i = 0; i < 8; i++) // 发送复位信号
    {
        DQ = 0;
        _nop_();
        _nop_();
        DQ = 1;
        _nop_();
        _nop_();
    }
    for (i = 0; i < 8; i++) // 发送读取温度命令
    {
        DQ = 0;
        _nop_();
        _nop_();
        DQ = 1;
        _nop_();
        _nop_();
    }
    for (i = 0; i < 16; i++) // 读取16位温度数据
    {
        DQ = 0;
        _nop_();
        _nop_();
        temp_value = temp_value >> 1;
        if (DQ)
        {
            temp_value |= 0x8000;
        }
        DQ = 1;
        _nop_();
        _nop_();
    }
    temp[0] = temp_value >> 8; // 提取高位温度数据
    temp[1] = temp_value & 0xff; // 提取低位温度数据
}
void main()
{
    InitUART();
    while (1)
    {
        while (!RI); // 等待接收测温命令
        if (SBUF == 0x01)
        {
            RI = 0;
            ReadTemp(); // 读取温度
            // 发送温度数据
            SendData(temp[0]);
            SendData(temp[1]);
        }
    }
}
void UART_ISR() interrupt 4
{
    if (RI) // 接收中断
    {
        RI = 0; // 清除接收中断标志位
    }
    if (TI) // 发送中断
    {
        TI = 0; // 清除发送中断标志位
    }
}
``
原文地址: https://www.cveoy.top/t/topic/epzF 著作权归作者所有。请勿转载和采集!