串口通信
通信的基本概念
串行和并行通信
数据传送方式
串行与并行通信的特性对比
并行:SDIO(4位,SD卡)、FSMC(16,液晶或显存)、W5100
串行:USART、I2C、SPI、LSB、MSB、W5500
全双工、半双工和单工
数据通信方向
同步和异步
在同步通讯中,数据信号所传输的内容绝大部分就是有效数据,而异步通讯中会包含有帧的各种标识符,所以同步通讯的效率更高,但是同步通讯双方的时钟允许误差较小,而异步通讯双方的时钟允许误差较大。
通信的速率
Bitrate—比特率:每秒钟传输的二进制位数,单位为比特每秒(bit/s)
Baudrate—波特率:表示每秒钟传输的码元个数
一个二进制位表示一个码元
0V —— 0
3.3V —— 1
这时波特率和比特率一样
两个二进制位表示一个码元
0V —— 00
2V —— 01
4V —— 10
6V —— 11
这时波特率和比特率不一样
串口通信
串口通信协议简介
物理层:规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。其实就是硬件部分。
协议层:协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。其实就是软件部分。
简单来说物理层规定我们用嘴巴还是用肢体来交流,协议层则规定我们用中文还是英文来交流。
RS232标准
RS232标准串口通讯结构图
1、RS232标准串口主要用于工业设备直接通信
2、电平转换芯片一般有MAX3232,SP3232
DB9 标准的公头及母头接法
USB转串口
1、USB转串口主要用于设备跟电脑通信
2、电平转换芯片一般有CH340、PL2303、CP2102、FT232
3、使用的时候电脑端需要安装电平转换芯片的驱动
原生的串口到串口
1、原生的串口通信主要是控制器跟串口的设备或者传感器通信,不需要经过电平转换芯片来转换电平,直接就用TTL电平通信
2、GPS模块、GSM模块、串口转WIFI模块、HC04蓝牙模块
起始位:由1个逻辑 0 的数据位表示
结束位:由 0.5、 1、 1.5 或 2 个逻辑 1 的数据位表示
有效数据:在起始位后紧接着的就是有效数据,有效数据的长度常被约定为 5、 6、 7 或 8 位长
校验位:可选,为的是数据的抗干扰性。
校验方法分为:1-奇校验(odd)、 2-偶校验(even) 、3- 0校验(space)、 4-1校验(mark) 、 5-无校验(noparity)
奇校验(odd) :有效数据和校验位中“ 1”的个数为奇数。
比如一个 8 位长的有效数据为: 01101001,此时总共有 4 个“ 1”,为达到奇校验效果,校验位为“ 1”,最后传输的数据将是 8 位的有效数据加上 1 位的校验位总共 9 位。
偶校验(even) :有效数据和校验位中“ 1”的个数为偶数。
比如一个 8 位长的有效数据为: 01101001,此时总共有 4 个“ 1”,为达到偶校验效果,校验位为“ 0”,最后传输的数据将是 8 位的有效数据加上 1 位的校验位总共 9 位。
0 校验是不管有效数据中的内容是什么,校验位总为“ 0”。
1 校验是校验位总为“ 1”。
无校验就是数据包中不包含校验位。
串口功能框图
TX:数据发送
RX:是数据接收
上面俩是最常用的俩
SCLK:时钟,仅同步通信时使用
nRTS:请求发送(Request To Send) n表示低电平有效
nCTS:允许发送(Clear To Send) n表示低电平有效
上面仨基本不用
要注意用USART1的时候需要打开APB2总线,用其他四个的时候要打开APB1总线。
USART的S表示同步的意思。
这里用到了重映射。
固件库结构体和函数
typedef struct
{
uint32_t USART_BaudRate; //波特率 BRR
uint16_t USART_WordLength; //字长 CR1_M
uint16_t USART_StopBits; //停止位 CR2_STOP
uint16_t USART_Parity; //校验控制 CR1_PCE、CR1_PS
uint16_t USART_Mode; //模式选择CR1_TE、CR1_RE
// 硬件流选择 CR3_CTSE、CR3_RTSE
uint16_t USART_HardwareFlowControl;
} USART_InitTypeDef;
typedef struct
{
uint16_t USART_Clock; // 同步时钟 CR2_CLKEN
uint16_t USART_CPOL; // 极性 CR2_CPOL
uint16_t USART_CPHA; // 相位 CR2_CPHA
uint16_t USART_LastBit; //最后一个位的时钟脉冲 CR2_LBC
} USART_ClockInitTypeDef;
//1-串口初始化函数
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)
//2-中断配置函数
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)
//3-串口使能函数
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)
//4-数据发送函数
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
//5-数据接收函数
uint16_t USART_ReceiveData(USART_TypeDef* USARTx)
//6-中断状态位获取函数
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)
程序
1-初始化串口需要用到的GPIO
2-初始化串口,USART_InitTypeDef
3-中断配置(接收中断,中断优先级)
4-使能串口
5-编写发送和接收函数
6-编写中断服务函数
中断接收和发送
使用printf等函数时要用重定向,需要把这个打上勾
usart.c
#include "usart.h"
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中断控制器组选择 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置USART为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
/* 抢断优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置NVIC */
NVIC_Init(&NVIC_InitStructure);
}
void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;