2601_95940305 2026-04-27 21:04 采纳率: 0%
浏览 7

这个怎么做,51单片机串口通信实验

实验三、基于串行口的数据传输实验(4学时)
实验内容:基于单片机的数据传输系统中,有甲、乙两个单片机,利用串口进行数据传输。
甲机:根据需要随时检测系统中3个开关的状态并进行显示,开关闭合,对应的指示灯LED点亮;开关断开,对应的指示灯LED灭。利用外中断0实现随时检测开关状态。将开关状态传送至乙机。
(1)利用外中断1启动/停止发送数据。
(2)定时1s发送一次数据。
乙机:收到甲机传送过来的开关状态,利用3位发光二极管进行显示,开关闭合,
对应的指示灯LED点亮;开关断开,对应的指示灯LED灭。
当3个开关都闭合时,数码管显示On;
其他情况时,显示OF。(提示:PROTEUS仿真时数码管位选线采用P1口的引脚)
要求:
1、波特率自定、晶振11.0592Mhz
2、绘制硬件电路图
3、编写甲机、乙机程序
注意:甲机程序两个,分别为利用外中断1启动/停止发送数据和利用定时器
定时1s发送一次数据
乙机接收程序分别采用查询和中断两种方式编写
4、调试

  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2026-04-27 21:05
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    根据你的实验要求,这是一个典型的51单片机串口通信实验,涉及甲机与乙机之间的数据传输。下面我将为你详细解答如何完成这个实验,并提供完整的代码和实现步骤。


    一、实验目标

    • 甲机功能

      • 检测3个开关状态(通过外部中断0触发)。
      • 利用外中断1启动/停止发送数据。
      • 定时器1每1秒发送一次数据。
      • 将开关状态通过串口发送给乙机。
    • 乙机功能

      • 接收甲机发送的开关状态。
      • 用3个LED显示对应状态。
      • 当三个开关都闭合时,数码管显示“On”;否则显示“Off”。

    二、硬件电路设计(简要说明)

    1. 甲机硬件电路

    • P1口:连接3个开关(低电平有效),用于检测状态。
    • P2口:连接3个LED(高电平点亮)。
    • P3.2:外中断0(INT0)输入,检测开关变化。
    • P3.3:外中断1(INT1)输入,控制发送数据的启停。
    • P3.0:串口发送端(TXD)。
    • P3.1:串口接收端(RXD)。
    • 定时器1:用于定时1秒发送数据。

    2. 乙机硬件电路

    • P1口:连接3个LED,显示开关状态。
    • P1.0-P1.2:数码管位选线(注意:在PROTEUS中使用P1口引脚作为位选)。
    • P3.0:串口接收端(RXD)。
    • P3.1:串口发送端(TXD)。
    • 数码管:共阴极,显示“On”或“Off”。

    提示:在PROTEUS仿真中,确保数码管的位选线正确接在P1口上。


    三、软件设计思路

    甲机程序(分两种):

    1. 外中断1控制发送(启动/停止)

    • 设置EA=1,开启全局中断。
    • 设置EX1=1,允许外中断1。
    • 设置IT1=1,外中断1为下降沿触发。
    • 在中断服务函数中切换发送标志位(如send_flag)。

    2. 定时器1定时发送(1秒一次)

    • 初始化定时器1为模式1(16位)。
    • 计算定时时间(1秒)对应的初值。
    • 启动定时器1。
    • 每次定时溢出后发送数据。

    乙机程序(分两种):

    1. 查询方式接收数据

    • 不使用中断,通过不断读取RI标志判断是否有数据到达。
    • 收到数据后,更新LED显示。

    2. 中断方式接收数据

    • 设置EA=1,开启全局中断。
    • 设置ES=1,允许串口中断。
    • 在中断服务函数中读取数据并更新LED显示。

    四、波特率设置(11.0592MHz晶振)

    • 波特率选择为9600 bps

    • 使用定时器1工作于模式2(8位自动重装),计算初值:

      $$ \text{TH1} = \text{TL1} = 256 - \frac{11059200}{12 \times 9600} = 256 - 96 = 160 = 0xA0 $$


    五、关键代码实现

    1. 甲机程序(外中断1控制发送)

    #include <reg51.h>
    
    #define LED P2  // 3个LED连接到P2口
    sbit INT1 = P3^3;  // 外中断1
    unsigned char send_flag = 0;  // 发送标志
    unsigned char switch_state = 0;  // 开关状态
    
    void UART_Init() {
        SCON = 0x50;      // 8位异步串行,允许接收
        TMOD |= 0x20;     // 定时器1模式2
        TH1 = 0xA0;
        TL1 = 0xA0;
        TR1 = 1;          // 启动定时器1
    }
    
    void External_Interrupt1() interrupt 3 {
        send_flag = !send_flag;  // 切换发送状态
    }
    
    void main() {
        UART_Init();
        IT1 = 1;            // 外中断1为下降沿触发
        EX1 = 1;            // 允许外中断1
        EA = 1;             // 全局中断开启
    
        while (1) {
            if (send_flag) {
                SBUF = switch_state;  // 发送当前开关状态
                while (!TI);          // 等待发送完成
                TI = 0;               // 清除发送标志
            }
        }
    }
    

    2. 甲机程序(定时器1定时发送)

    #include <reg51.h>
    
    #define LED P2
    unsigned char switch_state = 0;
    
    void UART_Init() {
        SCON = 0x50;
        TMOD |= 0x20;
        TH1 = 0xA0;
        TL1 = 0xA0;
        TR1 = 1;
    }
    
    void Timer1_ISR() interrupt 3 {
        static unsigned int count = 0;
        count++;
        if (count == 1000) {  // 假设1秒 = 1000次定时
            SBUF = switch_state;
            while (!TI);
            TI = 0;
            count = 0;
        }
    }
    
    void main() {
        UART_Init();
        ET1 = 1;            // 允许定时器1中断
        EA = 1;
    
        while (1) {
            // 主循环可以处理其他逻辑
        }
    }
    

    3. 乙机程序(查询方式接收)

    #include <reg51.h>
    
    #define LED P1  // 3个LED连接到P1口
    
    void UART_Init() {
        SCON = 0x50;
        TMOD |= 0x20;
        TH1 = 0xA0;
        TL1 = 0xA0;
        TR1 = 1;
    }
    
    void main() {
        UART_Init();
    
        while (1) {
            if (RI) {           // 接收完成
                LED = SBUF;     // 显示开关状态
                RI = 0;         // 清除接收标志
            }
    
            // 检查是否全开
            if (LED == 0x07) {  // 0b00000111
                // 显示 "ON"
            } else {
                // 显示 "OFF"
            }
        }
    }
    

    4. 乙机程序(中断方式接收)

    #include <reg51.h>
    
    #define LED P1
    
    void UART_Init() {
        SCON = 0x50;
        TMOD |= 0x20;
        TH1 = 0xA0;
        TL1 = 0xA0;
        TR1 = 1;
    }
    
    void UART_ISR() interrupt 4 {
        LED = SBUF;         // 显示开关状态
        RI = 0;             // 清除接收标志
    }
    
    void main() {
        UART_Init();
        ES = 1;             // 允许串口中断
        EA = 1;
    
        while (1) {
            // 主循环可以处理其他逻辑
        }
    }
    

    六、调试步骤

    1. 硬件连接检查

      • 确保所有引脚连接正确,尤其是串口(P3.0和P3.1)。
      • 检查数码管的位选线是否连接到P1口。
    2. 仿真环境配置

      • 使用PROTEUS搭建电路图。
      • 添加虚拟串口工具(如VirtualSerialPort)进行通信测试。
    3. 程序烧录

      • 使用STC-ISP或KEIL烧录程序到单片机。
    4. 功能测试

      • 测试甲机能否检测开关状态。
      • 测试乙机能否正确显示LED和数码管。
      • 测试外中断1是否能控制发送。

    七、总结

    | 功能点 | 实现方式 | |--------|----------| | 开关状态检测 | 外部中断0 | | 数据发送控制 | 外部中断1 或 定时器1 | | 数据接收方式 | 查询或中断 | | 显示方式 | LED + 数码管 |


    八、注意事项

    • 波特率必须一致,否则无法通信。
    • 串口初始化必须正确,包括SCON、TMOD、TH1、TL1等寄存器。
    • 中断优先级需要合理设置,避免冲突。
    • 数码管显示逻辑需根据实际硬件调整。

    如果你需要我帮你绘制PROTEUS电路图,或者进一步优化代码,请告诉我!

    评论

报告相同问题?

问题事件

  • 创建了问题 4月27日