最近学习完了STM32系列单片机,所以准备对所学习的知识进行总结,以便以后查阅。
文章的单片机以
MCU:STM32F103C8T6
标准准库:V3.5.0
开发环境:Keil5
通信方式
- 全双工:全双工通信允许数据在两个方向上同时传输,就像打电话一样。在这种模式下,发送和接收设备可以在同一时间互相发送和接收数据,无需进行中继或等待。这种模式需要使用两对线或无线频段,分别用于数据的发送和接收。
- 半双工:半双工通信允许数据在两个方向上传输,但一次只能在一个方向上传输。这种模式需要使用一对线或无线频段,同一时间只能有一个设备发送或接收数据。这种模式通常用于对讲机或某些早期电话系统。
- 单工:单工通信只允许数据在一个方向上传输。这种模式只使用一对线或无线频段,只能在一个设备上发送或接收数据。这种模式通常用于无线电广播或某些简单的通信系统。
异步通信与同步通信
- 异步通信:发送端和接收端各自运行在不同的时钟域中,发送端发送字符时不需要接收端的应答。每个字符(包括起始位、数据位、可选的奇偶校验位和停止位)都是独立发送的。这种方式下,每个字符的传输可能需要较长的时间间隔,因此整体传输效率较低。
- 同步通信:发送端和接收端共享同一时钟源,或者通过其他方式实现时钟同步。发送端按照固定的时间间隔连续发送数据,接收端则根据时钟信号同步接收数据。由于数据是连续传输的,所以同步通信的效率更高。
区别:异步通信没有时钟线,所以数据帧格式与同步通信方式有所区别。
一、UART介绍
USART全双工的,异步通信,任何USART双向通信至少需要两个脚:接
收数据输入(RX)和发送数据输出(TX)。UART只有异步传输功能。本文主要介绍UART串口通信。
UART的帧格式:起始位、数据帧、校验位、停止位
- 起始位(1):当UART空闲时,总线为高电平。当需要数据传输时,首先发送一个起始位,起始位为一个低电平“逻辑0”。
- 数据帧(8):紧挨着起始位的是数据位,数据位可以是5、6、7、8位,收发双方在数据开始传输前,需要对双方数据位作一致的定义,否则会导致数据的传输错误。数据位发送采用低位LSB(Least Significant Bit)先发送。
- 校验位:这是可选的比特,用于验证数据的正确性。奇偶校验位的值可以是奇校验或偶校验,它们根据数据位中1的个数确定。在收/发双方进行数据传输前要预设好是否需要校验位,如果需要则是奇校验还是偶校验。
- 停止位(1):这是数据传输结束的标志,可以是1/1.5/2位的逻辑1(高电平)
二、UART初始化
typedef struct {
uint32_t USART_BaudRate; // 波特率
uint16_t USART_WordLength; // 字长
uint16_t USART_StopBits; // 停止位
uint16_t USART_Parity; // 校验位
uint16_t USART_Mode; // USART 模式
uint16_t USART_HardwareFlowControl; // 硬件流控制
} USART_InitTypeDef;
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//IO配置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//串口配置 9600 8 N 1
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;//波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //发送与接收模式
USART_InitStructure.USART_Parity = USART_Parity_No;//没有校验位
USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位 1
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位 8
USART_Init(USART1, &USART_InitStructure);
//接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1, ENABLE);
}
/*发送一个字节*/
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1, Byte);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);//等待发送完成
}
uint8_t Serial_RxData;//接收的数据
uint8_t Serial_RxFlag;//接收完成标志
//中断处理函数
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
Serial_RxData = USART_ReceiveData(USART1);
Serial_RxFlag = 1;
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
/*
引入 <stdio.h>重新弄printf,在keil配置中勾选上 Use MicroLIB,之后就可以使用printf打印信息
*/
int fputc(int ch, FILE *f)
{
Serial_SendByte(ch);
return ch;
}