概念
串口,即串行接口,是一种可以将接收来自CPU的并行数据字符转换为连续的串行数据流发送出去,同时可将接收的串行数据流转换为并行的数据字符供给CPU的器件。
串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。
两种通讯方式
三种通讯方向
数据传输只支持数据在一个方向上传输
允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;
允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。
串行通讯的通信方式
同步通信:带时钟同步信号传输。SPI,IIC通信接口。
异步通信:不带时钟同步信号。UART(通用异步收发器),单总线。
常见的串行通信接口
通信标准 | 引脚说明 | 通信方式 | 通信方向 |
UART (通用异步收发器) | TXD:发送端 RXD:接受端 GND:公共地 | 异步通信 | 全双工 |
单总线 (1-wire) | DQ:发送/接受端 | 异步通信 | 半双工 |
SPI | SCK:同步时钟 MISO:主机输入,从机输出 MOSI:主机输出,从机输入 | 同步通信 | 全双工 |
I2C | SCL:同步时钟 SDA:数据输入/输出端 | 同步通信 | 半双工 |
STM32的串口通讯接口
STM32F4XX目前最多支持8个UART,STM32F407一般是6个。具体可以对照选型手册和数据手册来看。
UART异步通信方式引脚连接方法:
-RXD:数据输入引脚。数据接受。
-TXD:数据发送引脚。数据发送。
UART异步通信方式引脚(STM32F407ZGT6):
串口号 | RXD | TXD |
1 | PA10(PB7) | PA9(PB6) |
2 | PA3(PD6) | PA2(PD5) |
3 | PB11(PC11/PD9) | PB10(PC10/PD8) |
4 | PC11(PA1) | PC10(PA0) |
5 | PD2 | PC12 |
6 | PC7(PG9) | PC6(PG14) |
UART异步通信方式特点:
STM32串口通讯过程:
STM32串口异步通信需要定义的参数:
① 起始位
②数据位(8位或者9位)
③ 奇偶校验位(第9位)
④ 停止位(1,15,2位)
⑤ 波特率设置
PCLK1=42MHz
PCLK2=84MHz
PCLK1 用于 USART2~5;
PCLK2 用于 USART1 和USART6;
常用的串口相关寄存器
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
第一个参数入口:(选择串口号)
#define IS_USART_ALL_PERIPH(PERIPH) (((PERIPH) == USART1) || \
((PERIPH) == USART2) || \
((PERIPH) == USART3) || \
((PERIPH) == UART4) || \
((PERIPH) == UART5) || \
((PERIPH) == USART6) || \
((PERIPH) == UART7) || \
((PERIPH) == UART8))
第二个参数入口:(选择中断方式)
#define USART_FLAG_CTS ((uint16_t)0x0200)
#define USART_FLAG_LBD ((uint16_t)0x0100)
#define USART_FLAG_TXE ((uint16_t)0x0080)
#define USART_FLAG_TC ((uint16_t)0x0040)
#define USART_FLAG_RXNE ((uint16_t)0x0020)
#define USART_FLAG_IDLE ((uint16_t)0x0010)
#define USART_FLAG_ORE ((uint16_t)0x0008)
#define USART_FLAG_NE ((uint16_t)0x0004)
#define USART_FLAG_FE ((uint16_t)0x0002)
#define USART_FLAG_PE ((uint16_t)0x0001)
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
第一个参数入口:(选择串口号)
#define IS_USART_ALL_PERIPH(PERIPH) (((PERIPH) == USART1) || \
((PERIPH) == USART2) || \
((PERIPH) == USART3) || \
((PERIPH) == UART4) || \
((PERIPH) == UART5) || \
((PERIPH) == USART6) || \
((PERIPH) == UART7) || \
((PERIPH) == UART8))
第二个参数入口:(需要发送的数据)
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
参数入口:(选择串口号)
#define IS_USART_ALL_PERIPH(PERIPH) (((PERIPH) == USART1) || \
((PERIPH) == USART2) || \
((PERIPH) == USART3) || \
((PERIPH) == UART4) || \
((PERIPH) == UART5) || \
((PERIPH) == USART6) || \
((PERIPH) == UART7) || \
((PERIPH) == UART8))
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
第一个参数入口:(选择串口号)
#define IS_USART_ALL_PERIPH(PERIPH) (((PERIPH) == USART1) || \
((PERIPH) == USART2) || \
((PERIPH) == USART3) || \
((PERIPH) == UART4) || \
((PERIPH) == UART5) || \
((PERIPH) == USART6) || \
((PERIPH) == UART7) || \
((PERIPH) == UART8))
第二个参数入口
typedef struct
{
uint32_t USART_BaudRate; /*!< This member configures the USART communication baud rate.
The baud rate is computed using the following formula:
- IntegerDivider = ((PCLKx) / (8 * (OVR8+1) * (USART_InitStruct->USART_BaudRate)))
- FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 8 * (OVR8+1)) + 0.5
Where OVR8 is the "oversampling by 8 mode" configuration bit in the CR1 register. */
uint16_t USART_WordLength; /*!< Specifies the number of data bits transmitted or received in a frame.
This parameter can be a value of @ref USART_Word_Length */
uint16_t USART_StopBits; /*!< Specifies the number of stop bits transmitted.
This parameter can be a value of @ref USART_Stop_Bits */
uint16_t USART_Parity; /*!< Specifies the parity mode.
This parameter can be a value of @ref USART_Parity
@note When parity is enabled, the computed parity is inserted
at the MSB position of the transmitted data (9th bit when
the word length is set to 9 data bits; 8th bit when the
word length is set to 8 data bits). */
uint16_t USART_Mode; /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.
This parameter can be a value of @ref USART_Mode */
uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
or disabled.
This parameter can be a value of @ref USART_Hardware_Flow_Control */
} USART_InitTypeDef;
串口操作相关库函数配置步骤
①串口时钟使能:RCC_APBxPeriphClockCmd();
GPIO时钟使能:RCC_AHB1PeriphClockCmd();
②引脚复用映射:
GPIO_PinAFConfig();
③GPIO端口模式设置:GPIO_Init(); 模式设置为GPIO_Mode_AF
④串口参数初始化:USART_Init();
⑤开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)
NVIC_Init();
USART_ITConfig();
⑥使能串口:
USART_Cmd();
⑦编写中断处理函数:
USARTx_IRQHandler();
⑧串口数据收发:
void USART_SendData();//发送数据到串口,DR
uint16_tUSART_ReceiveData();//接受数据,从DR读取接受到的数据
⑨串口传输状态获取:
FlagStatus USART_GetFlagStatus();
void USART_ClearITPendingBit();
void My_UART_Init()
{
GPIO_InitTypeDef GPIO_Type_USART;
USART_InitTypeDef USART_Type;
NVIC_InitTypeDef NVIC_Type;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //使能串口1时钟
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
GPIO_Type_USART.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
GPIO_Type_USART.GPIO_Mode=GPIO_Mode_AF;
GPIO_Type_USART.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_Type_USART.GPIO_OType=GPIO_OType_PP;
GPIO_Type_USART.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_Type_USART);
USART_Type.USART_BaudRate = 115200; //波特率
USART_Type.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件流控制
USART_Type.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;//模式
USART_Type.USART_Parity = USART_Parity_No;//奇偶校验
USART_Type.USART_StopBits = USART_StopBits_1;//停止位
USART_Type.USART_WordLength = USART_WordLength_8b;//字长
USART_Init(USART1,&USART_Type); //初始化函数
USART_Cmd(USART1,ENABLE); //使能串口
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //将串口1中断设置为接收中断
NVIC_Type.NVIC_IRQChannel = USART1_IRQn;
NVIC_Type.NVIC_IRQChannelCmd = ENABLE;
NVIC_Type.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_Type.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_Type);
}
void USART1_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(USART1,USART_IT_RXNE)){
res=USART_ReceiveData(USART1);
USART_SendData(USART1,res);
}
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //一定要将中断进行分组
My_UART_Init();
while(1){
;
}
}