UART是单片机的一种重要的通信接口,通信参数涉及到波特率、数据长度、奇偶校验、停止位。
工业上往往有要求在线修改(无需重启单片机)串口通信参数的要求,同时对奇偶校验也有要求,除无校验、奇校验、偶校验外,还有MARK校验和SPACE校验:
void bsp_SetUartBaud(COM_PORT_E _ucPort,uint32_t _baud,uint16_t _wordLen, uint16_t _parity, uint16_t _stopBits)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = _baud;
if (_parity==0)
{
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_Parity = USART_Parity_No ;
}
else if (_parity==1)
{
if (_wordLen==7)
{
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_Parity = USART_Parity_Odd ;
}
else
{
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_Parity = USART_Parity_Odd ;
}
}
else if (_parity==2)
{
if (_wordLen==7)
{
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_Parity = USART_Parity_Even ;
}
else
{
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_Parity = USART_Parity_Even ;
}
}
else if (_parity==3)//Mark校验
{
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_Parity = USART_Parity_No ;
}
else if (_parity==4)//Space校验
{
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_Parity = USART_Parity_No ;
}
if (_stopBits==1)
USART_InitStructure.USART_StopBits = USART_StopBits_1;
else
USART_InitStructure.USART_StopBits = USART_StopBits_2;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
switch (_ucPort)
{
case COM1:USART_Init(USART1, &USART_InitStructure);break;
case COM2:USART_Init(USART2, &USART_InitStructure);break;
case COM3:USART_Init(USART3, &USART_InitStructure);break;
case COM4:USART_Init(UART4, &USART_InitStructure);break;
case COM5:USART_Init(UART5, &USART_InitStructure);break;
default:USART_Init(USART1, &USART_InitStructure);break;
}
}
void COM_SendString(COM_PORT_E _ucPort, uint8_t* Data,u16 Len,uint16_t Parity)
{
uint16_t i=0;
USART_TypeDef *pUart;
pUart = ComToUart(_ucPort);
if (pUart == 0)
{
return;
}
USART_ClearFlag(pUart,USART_FLAG_TC);
for(i=0;i<Len;i++)
{
switch (Parity)
{
case 3:USART_SendData(pUart, 0x100 | *Data);break;//MARK校验
case 4:USART_SendData(pUart, 0xFF & *Data);break;//SPACE校验
default:USART_SendData(pUart, *Data);break;
}
while( USART_GetFlagStatus(pUart, USART_FLAG_TC) == RESET );
Data++;
}
}
另外,串口在接收数据时,数据的长度是不固定的,这种情况下就要使用IDLE中断。
IDLE中断是在串口接收完一串完整数据后,电平归0一段时间(不同波特率下这段时间会有区别)产生的中断,IDLE中断的产生代表数据传输过程完毕:
static void InitHardUart(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
#if UART1_FIFO_EN == 1 /* 串口1 TX = PA9 RX = PA10 或 TX = PB6 RX = PB7*/
/* 第1步:打开GPIO和USART部件的时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* 第2步:将USART Tx的GPIO配置为推挽复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第3步:将USART Rx的GPIO配置为浮空输入模式
由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的
但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第4步: 配置串口硬件参数 */
USART_InitStructure.USART_BaudRate = UART1_BAUD; /* 波特率 */
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;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* 使能接收中断 */
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); /* 使能IDLE中断 */
/*
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
注意: 不要在此处打开发送中断
发送中断使能在SendUart()函数打开
*/
USART_Cmd(USART1, ENABLE); /* 使能串口 */
/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
如下语句解决第1个字节无法正确发送出去的问题 */
// USART_ClearFlag(USART1, USART_FLAG_TC); /* 清发送完成标志,Transmission Complete flag */
#endif
}
void USART1_IRQHandler(void)
{
uint8_t clear;
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
if (RxCount1 >=UART1_RX_BUF_SIZE)
RxCount1=0;
g_RxBuf1[RxCount1] = USART_ReceiveData(USART1);
RxCount1++;
}
if (USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
{
clear=USART1->SR;
clear=USART1->DR;
RecvFinished1=1;
}
if(USART_GetFlagStatus(USART1,USART_FLAG_ORE) == SET)
{
USART_ClearFlag(USART1,USART_FLAG_ORE);
USART_ReceiveData(USART1);
}
}