【单片机】12-串口通信和RS485

1.通信有关的常见概念

区分:串口,COM口,UART,USART_usart和串口区别-CSDN博客

串口、COM口、UART口, TTL、RS-232、RS-485区别详解-CSDN博客

1.什么是通信

(1)人和人之间的通信:说话,写信

(2)人和计算机之间的通信:按键,显示器,鼠标

(3)计算机和计算机之间的通信

2.通信的关键

(1)事先约定

(2)基本的信息单元

(3)有效信息的编码,传输和解码

3.通信的专业性概念

(1)同步和异步:同一个步调

(2)单工,半双工,全双工:数据传输方向

(3)并行和串口:并行(多根线),串行(单根线)

(4)电平信号【传输近,易受干扰】和差分信号【传输远,不易受干扰】:电平是通过高低电平进行区分,差分是相对的

2.串行通信

1.串口通信基础

(1)一种特定的通信协议【电平通信】

(2)串行通信,串口通信,UART,USART

(3)串口通信的特点:异步,串行,全双工

2.串行通信的主要用途

(1)早期:计算机之间短距离通信(1.5米内),完备通信机制

(2)现在:CPU之间近距离通信【CPU和周边芯片】,调试信息输入输出非完备通信

3.串行通信的工作方式

(1)3根线(GND,RxD【接收线】,TxD【发送线】---recive ,transmit)---不完备通信

或者9根线(DB9)-完备通信

(2)发送方有发送位移寄存器,接收方有接收移位寄存器

(3)数据在发送方和接收方的CPU中都以字节为单位整字节处理

(4)数据在通信线上以位为单位逐个bit的传输

4.串行通信的主要概念

传输都是一帧一帧的发

1.起始位

开始之前要发送一个起始位

2.数据位

比如我们传输“A”,转换为ASCII就是8位二进制,这8位就叫做8位数据位【有效数据】

数据位要双方沟通确定的

3.奇偶校验位

判断传输过程中是否出错

4.停止位(帧)

判断是否结束

5.波特率

串行通信的速度

一秒钟传输多少给bit位,发送方和接收方必须波特率设置为一样【波特率越小,传输速度慢,抗干扰能力越强】

6.流控

速率协商,现在一般要禁用掉

3.51单片机的串行通信

1.基础概念

SoC:把CPU以及其他功能集成到一个芯片上

(1)串行通信功能是SoC的一个(内部)外设提供的,与CPU无关【CPU=运算器+控制器】--CPU本身无法通信

(2)各种不同的SoC的串行通信大同小异【内部差不多,编程时候可能不同】

(3)串行通信经常作为主控SoC与其他外部芯片之间的通信接口【串行通信==SoC与外部其他芯片的通信】

2.STC51单片机的串行通信简介

4.STC51的串行通信相关寄存器

1.总体浏览

2.SCON:串行控制寄存器

3.SBUF:串行口缓存寄存器

4.PCON:电源控制寄存器

5.IE:中断允许寄存器

6.串口发送时的软硬件协作方式

(1)查询方式。硬盘在发送完一帧数据后会将一个标志位置位(标志位本来是0),软件需要不断读取这个标志位的值来判断硬件是否完成了发送(如果读出来的是0就表示硬件还在发还在发还没完还在忙,所以我们就不能认为硬件发完了,所以就不能给硬件安排下一帧数据的发送;如果读出来的是1则说明硬件已经发完了上一帧数据,这时候软件就应该给硬件在给一帧数据去发送)

(2)因为串口发送完这个事件对CPU来说是个异步事件(因为不知道什么时候发送消息),所以这里查询方式来处理和之前讲过的查询方式处理按键是非常类似的。

(3)常见情况下:串口发送会使用查询方式,串口接收会使用中断方式【因为不知道什么时候会接收到信息,使用中断才不会过度销毁CPU】

7.波特率加倍

PCON中的SMOD

所谓波特率加倍,就是正常计算出的波特率假设是2400,那么SMOD=1时则实际波特率就是4800;当SMOD=0时不加倍,也就是2400还是2400

5.STC51的串行通信实战

1.硬件接线分析

(1)目标:将PC机和51单片机通过串口连接起来

(2)PC机的串口情况:台式机串口,笔记本USB转串口

(3)开发板原理图分析

2.接线方案

1.使用板载CH340

什么都不用动,默认就是使用这个,最简单最省事,最推荐

2.使用DB9接口USB转串口线

用DB9接口的USB转串口线

注意:跳线帽接到DB9一侧

3.使用TTL接口USB转串口线

只接三根线:TxD,RxD,GND

4.总结

3.使用板载CH340进行串口实践

1.接线+下载程序

2.查看设备管理器确定COM号

3.方法一:使用普中下载软件自带的串口助手监视

4.方法二:使用第三方串口助手软件监视

5.方法三:使用SecureCRT软件监视

4.使用DB9接口USB转串口线

1.接线+下载程序

2.注意对下载程序的影响

此时无法进行程序下载

3.使用各种方式进行监视

5.串口初始化

//串口初始化函数
//预设一个串口条件:8位数据位,1停止位,0校验位,波特率4800
//初始化的主要工作就是去设置相关的寄存器
void uart_init(void){SCON=0x50; //串口工作在模式1(8位串口),允许接收PCON=0x80;   //波特率加倍,意思是本来需要波特率4800,等一下计算时按照2400去计算就好}

6.波特率计算

SMOD---》判断是否进行波特率加倍【如果加倍则为1,不加倍则为0】

 查看数据手册中”串行通信中波特率的设置“

接着查看定时/计数器1的工作方式2的寄存器设置情况

TMOD=0x20;  //设置T1为模式2

TR1=1;        //开启T1让它开始工作

我们刚刚在上面计算出TH1=243;,所以进行设置

TH1=243;
TL1=243;   //8位自动重装,意思就是TH1用完了下一个周期TL1会自动重装到TH1中

 




7.串口发送字符【单个字符】

注意点:51单片机不一样,要先发送在检验有没有在发送

其他MCU都是先检验在发送

如果为【0】则表示在忙,如果为【1】则表示发送结束

//串口发送函数,发送一个字节
void uart_send_byte(unsigned char c){//【第一步】发送一个字节SBUF=c;//【第二步】先确认串口发送部分没有在忙while(!TI);//TI=0,表示在忙//【第三步】软件复位TI标志位---数据手册要求的TI=0;
}

8.测试一下

1.波特率不加倍

#include<reg51.h>//函数声明
void uart_init(void);
void uart_send_byte(unsigned char c);
void delay();void main(){//第一步:初始化好串口到正确的状态uart_init();while(1){//为了调试方便,让A循环发送,才好监视//第二步:通过串口发送信息出去uart_send_byte('A');delay();}}void delay(){unsigned char i,j;for(i=0;i<100;i++){for(j=0;j<200;j++);}
}//串口初始化函数
//预设一个串口条件:8位数据位,1停止位,0校验位,波特率4800
//初始化的主要工作就是去设置相关的寄存器
void uart_init(void){//波特率不加倍的例子SCON=0x50; //串口工作在模式1(8位串口),允许接收PCON=0x00;   //波特率不加倍//通信波特率相关的设置//此处我们使用【方式1】---对应数据手册TMOD=0x20;  //设置T1为模式2TR1=1;	//开启T1让它开始工作TH1=249;TL1=249;    //8位自动重装,意思就是TH1用完了下一个周期TL1会自动重装到TH1中//中断初始化ES=1;//串口中断初始化EA=1;//整个中断初始化}//串口发送函数,发送一个字节
void uart_send_byte(unsigned char c){//【第一步】发送一个字节SBUF=c;//【第二步】先确认串口发送部分没有在忙while(!TI);//TI=0,表示在忙//【第三步】软件复位TI标志位---数据手册要求的TI=0;
}

因为我们算出来的TH1和TL1=6.5,所以精确度可能会受到影响,我们将其设置为250 或者 249则结果都会输出乱码

2.换一个波特率:9600

我们前面算出TH1=6.5【这里我们的波特率为4800】,所以如果为9600则我们应该将【6.5/2=3.25】才是我们9600的结果


//波特率为9600SCON=0x50; //串口工作在模式1(8位串口),允许接收PCON=0x00;   //波特率不加倍//通信波特率相关的设置//此处我们使用【方式1】---对应数据手册TMOD=0x20;  //设置T1为模式2TR1=1;	//开启T1让它开始工作TH1=253;TL1=253;    //8位自动重装,意思就是TH1用完了下一个周期TL1会自动重装到TH1中//中断初始化ES=1;//串口中断初始化EA=1;//整个中断初始化

9.串口发送字符串【多个字符】

#include<reg51.h>//函数声明
void uart_init(void);
void uart_send_byte(unsigned char c);
void delay();
void uart_send_string(unsigned char *str);void main(){//第一步:初始化好串口到正确的状态uart_init();while(1){//发送字符串,也可以发送中文uart_send_string("abcdefg");delay();}}void delay(){unsigned char i,j;for(i=0;i<100;i++){for(j=0;j<200;j++);}
}//串口初始化函数
//预设一个串口条件:8位数据位,1停止位,0校验位,波特率4800
//初始化的主要工作就是去设置相关的寄存器
void uart_init(void){//波特率加倍的例子SCON=0x50; //串口工作在模式1(8位串口),允许接收PCON=0x80;   //波特率加倍,意思是本来需要波特率4800,等一下计算时按照2400去计算就好//通信波特率相关的设置//此处我们使用【方式1】---对应数据手册TMOD=0x20;  //设置T1为模式2TR1=1;	//开启T1让它开始工作TH1=243;TL1=243;    //8位自动重装,意思就是TH1用完了下一个周期TL1会自动重装到TH1中//中断初始化ES=1;//串口中断初始化EA=1;//整个中断初始化}//串口发送函数,发送一个字节【单个字节】
void uart_send_byte(unsigned char c){//【第一步】发送一个字节SBUF=c;//【第二步】先确认串口发送部分没有在忙while(!TI);//TI=0,表示在忙//【第三步】软件复位TI标志位---数据手册要求的TI=0;
}//发送字符串【多个字符】
void uart_send_string(unsigned char *str)
{while (*str != '\0'){uart_send_byte(*str);		// 发送1个字符str++;						// 指针指向下一个字符}
}

10.串口接收函数编写

因为我们在程序执行过程中如果要接收PC机传输过来的数据,则表示程序要进行中断,则要进行中断处理。

void uart_isr(void) interrupt 4 using 1{
}

#include<reg51.h>//函数声明
void uart_init(void);
void uart_send_byte(unsigned char c);
void delay();
void uart_send_string(unsigned char *str);void main(){//第一步:初始化好串口到正确的状态uart_init();uart_send_string("串口回环测试\n");while(1);
}void delay(){unsigned char i,j;for(i=0;i<100;i++){for(j=0;j<200;j++);}
}//串口初始化函数
//预设一个串口条件:8位数据位,1停止位,0校验位,波特率4800
//初始化的主要工作就是去设置相关的寄存器
void uart_init(void){//波特率加倍的例子SCON=0x50; //串口工作在模式1(8位串口),允许接收PCON=0x80;   //波特率加倍,意思是本来需要波特率4800,等一下计算时按照2400去计算就好//通信波特率相关的设置//此处我们使用【方式1】---对应数据手册TMOD=0x20;  //设置T1为模式2TR1=1;	//开启T1让它开始工作TH1=243;TL1=243;    //8位自动重装,意思就是TH1用完了下一个周期TL1会自动重装到TH1中//中断初始化ES=1;//串口中断初始化EA=1;//整个中断初始化}//串口发送函数,发送一个字节【单个字节】
void uart_send_byte(unsigned char c){//【第一步】发送一个字节SBUF=c;//【第二步】先确认串口发送部分没有在忙while(!TI);//TI=0,表示在忙//【第三步】软件复位TI标志位---数据手册要求的TI=0;
}//发送字符串【多个字符】
void uart_send_string(unsigned char *str)
{while (*str != '\0'){uart_send_byte(*str);		// 发送1个字符str++;						// 指针指向下一个字符}
}//中断处理程序
void uart_isr(void) interrupt 4 using 1
{unsigned char tmp;if(RI){tmp=SBUF;   //读取SBUF,其实就是读出串口接收到的1个字节//RI:串行口1接收中断标志RI=0;}//自此已经读到了PC发给单片机的一个字节,但是单片机没有显示器无法显示//我们用最简单的方法,就是直接回发uart_send_byte(tmp);
}

6.RS485

1.UART的缺点:传输距离受限

(1)理论上RS232不超过15米--电脑的COM端口【DB9】

(2)理论上TTL电平通信距离更短---TTL是在单片机上使用

(3)实际上几百米也有人宣称做到了,但是稳定性不能保证

(4)波特率越高通信距离越短【速度越快,通信距离越短】

2.远距离传输

(1)提高电压标准

(2)提高通信线抗干扰能力,降低阻抗

(3)使用差分信号--抗干扰能力强【RS485/RS422】

3.RS485(RS422)

(1)最大通信距离1200多米,最快通信速率10Mbps,距离和速度成反比(USB接口,网线)

(2)差分信号负逻辑【5V代表---0     -3V代表----1】

(3)更远距离可以加中继器【中继器---多个485的节点连接起来--放大】

(4)半双工【如果要实现全双工,则使用4根线】

(5)RS485只提高物理层通信能力,不提供数据层协议,需要用户自定义,或者使用标准协议如MODBUS协议。

4.MAX485

MAX485就是相当于UART与RS485之间的信号转换

(1)CPU本身只会提供URAT接口,而不会提供RS485接口。CPU根本不认识RS485

(2)RS485使用场景:CPUA-->UART转RS485------>远距离通信----->RS485转UART---->CPUB

(3)对RS485的理解:RS485是纯硬件实现的,硬件芯片如MAX485来管理的,根本不涉及软件编程。软件工程师只关注串口,只通过串口将数据发送出去或者接收回来即可。UART转485和485转UART对CPU来说是透明的。

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

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

相关文章

腾讯云 Cloud Studio 实战训练营结营活动获奖公示

点击链接了解详情 “腾讯云 Cloud Studio 实战训练营” 是由腾讯云联合 CSDN 推出的系列开发者技术实践活动&#xff0c;通过技术分享直播、动手实验项目、优秀代码评选、有奖征文活动等&#xff0c;让广大开发者沉浸式体验腾讯云开发者工具 Cloud Studio 的同时&#xff0c;实…

《数据结构、算法与应用C++语言描述》-栈的应用-开关盒布线问题

开关盒布线问题 问题描述 在开关盒布线问题中&#xff0c;给定一个矩形布线区域&#xff0c;其外围有若干管脚。两个管脚之间通过布设一条金属线路来连接。这条金属线路称为电线&#xff0c;它被限制在矩形区域内。两条电线交叉会发生电流短路。因此&#xff0c;电线不许交叉…

Python异步框架大战:FastAPI、Sanic、Tornado VS Go 的 Gin

一、前言 异步编程在构建高性能 Web 应用中起着关键作用&#xff0c;而 FastAPI、Sanic、Tornado 都声称具有卓越的性能。本文将通过性能压测对这些框架与Go的Gin框架进行全面对比&#xff0c;揭示它们之间的差异。 原文&#xff1a;Python异步框架大战&#xff1a;FastAPI、Sa…

【智能家居项目】裸机版本——项目介绍 | 输入子系统(按键) | 单元测试

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《智能家居项目》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f3c0;项目简介&#x1f3c0;输入子系统(按键)⚽应用层⚽设备层⚽ 内核层抽象层⚽…

每日一练-Q1-大数加法-20231001

目录 1.题目描述 2.输入描述 3.示例提示 4.问题分析 5.通过代码 1.题目描述 大数一直是一个c语言的一个难题。 现在我们需要你手动模拟出大数加法过程。 请你给出两个大整数加法结果。 2.输入描述 第一行输入整数n&#xff0c;第二行输入整数m。 (1<number<1e100)…

在nodejs中如何防止ssrf攻击

在nodejs中如何防止ssrf攻击 什么是ssrf攻击 ssrf&#xff08;server-side request forgery&#xff09;是服务器端请求伪造&#xff0c;指攻击者能够从易受攻击的Web应用程序发送精心设计的请求的对其他网站进行攻击。(利用一个可发起网络请求的服务当作跳板来攻击其他服务)…

10月1日作业

汇编指令合集 用select实现服务器并发代码 #include<myhead.h> #define IP "192.168.0.106" #define PORT 8888int main(int argc, const char *argv[]) {//新建套接字文件int sfd socket(AF_INET, SOCK_STREAM, 0);if(sfd < 0){ERR_MSG("socket&quo…

多线程学习笔记(一)

文章目录 1 线程基础知识复习2 CompletableFuture1、Future和Callable接口2、FutureTask3、对Future的改进4、案例精讲——电商5、常用方法6、CompetableFutureWithThreadPool【重要】 3 锁1、乐观锁和悲观锁2、synchronized 8锁案例3、公平锁和非公平锁4、可重入锁5、死锁及排…

web:[RoarCTF 2019]Easy Calc

题目 进入页面是一个计算器的页面 随便试了一下 查看源代码看看有什么有用的信息 访问一下这个calc.php 进行代码审计 <?php error_reporting(0); if(!isset($_GET[num])){show_source(__FILE__); }else{$str $_GET[num];$blacklist [ , \t, \r, \n,\, ", , \[, \]…

Win11下无法打开丛林之狐,提示未检测到DirectX 8.1

新装的win11系统&#xff0c;打开丛林之狐提示未检测到DirectX 8.1. 运行dxdiag检查DirectX版本&#xff1a; DX版本已经是12了&#xff1a; 最终参考了这篇文章解决了&#xff1a; 罪恶都市出现XX-directx version 8.1处理方法 - 知乎 控制面板 > 程序 > 启用或关闭Wi…

蜂蜜配送销售商城小程序的作用是什么

蜂蜜是农产品中重要的一个类目&#xff0c;其受众之广市场需求量大&#xff0c;但由于非人人必需品&#xff0c;因此传统线下门店经营也面临着痛点&#xff0c;线上入驻平台也有很多限制难以打造自有品牌&#xff0c;无法管理销售商品及会员、营销等&#xff0c;缺少自营渠道&a…

力扣 -- 718. 最长重复子数组

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int findLength(vector<int>& nums1, vector<int>& nums2) {int m nums1.size();int n nums2.size();//多开一行&#xff0c;多开一列vector<vector<int>> dp(m 1, ve…

【中秋国庆不断更】OpenHarmony多态样式stateStyles使用场景

Styles和Extend仅仅应用于静态页面的样式复用&#xff0c;stateStyles可以依据组件的内部状态的不同&#xff0c;快速设置不同样式。这就是我们本章要介绍的内容stateStyles&#xff08;又称为&#xff1a;多态样式&#xff09;。 概述 stateStyles是属性方法&#xff0c;可以根…

【数据库——MySQL】(13)过程式对象程序设计——存储函数、错误处理以及事务管理

目录 1. 存储函数2. 存储函数的应用3. 错误处理4. 抛出异常5. 事务处理6. 事务隔离级7. 应用实例参考书籍 1. 存储函数 要 创建 存储函数&#xff0c;需要用到 CREATE 语句&#xff1a; CREATE FUNCTION 存储函数名([参数名 类型, ...])RETURNS 类型[存储函数体]注意&#xff1…

【计算机网络】DNS原理介绍

文章目录 DNS提供的服务DNS的工作机理DNS查询过程DNS缓存 DNS记录和报文DNS记录DNS报文针对DNS服务的攻击 DNS提供的服务 DNS&#xff0c;即域名系统(Domain Name System) 提供的服务 一种实现从主机名到IP地址转换的目录服务&#xff0c;为Internet上的用户应用程序以及其他…

最快的包管理器--pnpm创建vue项目完整步骤

1.用npm全局安装pnpm npm install -g pnpm 2.在要创建vue项目的包下进入cmd&#xff0c;输入&#xff1a; pnpm create vue 3.输入项目名字&#xff0c;选择Router,Pinia,ESLint,Prettier之后点确定 4.cd到创建好的项目 &#xff0c;安装依赖 cd .\刚创建好的项目名称\ p…

Redis配置和优化

Redis配置和优化 一 、Redis介绍二、关系数据库和非关系数据库2.1、关系型数据库2.2、 非关系型数据库2.3、 非关系型数据库的产生背景2.4、 关系型数据库和非关系型数据库区别2.5、 总结 三、缓存概念3.1、系统缓存3.2、 缓存保存位置及分层结构3.2.1、DNS缓存3.2.2、 应用层缓…

笔试练习day01

目录 一、选择题 1、格式化输出 2、逻辑判断--短路原则 3、赋值语句 4、左移、异或 二、编程题 1、组队竞赛 2、删除公共字符 一、选择题 1、格式化输出 知识点&#xff1a;格式化输出&#xff0c;%m.ns 2、逻辑判断--短路原则 知识点&#xff1a; else和最近的if匹…

第一次作业题解

第一次作业题解 P5717 【深基3.习8】三角形分类 思路 考的是if()的使用,还要给三条边判断大小 判断优先级&#xff1a; 三角形&#xff1f;直角、钝角、锐角等腰等边 判断按题给顺序来 代码 #include <stdio.h> int main() {int a 0, b 0, c 0, x 0, y 0, z 0…

排序篇(二)----选择排序

排序篇(二)----选择排序 1.直接选择排序 基本思想&#xff1a; 每一次从待排序的数据元素中选出最小&#xff08;或最大&#xff09;的一个元素&#xff0c;存放在序列的起始位置&#xff0c;直到全部待排序的数据元素排完 。 直接选择排序: ​ 在元素集合array[i]–array[…