众所周知,现今开发板上的485和232是用来进行断距离通信的。对于单片机来说,实际中的通信是用485还是232,没有区别。因为他们两者都用的是单片机的串口功能。
之所以不同,是因为485的硬件通信是通过差分方式来进行的,而232是共模信号,TX和RX是对地的信号。因而在实际接线中,232需将TX和RX还要地线都接上,而485只需接A和B即可。
好了,现在简单介绍一下,STM32库函数讲解串口的常用发送和接收方式。
串口发送和接收引脚是GPIO的复用,所以串口初始化需要使能响应的GPIO和时钟。
GPIO使能:
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
#ifdef USE_STM3210C_EVAL
/* Enable the USART2 Pins Software Remapping */
GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
#elif defined(USE_STM3210B_EVAL) || defined(USE_STM32100B_EVAL)
/* Enable the USART2 Pins Software Remapping */
GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
#endif
/* Configure USARTy Rx as input floating */
GPIO_InitStructure.GPIO_Pin = USARTy_RxPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(USARTy_GPIO, &GPIO_InitStructure);
/* Configure USARTy Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = USARTy_TxPin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(USARTy_GPIO, &GPIO_InitStructure);
}
时钟使能:
/* Enable GPIO clock */
RCC_APB2PeriphClockCmd(USARTy_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE);
#ifndef USE_STM3210C_EVAL
/* Enable USARTy Clock */
RCC_APB2PeriphClockCmd(USARTy_CLK, ENABLE);
#else
/* Enable USARTy Clock */
RCC_APB1PeriphClockCmd(USARTy_CLK, ENABLE);
#endif
接下来初始化串口参数:
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USARTy */
USART_Init(USARTy, &USART_InitStructure);
/************************************************************************************************/
先介绍查询方式。
发送:
void SendByte(uint8_t ch)
{
USART_SendData(EVAL_COM1, (uint8_t) ch);
while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET)
{}
}
接收:
uint8_t RecvgByte(void)
{
while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_RXNE) == RESET)
{}
return USART_ReceiveData(EVAL_COM1);
}
/************************************************************************************************/
使用中断方式时,还需要配置中断:
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USARTz Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
中断响应函数:
if(USART_GetITStatus(USARTy, USART_IT_RXNE) != RESET)
{
/* Read one byte from the receive data register */
RxBuffer[RxCounter] = USART_ReceiveData(USARTy);
if(RxBuffer[RxCounter-1] == '\r' && RxBuffer[RxCounter] == '\n')
{
/* 关闭接受中断,开启发送中断 */
USART_ITConfig(USARTy, USART_IT_RXNE, DISABLE);
USART_ITConfig(USARTy, USART_IT_TXE, ENABLE);
}
RxCounter++;
}
if(USART_GetITStatus(USARTy, USART_IT_TXE) != RESET)
{
/* Write one byte to the transmit data register */
USART_SendData(USARTy,RxBuffer[TxCounter++]);
if(TxCounter == RxCounter)
{
RxCounter = 0;
TxCounter = 0;
/* 关闭接受中断,开启发送中断 */
USART_ITConfig(USARTy, USART_IT_RXNE, ENABLE);
USART_ITConfig(USARTy, USART_IT_TXE, DISABLE);
}
}
中断管理函数:
开发送中断:
USART_ITConfig(USARTy, USART_IT_TXE, ENABLE);
开发送中断:
USART_ITConfig(USARTy, USART_IT_TXE, DISABLE);
开接收中断:
USART_ITConfig(USARTy, USART_IT_RXNE, ENABLE);
关接收中断:
USART_ITConfig(USARTy, USART_IT_RXNE, DISABLE);