5.串口通信

串口的介绍

UART(通用异步收发器)是一种双向、串行、异步的通信总线,仅用一根数据接收线(RX)和一根数据发送线(TX)就能实现全双工通信

R:Receiver(接收),T:Transmit(发送)

数据组成

UART 在发送或接收过程中的一帧数据由4部分组成,起始位、数据位、奇偶校验位和停止位

如图所示。其中,起始位标志着一帧数据的开始,停止位标志着一帧数据的结束,数据位是一帧数据中的有效数据,校验位分为奇校验和偶校验,用于检验数据在传输过程中是否出错。(奇校验时,发送方应使数据位中1的个数与校验位中1的个数之和为奇数;接收方在接收数据时, 对1的个数进行检查,若不为奇数,则说明数据在传输过程中出了差错。同样,偶校验则检查1的个数是否为偶数)

UART通信过程中的数据格式及传输速率是可设置的,为了正确的通信,收发双方应约定并遵循同样的设置。数据位可选择为5、6、7、8位,其中8位数据位是最常用的,在实际应用中一般都选择8位数据位;校验位可选择奇校验、偶校验或者无校验位;停止位可选择1位(默认), 1.5或2位

串口通信的速率用波特率表示,它表示每秒传输二进制数据的位数,单位是bps(位 /秒),常用的波特率有9600、19200、38400、57600以及115200等

如波特率9600则代表每秒传输9600bit数据,以串口发送1个字节10bit算(起始位1bit+数据8bit+停止位1bit+NO校验位),则传输1个字节需要的时间是1*10/9600秒

USART:通用同步/异步串行接收/发送器

TTL

一般单片机产生的都是TTL电平。无论是51、32、还是各种跑Linux的ARM芯片,TTL满足绝大多数调试需求

TTL串口采用的是单一的信号线 (TX线和RX线) 进行数据传输,其中TX线用于单片机发送数据,RX线用于单片机接收数据。数据传输速率通常可以达到几-kbps至上百kbps的速率,传输距离较短,一般不超过数十米

TTL转USB
例图


传输方向

TTL的逻辑电平通常是0V和5V,其中0V表示逻辑“0”,5V表示逻辑“1”

RS-232

RS-232转USB

规定逻辑“1”的电平为-5V~-15 V,逻辑“0”的电平为+5 V~+15 V

由于RS -232采用串行传送方式,并且将TTL电平(某芯片)转换为RS-232C电平,其传送距离一般可达30 m。若采用光电隔离20 mA的电流环进行传送,其传送距离可以达到1000 m

公母头接法

RS-485

传输速度可以达到10Mb/s以上,传输距离可以达到3000米左右

传输方式为:差分方式

分类方式

串口并口

图解

同步异步

异步:通信双方各自约定通信速率

UART:TX、RX

1 Wire

同步:通信双方靠一根时钟线来约定通信速率

IIC:SDA、SCL

SPI:MOSI、MISO、SCK、CS

单工:指消息只能单方向传输的工作方式

半双工:指信息即可从A到B,也可以从B到A,任一时刻只能有一个方向上的传输存在

全双工:指在任意时刻线路上存在A到B和B到A的双向信号传输

相关寄存器

SCON

工作模式:01(8位UART波特率可变)其他不用为0

详细1

REN = 1,接收信息,一开始发送中断标志位、接收中断标志位置0

TB8:发送校验位,RB8:接收校验位,TI:发送中断,RI:接收中断

详细2

则SCON = 0x50

详细3

PCON

PCON解释图

TMOD

模式(M1、M0):这里选10(8位自动重装载定时器),其他在定时器有讲解

TMOD解释图

SBUF

接收和发送的数据都存在SBUF
SBUF图解

IE

中断允许寄存器
允许寄存器分析

中断处理函数

中断源中断处理函数
UARTUART_Routine(void) interrupt 4

代码编写

为何需要使用定时器观看链接讲解(9.34):波特率发生器

main.c

#include <reg52.h>
#include "delay.h"	//声明头文件,可在此文件使用头文件声明的函数、变量等
#include "Uart.h"uchar recv;	//全局变量用于接收数据void main()
{UART_Init();while(1){Delay1000ms();UART_send_str("i am xingzai");	//发送字符}
}
//串口中断处理函数
UART_Routine(void)         interrupt 4
{if(1 == RI){RI = 0;	//接收中断请求标志位软件复位recv = SBUF;	//接收数据赋值给变量switch(recv){case 0x1: LED1 = 0;break;   case 0x2: LED2 = 0;break;case 0x3: LED3 = 0;break;case 0x4: LED4 = 0;break;case 0x5: P1  |= 0x0F;break;	//这里采用或等于,目的不让P1.6蜂鸣器为0,保留高位原数据case 0x6: BEEP = 0;break;case 0x7: BEEP = 1;break;case 0x8: JDQ1 = 0;break;case 0x9: JDQ1 = 1;break;}}
}

delay.c

#include "delay.h"	//声明对应头文件,用于声明里面此文件函数、变量等
#include <intrins.h>
#include "main.h"
//延时函数
void Delay1000ms()		//@11.0592MHz
{uchar data i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}

delay.h

//头文件固定格式,防止头文件重复包含
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay1000ms();#endif

Uart.c

#include <reg52.h>
#include "Uart.h"void UART_Init()
{//配置相关寄存器SCON = 0x50;	//配置串口寄存器PCON=0x00;TMOD |= 0x20;	//配置时间寄存器定时器1//定时器初值TH1 = 0xFD;TL1 = 0xFD;EA = 1;	//打开中断总允许位ES = 1;	//打开串口中断允许位TR1 = 1;	//打开定时器1运行控制位
}//字符发送函数
void UART_send_char(uchar send_char)
{//将字符赋值给数据缓存寄存器SBUF = send_char;while(!TI);	//发送时为0,发送完触发发送中断时为1,为1时则数据发送完TI = 0;	//发送中断请求标志位软件复位
}
//接收传过来的字符串
void UART_send_str(uchar *send_str)
{//判断字符到最后'\0'则停止发送while(*send_str != '\0')UART_send_char(*send_str++);	//将字符逐个传给这个函数发送
}

Uart.h

#ifndef __UART_H__
#define __UART_H__
//因为main.c中已经声明了Uart.h,在Uart.h声明了main.h则main.c中也可以使用mian.h
#include "main.h"		void UART_Init();
void UART_send_char(unsigned char send_char);
void UART_send_str(unsigned char *send_str);#endif

main.h

#ifndef __MAIN_H__
#define __MAIN_H__
#include "reg52.h"typedef unsigned char uchar;	//给unsigned char取别名uchar
//定义对应元器件引脚
sbit LED1 = P1^0;
sbit LED2 = P1^1;
sbit LED3 = P1^2;
sbit LED4 = P1^3;
sbit BEEP = P1^6;
sbit JDQ1 = P1^7;#endif

回环

#include "reg52.h"
#include <intrins.h>unsigned char recv;
unsigned char send_buf[20];sbit LED1 = P1^0;
sbit LED2 = P1^1;
sbit LED3 = P1^2;
sbit LED4 = P1^3;
sbit BEEP = P1^6;
sbit JDQ1 = P1^7;void Delay1000ms()    //@11.0592MHz
{unsigned char data i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}void UART_send_byte(unsigned char send_byte)
{SBUF = send_byte;while(!TI);TI=0;
}void UART_send_str(unsigned char *send_str)
{	while(*send_str != '\0'){UART_send_byte(*send_str++);	}	
}void main()
{SCON = 0x50;PCON=0x00;TMOD |= 0x20;TH1 = 0xFD;TL1 = 0xFD;EA = 1;ES = 1;TR1 = 1;while(1){Delay1000ms();
//		UART_send_str("i am wfeng!\r\n");}
}UART_Routine(void)    interrupt 4
{if(1 == RI) //if(RI){RI=0;recv = SBUF;SBUF = recv;while(!TI);TI=0;}
}

继电器

继电器动态原理图

继电器模块的基本工作原理:

电磁线圈: 继电器内部包含一个电磁线圈,通常由绕制在绝缘芯片上的细导线组成。当通过线圈通电时,产生电磁场。

磁性吸引: 电磁场会使继电器中的铁芯(或磁性材料)受到磁性吸引,导致铁芯在电磁力的作用下移动。

触点操作: 铁芯的移动会导致机械部分的运动,最终使触点(开关)发生动作。继电器通常有常开(Normally Open,NO)和常闭(Normally Closed,NC)两组触点。

常开触点: 在继电器未通电时处于闭合状态,当电磁线圈通电时,触点打开。

常闭触点: 在继电器未通电时处于打开状态,当电磁线圈通电时,触点闭合。

电气隔离: 继电器的主要作用之一是提供电气隔离。通过电磁原理,可以在控制信号与被控制电路之间提供隔离,从而使得不同电路之间的电流不会相互影响。继电器模块常用于控制高电流或高电压的电路。

ESP8266

AP模式:无线接入点,它是一个无线网络的中心节点,可以看成是一个服务器。它作为一个网络的中心节点,提供无线接入服务,其他的无线设备允许接入该节点,所有接入该节点设备的无线信号数据都要通过它才能进行交换和互相访问。一般的无线路由器、网关、热点就是工作在AP模式下,AP节点和AP节点之间允许相互连接。

STA模式:无线网络中的一个终端站点设备,可以看成是一个客户端,一般来说,处在STA模式下的设备本身不接受无线的接入,该设备连接到AP节点进行网络访问,STA模式下的设备之间的通信可以通过AP进行转发实现

AT指令

可在官网寻找对应的指令集:安信可科技

配置 WiFi 模式:AT+CWMODE=3	//模式3:STA+AP
连接路由器:AT+CWJAP="wfeng","wf05430543"
查询 ESP8266的IP 地址: AT+CIFSR
//PC端使用网络调试工具,建⽴一个 TCP 服务器器
ESP8266 作为Client 连接到服务器:AT+CIPSTART="TCP","192.168.31.118",8090
发送数据:AT+CIPSEND=4

代码编写

电脑当服务端,单片机当客户端,电脑发指令控制单片机(接收),单片机发送字符给电脑

main.c

#include "define.h"
#include "send.h"
#include "delay.h"void main()
{define_bl();do{send_str("AT+CWMODE=3\r\n");	//发送AT指令配置ESP8266模块,选择模式3Delay1000ms();}while(Esp_Ok_flag);Esp_Ok_flag = 1;do{send_str("AT+CWJAP=\"qiji\",\"12345678\"\r\n");	//连接WiFiDelay1000ms();}while(Esp_Ok_flag);Esp_Ok_flag = 1;do{send_str("AT+CIPSTART=\"TCP\",\"192.168.43.10\",8085\r\n");	//连接服务器Delay1000ms();}while(Esp_Ok_flag);do{send_str("AT+CIPSEND=4\r\n");	//发送4个字节数据Delay1000ms();}while(Esp_Ok_flag);send_str("xinz\r\n");	//发送的数据Esp_Ok_flag = 1;while(1){Delay1000ms();}
}

define.c

#include <define.h>
int Esp_Ok_flag = 1;
void define_bl()
{SCON = 0x50;PCON = 0x00;TMOD = 0x20;TH1 = 0xFD;TL1 = 0xFD;TR1 = 1;ES = 1;EA = 1;
}

define.h

#ifndef __DELAY_H__
#define __DELAY_H__#include "reg52.h"void define_bl();typedef unsigned char uchar;	//取别名
extern int Esp_Ok_flag;	//定义一个全局变量方便不同.c文件使用
//定义对应元器件引脚
sbit LED1 = P1^0;
sbit LED2 = P1^1;
sbit LED3 = P1^2;
sbit LED4 = P1^3;
sbit BEEP = P1^6;
sbit JDQ1 = P1^7;#endif

send.c

#include <send.h>
//接收需要发送的字符
void send_str(uchar *send_s)
{while(*send_s != '\0')	//当字符串!='\0'时把字符一个个传给send_char函数发送{send_char(*send_s++);	//将每个字符逐一发送}
}void send_char(uchar send_c)
{SBUF = send_c;	//将单个字符赋值给SBUF则发送while(!TI);	//当TI为0,则发送未完成,当发送完成为1,取反为0跳出循环TI = 0;	//复位,发送请求中断标志位为0
}

send.h

#ifndef __SEND_H__
#define __SEND_H__#include "define.h"
//声明两个发送函数
void send_str(uchar *send_s);
void send_char(uchar send_c);#endif

receive.c

#include <define.h>
uchar Recv_Buf[20];
char recv;
//串口中断函数
UART_Routine(void) interrupt 4
{static int i = 0;  //static:全局使用不重新char Recv;if(1 == RI) //if(RI){RI=0;Recv=SBUF;if(Recv == 'O'|| Recv == '+'){i = 0;Recv_Buf[i] = Recv;Recv_Buf[i+1] = Recv;			}else{i++;Recv_Buf[i] = Recv;		}if(Recv_Buf[0] == 'O'&&Recv_Buf[1] == 'K')	//收到回复OK则说明指令执行成功{Esp_Ok_flag = 0;	//让标志为0跳出循环,执行下一个指令i = 0;	//重置数组指向位数}//接收到服务器,接收到的指令会以 +IPD 开头,以及第七个是接收的指令开始,判断接收到哪个指令执行下方的操作if(Recv_Buf[0] == '+'&&Recv_Buf[1] == 'I'&&Recv_Buf[2] == 'P'&&Recv_Buf[3] == 'D'){if(Recv_Buf[7] == 'L'&&Recv_Buf[8] == 'E'&&Recv_Buf[9] == 'D'&&Recv_Buf[10] == '1'&&Recv_Buf[11] == '1')LED1 = 1;if(Recv_Buf[7] == 'L'&&Recv_Buf[8] == 'E'&&Recv_Buf[9] == 'D'&&Recv_Buf[10] == '1'&&Recv_Buf[11] == '0')LED1 = 0;			if(Recv_Buf[7] == 'L'&&Recv_Buf[8] == 'E'&&Recv_Buf[9] == 'D'&&Recv_Buf[10] == '2'&&Recv_Buf[11] == '1')LED2 = 1;if(Recv_Buf[7] == 'L'&&Recv_Buf[8] == 'E'&&Recv_Buf[9] == 'D'&&Recv_Buf[10] == '2'&&Recv_Buf[11] == '0')LED2 = 0;				if(Recv_Buf[7] == 'L'&&Recv_Buf[8] == 'E'&&Recv_Buf[9] == 'D'&&Recv_Buf[10] == '3'&&Recv_Buf[11] == '1')LED3 = 1;if(Recv_Buf[7] == 'L'&&Recv_Buf[8] == 'E'&&Recv_Buf[9] == 'D'&&Recv_Buf[10] == '3'&&Recv_Buf[11] == '0')LED3 = 0;				if(Recv_Buf[7] == 'L'&&Recv_Buf[8] == 'E'&&Recv_Buf[9] == 'D'&&Recv_Buf[10] == '4'&&Recv_Buf[11] == '1')LED4 = 1;if(Recv_Buf[7] == 'L'&&Recv_Buf[8] == 'E'&&Recv_Buf[9] == 'D'&&Recv_Buf[10] == '4'&&Recv_Buf[11] == '0')LED4 = 0;				if(Recv_Buf[7] == 'B'&&Recv_Buf[8] == 'E'&&Recv_Buf[9] == 'E'&&Recv_Buf[10] == 'P'&&Recv_Buf[11] == '1')BEEP = 1;if(Recv_Buf[7] == 'B'&&Recv_Buf[8] == 'E'&&Recv_Buf[9] == 'E'&&Recv_Buf[10] == 'P'&&Recv_Buf[11] == '0')BEEP = 0;			if(Recv_Buf[7] == 'J'&&Recv_Buf[8] == 'D'&&Recv_Buf[9] == 'Q'&&Recv_Buf[10] == '1'&&Recv_Buf[11] == '1')JDQ1 = 1;if(Recv_Buf[7] == 'J'&&Recv_Buf[8] == 'D'&&Recv_Buf[9] == 'Q'&&Recv_Buf[10] == '1'&&Recv_Buf[11] == '0')JDQ1 = 0;								}	if(i>18)i=18;}
}

delay.c

#include <delay.h>
#include <intrins.h>
//延时函数
void Delay1000ms()    //@11.0592MHz
{unsigned char data i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}

delay.h

#ifndef __DELAY_H__
#define __DELAY_H__
//声明延时函数
void Delay1000ms();#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/48386.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 中文分词模拟器(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线…

浅谈Canal原理

canal [kə’nl]&#xff0c;译意为水道/管道/沟渠&#xff0c;主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据 订阅 和 消费。应该是阿里云DTS&#xff08;Data Transfer Service&#xff09;的开源版本。 Canal与DTS提供的功能基本相似&#xff1a; 基于…

vue2学习笔记9 - 通过观察vue实例中的data,理解Vue中的数据代理

接着上一节&#xff0c;学一学vue中的数据代理。学vue这几天&#xff0c;最大的感受就是&#xff0c;名词众多&#xff0c;听得发懵。。不过&#xff0c;深入理解之后&#xff0c;其实说得都是一回事。 在Vue中&#xff0c;数据代理是指在实例化Vue对象时&#xff0c;将data对…

神经网络模型实现(训练、测试)

目录 一、神经网络骨架&#xff1a;二、卷积操作&#xff1a;三、卷积层&#xff1a;四、池化层&#xff1a;五、激活函数&#xff08;以ReLU为例&#xff09;&#xff1a;六、模型搭建&#xff1a;七、损失函数、梯度下降&#xff1a;八、模型保存与加载&#xff1a;九、模型训…

基于RFID的课堂签到系统设计

1.简介 基于RFID的课堂签到系统设计是一种利用无线射频识别&#xff08;RFID&#xff09;技术实现课堂自动签到的系统。这种系统通过RFID标签&#xff08;通常是学生携带的卡片或手环等&#xff09;与安装在教室内的RFID读写器之间的无线电信号进行数据交换&#xff0c;从而实现…

移动设备安全革命:应对威胁与解决方案

移动设备已成为我们日常工作和家庭生活中不可或缺的工具&#xff0c;然而&#xff0c;对于它们安全性的关注和投资仍然远远不够。本文深入分析了移动设备安全的发展轨迹、目前面临的威胁态势&#xff0c;以及业界对于这些安全漏洞响应迟缓的深层原因。文中还探讨了人们在心理层…

Java跨平台的原理是什么?JDK,JRE,JVM三者的作用和区别?xxx.java和xxx.class有什么区别?看这一篇就够了

目录 1. Java跨平台相关问题 1.1 什么是跨平台(平台无关性)&#xff1f; 1.2 跨平台(平台无关性)的好处&#xff1f; 1.3 编译原理基础&#xff08;Java程序编译过程&#xff09; 1.4Java跨平台的是实现原理&#xff1f; 1.4.1 JVM(Java虚拟机) 1.4.2 Class文件 1.4.3 …

485开关量采集模块16路I/O输入输出ModbusRTU协议—DAM-3950A

品牌&#xff1a;阿尔泰科技 型号&#xff1a;DAM-3950A 概述&#xff1a; DAM-3950A为16路隔离数字量输入&#xff0c;6路C型10路A型信号继电器输出模块&#xff0c;RS485通讯接口&#xff0c;带有标准ModbusRTU协议。配备良好的人机交互界面&#xff0c;使用方便&#xff…

Linux 文件安装的mysql 启动

1、找到my.cnf 2、确定文件类容&#xff1a; 并确保这些重要的配置&#xff1a;basedir 、datadir、socket 文件或目录都存在 3、找到mysqld 位置 4、启动mysqld mysqld --defaults-file/etc/my.cnf --usermysql

c++基础(类和对象中)(类的默认成员函数)

目录 一.构造函数&#xff08;类似初始化&#xff09; 1.概念 2.构造函数的特点 二.析构函数&#xff08;类似 销毁对象/空间&#xff09; 三.拷贝构造函数(类似复制粘贴的一种 初始化 ) 1.概念&#xff1a; 2.拷贝构造的特点&#xff1a; 四.赋值运算符重载&#xff08…

level 6 day2-3 网络基础2---TCP编程

1.socket&#xff08;三种套接字&#xff1a;认真看&#xff09; 套接字就是在这个应用空间和内核空间的一个接口&#xff0c;如下图 原始套接字可以从应用层直接访问到网络层&#xff0c;跳过了传输层&#xff0c;比如在ubtan里面直接ping 一个ip地址,他没有经过TCP或者UDP的数…

华为OD机试(C卷,200分)- 二叉树计算

题目描述 给出一个二叉树如下图所示&#xff1a; 请由该二叉树生成一个新的二叉树&#xff0c;它满足其树中的每个节点将包含原始树中的左子树和右子树的和。 左子树表示该节点左侧叶子节点为根节点的一颗新树&#xff1b;右子树表示该节点右侧叶子节点为根节点的一颗新树。…

食南之徒~马伯庸

◆ 第一章 >> 老赵&#xff0c;这你就不懂了。过大于功&#xff0c;要受罚挨打&#xff0c;不合算&#xff1b;功大于过&#xff0c;下回上司有什么脏活累活&#xff0c;第一时间会想到你&#xff0c;也是麻烦多多。只有功过相抵&#xff0c;上司既挑不出你的错&#xf…

MMU(内存管理单元)

概述 MMU 即内存管理单元&#xff0c;是用硬件电路逻辑实现的一个地址转换器件&#xff0c;它负责接受虚拟地址和地址关系转换表&#xff0c;以及输出物理地址 线性地址 由于保护模式的内存模型是分段模型&#xff0c;它并不适合于 MMU 的分页模型&#xff0c;所以我们要使用…

springcloud-config客户端启用服务发现报错找不到bean EurekaHttpClient

背景 在对已有项目进行改造的时候&#xff0c;集成SpringConfigStarter&#xff0c;编写完bootstrap.yml&#xff0c;在idea 启动项中编辑并新增VM options -Dspring.cloud.config.discovery.enabledtrue&#xff0c;该版本不加spring不会从configService获取信息&#xff0c;…

三、GPIO口

我们在刚接触C语言时&#xff0c;写的第一个程序必定是hello world&#xff0c;其他的编程语言也是这样类似的代码是告诉我们进入了编程的世界&#xff0c;在单片机中也不例外&#xff0c;不过我们的传统就是点亮第一个LED灯&#xff0c;点亮电阻&#xff0c;电容的兄弟&#x…

[CSS] 浮动布局的深入理解与应用

文章目录 浮动的简介元素浮动后的特点解决浮动产生的影响浮动后的影响解决浮动产生的影响 浮动相关属性实际应用示例示例1&#xff1a;图片与文字环绕示例2&#xff1a;多列布局示例3&#xff1a;响应式布局 总结 浮动布局是CSS中一种非常强大的布局方式&#xff0c;最初设计用…

java项目(knife4j使用,静态资源未放在static资源包下,公共字段自动填充,Spring Cache与Spring Task)

Knife4j&#xff08;生成接口文档&#xff09; 使用swagger你只需要按照它的规范去定义接口及接口相关的信息&#xff0c;就可以做到生成接口文档&#xff0c;以及在线接口调试页面。官网:https://swagger.io/ Knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案。…

JMeter请求导出Excel

前言 今天记录一个使用JMeter模拟浏览器请求后端导出&#xff0c;并下载Excel到指定位置的过程 创建请求 同样先创建一个线程组&#xff0c;再创建一个请求&#xff0c;设置好请求路径&#xff0c;端口号等 查看结果树 右键--添加--监听器--查看结果树 这里可以查看&#…

Windows搭建RTMP视频流服务器

参考了一篇文章&#xff0c;见文末。 博客中nginx下载地址失效&#xff0c;附上一个有效的地址&#xff1a; Index of /download/ 另外&#xff0c;在搭建过程中&#xff0c;遇到的问题总结如下&#xff1a; 1 两个压缩包下载解压并重命名后&#xff0c;需要 将nginx-rtmp…