1.什么串口
首先,串口、UART口、COM口、USB口是指的物理接口形式(硬件)。而TTL、RS-232、RS-485是指的电平标准(电信号)。
串口:串口是一个泛称,UART,TTL,RS232,RS485都遵循类似的通信时序协议,因此都被通称为串口。
我们今天学习的主要是USART(通用的同步异步收发器)和UART(通用的异步收发器)
几个概念:
同步:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
串行通信:数据在传输的过程中是按位传输 spi iic 485(1200米) can
数据传输速度慢,传输距离远 usart(15米)
并行通信:数据在传输的时候,一次可以传输多位数据(8bit 16bit 24bit 64bit… 8080) 数据传输速度块,传输距离近
单工通信:是指消息只能单方向传输的工作方式。例如遥控、遥测,
半双工通信:允许在两个方向上传输数据,即从A端发送数据到B端,或从B端发送数据至A端,但不能同时进行双向传输,方向的选择数据终端控制。
全双工通信:发送数据的同时也能够接收数据,两者同步进行
2.串口–USART介绍
通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。 USART利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。使用多缓冲器配置的DMA方式,可以实现高速数据通信
波特率:单位时间(秒)内传输数据的位数 9600
单位时间内传送的码元符号的个数,它是对符号传输速率的一种度量,它用单位时间内载波调制状态改变的次数来表示,波特率即指一个单位时间内传输符号的个数。
2.1USART主要特性
● 全双工的,异步通信
● NRZ标准格式
● 分数波特率发生器系统
─ 发送和接收共用的可编程波特率,最高达4.5Mbits/s
● 可编程数据字长度(8位或9位)–有效数据
● 可配置的停止位-支持1或2个停止位
● 单线半双工通信
● 可配置的使用DMA的多缓冲器通信
─ 在SRAM里利用集中式DMA缓冲接收/发送字节
● 单独的发送器和接收器使能位
2.2功能描述:
任何USART双向通信至少需要两个脚:接收数据输入(RX)和发送数据输出(TX)。
USART1进行操作:
停止位:
配置流程:
2.3分数波特率的产生
常用波特率:9600 115200 38400…
TX/RX波特率:9600 115200 38400......
fck:72MHZ
USARTDIV=72000000/(16*9600)
得到USARTDIV将正数部分和小数部分分开
最终再次整合保存到BRR寄存器中
校验:奇偶校验
校验主要用于检测数据再发送的过程中是否出现错误
奇校验:检测数据中1的个数是否为奇数个
偶校验:检测数据中1的个数是否为偶数个
使用奇校验:发送方1010 1010 1 接收方接收到数据之后,再次对10101010进行校验,得到一个校验码,和发送方对比。
当前测试例程的示意图:
串口配置:
#include "my_usart1.h"
//#include "stdlib.h"
/*
1.开时钟:A端口时钟 串口1时钟
2.配置IO口的工作模式
PA9--复用推挽输出
PA10--浮空输入
3.配置串口工作模式
起始位 数据位 校验位 停止位 波特率
*/
void usart1_Config(u32 brr)
{
float div;
uint32_t integer;//整数部分
uint32_t decimal;//小数部分
//打开时钟
RCC->APB2ENR |=(0X01<<2);//A端口
RCC->APB2ENR |=(0X01<<14);//usart1时钟
//IO口-PA9_TX和PA10_RX
GPIOA->CRH &=~(0X0F<<4);//清零
GPIOA->CRH |=(0X09<<4);//复用推挽
//PA10_RX
GPIOA->CRH &=~(0X0F<<8);//清零
GPIOA->CRH |=(0X04<<8);//浮空
/*
3.配置串口工作模式
起始位 数据位 校验位 停止位 波特率 使能(一般写在最后)
*/
USART1->CR1 &=~(0X01<<12);//字长
USART1->CR1 |=(0X03<<2);//收发使能
//奇偶校验我们现在不使用,所以就没配置
USART1->CR2 &=~(0X03<<12);//停止位
//波特率--usartdiv=72000000HZ*16/brr
div=72000000.0/(brr*16);
integer=(u32)div;
decimal=(div-integer)*16+0.5f;
USART1->BRR =integer<<4|decimal;
//使能
USART1->CR1 |=0X01<<13;
}
//测试函数
void usart_Echo(void)
{
u8 data;
//接收数据
while(!(USART1->SR &(0X01<<5)));//0取非 1
data=USART1->DR;
while(!(USART1->SR &(0X01<<7)));
USART1->DR=data;
}
//printf函数为什么可以打印,就是因为以下函数
int fputc(int c, FILE * stream)
{
while(!(USART1->SR &(0X01<<7)));
USART1->DR=c;
return c;
}