本章概述思维导图
通信介绍
通信介绍概况
通信,至少是需要两个对象,一个收一个发数据。
根据数据通信的传输时序协调方式,可分为:同步通信和异步通信;
根据数据通信的传输线路可分为:串行通信和并行通信;
根据数据通信的传输方向性及双向交互能力可分为:单工通信和双工通信(半双工通信和全双工通信)
同步通信和异步通信定义
同步通信:发送方与接收方通过共享时钟线的时钟信号,确保数据按固定时间间隔传输,接收方能准确预测数据到达时间;
异步通信:发送方与接收方无共享时钟线,通过数据包或数据帧格式(如起始信号/停止位)协调传输数据;
同步和异步的区别:同步通讯需要有时钟信号控制,通过时钟线的高低电平控制数据的收发;异步通信没有时钟信号控制,通过数据帧格式控制数据的收发(大家约定好通信速度(波特率));
小心得:就是一个有时钟线提供时钟时序,一个没有时钟线;
串行通信和并行通信定义
串行通信:数据按位顺序传输,使用单条线路进行数据得传输。例如,发送字节 10110010
时,先传 1
,再传 0
,以此类推。
并行通信:数据的多个位(通常8位、16位等)同时通过多条线独立线路并行传输。如传输字节 10110010
,会使用8根数据线,每根线同时传1位。
串行和并行的区别;
串行通信指同一时刻,只能收或发一个bit位信息,因此只用一根数据信号线即可;并行通信指同一时刻,可以收或发多个bit位信息,因此需要多根数据信号线才行;
单工和半双工、全双工定义
单工通信:数据仅能沿固定方向单向传输,发送端与接收端角色不可互换。
应用场景:广播系统(电台→听众、卫星数据下行)、传感器网络(如温湿度传感器→数据中心)等;
半双工通信:同一信道分时复用,双方交替发送和接收;
应用场景:对讲机、传统Wi-Fi;
全双工通信:双方可同时发送和接收数据;
应用场景:电话通话、以太网交换机等;
单工和半双工、全双工的区别:
单工通信:单工要么收要么发,只能做接收设备或者发送设备。接收器不能发送数据给 发送器。例如:收音机;
半双工通信:双发都可以发送数据,双方不能同时发送数据或接收数据;只有一根发送/接收数据信号线。(特点:可以收可以发,但是不能同时收发)例如:对讲机;
全双工通信:双方可以同时发送或者接收数据;有两根发送/接收数据信号线;(特点:可以同时即发送又接收数据)例如:手机
USART串口通信
串口(USART)通讯:异步通讯、全双工、串行通讯、总线协议;
USART通用同步异步收发器,是一种通用的串行、异步/同步通信总线。该总线有两条数据信号线,可以实现全双工的发送和接收;
波特率:用于描述USART串口通信时的通信速度,其单位(bps)即每秒钟传送的位(bit) 的数量
上位机:就是连接串口的电脑或者手机上的APP软件;是在自动化控制系统中,用于监控 和控制下位机(如单片机、PLC等)的计算机。它可以直接发送操作指令给下位机, 并接收下位机的反馈数据,通过用户操作交互界面向用户展示数据。
USART采用帧格式从低位开始发送数据——>高位
串口通信是不允许连续发送,避免累积误差。所以发送完一字节数据后就得停止重新发送;
USART1串口1电路原理图
1. 分析原理图,查看对应引脚
分析原理图这是串口USART1实现下载程序功能
我们不能随意配置USART1的引脚,要根据STM32F103X引脚定义手册来查看USART1配置的引脚;
TXD发送数据脚--->PA10(数据接收脚)
RXD接收数据脚--->PA9 (数据发送脚)
串口属于自行控制数据的收发,所以我们应设置GPIO引脚模式为复用模式;
发送对接收;PA10设置为复用输入模式,PA9设置为复用输出模式;
2. 配置串口1(USART1)模块初始化函数
配置USART1串口初始化函数步骤:
1. 开时钟
2. 对串口1模块开启复位时钟,在取消复位;
3. 配置GPIO模式
4. 通过在USART_CR1寄存器上置位UE位来激活USART
5. 编程USART_CR1的M位来定义字长。
6. 在USART_CR2中编程停止位的位数。
7. 利用USART_BRR寄存器选择要求的波特率。
8. 设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。
9. 设置USART_CR1的RE位。激活接收器,使它开始寻找起始位。
代码示例:
#include "USART1.h"
/*USART1串口初始化函数形参bps——>保持通信的波特率PA10设置为输入模式,PA9设置为复用输出模式;
*/
void USART1_Init(u32 bps)
{
// 1. 开时钟RCC->APB2ENR|=1<<2;//开启PA时钟;RCC->APB2ENR|=1<<14;//开启USART1时钟
// 2. 对串口1模块开启复位时钟,在取消复位;RCC->APB2RSTR|=1<<14;//开启USART1复位时钟,复位这一步可以省略配置USART1步骤RCC->APB2RSTR&=~(1<<14);//取消复位时钟,关闭复位
// 3. 配置GPIO模式GPIOA->CRH&=0xfffff00f;//清空PA10、PA9引脚模式GPIOA->CRH|=0x000008b0;//PA10输入PA9输出
// 4.通过在USART_CR1寄存器上置位UE位来激活USARTUSART1->CR1|=1<<13;
// 5.编程USART_CR1的M位来定义字长。USART1->CR1&=~(1<<12);
// 6.在USART_CR2中编程停止位的位数。USART1->CR2&=~(0x3<<12);
// 7.利用USART_BRR寄存器选择要求的波特率。USART1->BRR=72000000/bps;
// 8.设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。USART1->CR1|=1<<3;
// 9.设置USART_CR1的RE位。激活接收器,使它开始寻找起始位。USART1->CR1|=1<<2;
}
3. USART1串口底层发送数据函数
USART1串口数据发送函数(以数据帧格式发送):
配置步骤:
1.把发送的数据放入到USART_DR数据寄存器
2.判断USART_SR状态寄存器的TXE(发送数据寄存器空)位数据是否发送完成
代码示例:
/*USART1串口底层数据发送函数形参:temp——>发送的数据
*/
void USART1_TX(u8 *temp)
{while(*temp){USART1->DR=*temp++;while(&(USART1->SR&1<<7)){}}
}
测试USART1串口初始化函数和USART1串口底层发送函数
代码示例:
#include "LED.h"
#include "Delay.h"
#include "SYSTICK.h"
#include "BEEP.h"
#include "KEY.h"
#include "USART1.h"
int main()
{LED_Init();//LED灯初始化函数BEEP_Init();//蜂鸣器初始化函数KEY_Init();//按键初始化函数USART1_Init(115200);//USART1串口1初始化函数USART1_TX((u8 *)"串口1初始化完成\n");//发送"串口1初始化完成"这句话while(1){}
}
测试结果:
4. 串口读取/接收数据操作
操作步骤:
1. 首先判断USART1_SR寄存器中RXNE(读数据寄存器非空),置1表示收到数据,可以读出。置0表示数据没有收到;
2. 将收到数据返回给上位机终端显示
代码示例:
#include "LED.h"
#include "Delay.h"
#include "SYSTICK.h"
#include "BEEP.h"
#include "KEY.h"
#include "USART1.h"
int main()
{LED_Init();//LED灯初始化函数BEEP_Init();//蜂鸣器初始化函数KEY_Init();//按键初始化函数USART1_Init(115200);//USART1串口1初始化函数USART1_TX((u8 *)"串口1初始化完成\n");u8 dat=0;while(1){if(USART1->SR&1<<5){dat=USART1->DR;//读取数据USART1->DR=dat;//将读取的数据在上位机软件显示}}
}
上位机软件发送数据给USART1串口判断是否接收:
发送结果显示:
5. printf( )打印函数使用USART1底层实现
在我们以后项目开发过程中会遇到各种各样的开发问题,使用printf( )函数可以让我们快速方便的查找问题!解决问题!下面是利用串口1实现printf( )函数的底层实现;
配置步骤:
1.在<stdio.h>文件中查找函数fputc
2.创建printf( )打印函数
3.实现printf函数还需在keil v5中的魔法棒中第二个选项卡Target中勾选右上角的Use Micro LIB;
代码示例:
/*printf函数底层接口实现形参:tx——发送的内容注意:不需要声明哟!
*/
int fputc(int tx, FILE *stream)
{USART1->DR=tx;while(!(USART1->SR&1<<7)){}return tx;
}
第三步操作:
测试printf( )函数实现代码示例:
#include "USART1.h"
#include "stdio.h"
int main()
{USART1_Init(115200);//USART1串口1初始化函数printf("大河向东流哇\n天上的星星参北斗哇\n嘿嘿 参北斗哇\n生死之交一碗酒哇\n说走咱就走哇\n你有我有全都有哇\n嘿嘿 全都有哇\n");while(1){}
}
测试结果
6. 显示USART1接收到的数据
代码示例:
#include "stm32f10x.h"
#include "Delay.h"
#include "USART.h"
#include <stdio.h>int main()
{USART1_Init(115200);//串口1初始化函数USART1_TX((u8 *)"串口1初始化成功\n");u8 dat; //读取数据 u8 buffer[100];//接收数据的数组 u8 cnt=0;//下标while(1){if(USART1->SR&1<<5){dat=USART1->DR;//读取数据buffer[cnt]=dat;//将读取的数据放入到数组中if(dat == '\n'){buffer[cnt-1]='\0';//上位机软件设置时以\r\n结尾。手动把\r改成数组结束标准符printf("buf=%s;\tcnt=%d\n",buffer,cnt);cnt=0;}else cnt++;}}
}
制作不易!喜欢的小伙伴给个小赞赞!喜欢我的小伙伴可以点关注!有不懂的地方和需要的资源随时问我哟!