一.底层驱动配置
1.手册解读
5017共支持6路串口,且均可配置38k载波红外输出,主要功能与普通串口一致,不做赘述,直接看寄存器;
如图1,是主要的串口配置寄存器:
图1
2.原理图解读
我们的表共有三中通信方式,分别是载波、红外以及485,均通过串口方式进行数据的读取和发送:
如图2:RXD485接芯片RX3管脚,TXD485接芯片TX4管脚;
图2
3.软件配置
想要我们的硬件串口模块正常工作就需要配置使能,主要从以下方面进行配置:
.1串口模块时钟使能;
.2确定一种串口工作方式,然后配置寄存器;
3.1芯片库函数
下面是芯片提供的配置串口库函数,我们在配置串口的时候可以直接调用,只需给定必要的参数即可:
/*
*********************************************************************************************************
* INITIAL UART MODULE
*
* 函数说明: 初始化UART模块
*
* 入口参数: UARTx 只能是HT_UART0/HT_UART1/HT_UART2/HT_UART3/HT_UART4/HT_UART5中一个
*
* UART_InitStruct UART初始化结构体指针,主要包含7个参数:
* 1) UART_Logic : UART通讯逻辑设定
* 2) UART_StopBits : UART通讯停止位设定
* 3) UART_WordLength : UART通讯数据位长度设定
* 4) UART_Parity : UART通讯奇偶校验设定
* 5) UART_BaudRate : UART通讯波特率
* 6) ReceiveEN : UART接收使能控制
* 7) SendEN : UART发送使能控制
*
* 返回参数: 无
*
* 特殊说明: 1) HT_UART3/HT_UART4与ISO7816功能复用,如果这边有对HT_UART3/HT_UART4初始化,则不能再使用
* HT_ISO7816_0/HT_ISO7816_1功能,其对应关系为:
* HT_UART3 <----->HT_ISO7816_1
* HT_UART4 <----->HT_ISO7816_0
* 2) 由于涉及到波特率计算,所以用户在调用此函数时应先配置好系统时钟。否则如果已经配置好波特率,
* 再改变系统时钟,则波特率配置将失效
* 3) 用户在配置UART寄存器前应先使能UART模块,具体参见HT_CMU_ClkCtrl1Config()函数
*********************************************************************************************************
*/
void HT_UART_Init(HT_UART_TypeDef* UARTx, UART_InitTypeDef* UART_InitStruct)
{
/* assert_param */
uint32_t tempreg,sysclk;
UARTx->MODESEL = UART_MODESEL_UART; /*!< 选择为UART功能 */
/*!< 只对Uart3/4有效 */
tempreg = UARTx->UARTCON & (UART_UARTCON_TXIE | UART_UARTCON_RXIE); /*!< 保留TXIE,RXIE不变 */
if(UART_InitStruct->UART_Parity != UartParity_Disable )
{
tempreg |= UART_UARTCON_PARITYEN;
tempreg |= UART_InitStruct->UART_Parity; /*!< 配置奇偶校验位 */
}
tempreg |= UART_InitStruct->UART_Logic; /*!< 配置UART通讯逻辑 */
tempreg |= UART_InitStruct->UART_StopBits; /*!< 配置停止位 */
tempreg |= UART_InitStruct->UART_WordLength; /*!< 配置通讯数据长度 */
if(UART_InitStruct->ReceiveEN != DISABLE)
{
tempreg |= UART_UARTCON_RXEN; /*!< 配置接收使能 */
}
if(UART_InitStruct->SendEN != DISABLE)
{
tempreg |= UART_UARTCON_TXEN; /*!< 配置发送使能 */
}
UARTx->UARTCON = tempreg; /*!< 配置寄存器 */
sysclk = HT_CMU_SysClkGet()>>1; /*!< 获取当前系统时钟频率/2 */
UARTx->SREL = sysclk/UART_InitStruct->UART_BaudRate-1; /*!< 计算波特率 */
UARTx->IRCON &= ~UART_IRCON_IRTX; /*!< 关闭红外调制输出功能 */
}
3.2底层驱动
3.2.1数据结构
typedef struct
{
UARTLogic_TypeDef UART_Logic; /*!< 串口逻辑设置 */
UARTStopBits_TypeDef UART_StopBits; /*!< 串口停止位设置 */
UARTWordLength_TypeDef UART_WordLength; /*!< 串口通讯数据长度设置 */
UARTParity_TypeDef UART_Parity; /*!< 串口奇偶校验位设置 */
uint32_t UART_BaudRate; /*!< 串口波特率, 比如1200, 2400 */
FunctionalState ReceiveEN; /*!< 串口接收使能控制 */
FunctionalState SendEN; /*!< 串口发送使能控制 */
}UART_InitTypeDef; /*!< end of group UART_InitTypeDef */
3.2.2打开串口
u08 OpenMcuUart (u08 *pSrc, u08 ChannelNo)
{
u08 ReturnData;
UART_InitTypeDef UartInitStruct;
IR_InitTypeDef IrInitStruct;
ReturnData = GAL_YES;
/* 先关闭, 再打开 */
CloseMcuUart(ChannelNo);
/* 停止位 */
if (2 == *(pSrc + 0))
{
UartInitStruct.UART_StopBits = TwoStopBits;
}
else
{
UartInitStruct.UART_StopBits = OneStopBits;
}
/* 数据长度 */
if (7 == *(pSrc + 1))
{
UartInitStruct.UART_WordLength = WordLength_7Bits;
}
else
{
UartInitStruct.UART_WordLength = WordLength_8Bits;
}
/* 校验位 */
if (0 == *(pSrc + 2))
{
UartInitStruct.UART_Parity = UartParity_Disable;
}
else if (1 == *(pSrc + 2))
{
UartInitStruct.UART_Parity = UartParity_ODD;
}
else
{
UartInitStruct.UART_Parity = UartParity_EVEN;
}
UartInitStruct.UART_Logic = UartLogicPositive;
UartInitStruct.UART_BaudRate = TabBaudRate[*(pSrc + 3)];
UartInitStruct.ReceiveEN = ENABLE;
UartInitStruct.SendEN = ENABLE;
HT_UART_Init(HT_UART3, &UartInitStruct);
InitUartIO(UART_DRV_CHNL_3, SYSTEM_POWERON);
}
3.2.3中断配置
内核中断向量配置及优先级配置:
/*******************************************************************************
* FUNCTION: InitMcuNvic
* DESCRIPTION: 中断向量及优先级初始化
* INPUT: 无
* OUTPUT: 无
* RETURN: 无
* OTHERS:
* HISTORY:
*******************************************************************************/
void InitMcuNvic (u08 SystemMode)
{
NVIC_ClearPendingIRQ(UART3_IRQn);
NVIC_EnableIRQ(UART3_IRQn); /* 串口3中断, 红外 */
NVIC_SetPriority(UART3_IRQn, 2);
}
置接收状态:
/*******************************************************************************
* FUNCTION: SetMcuUartReceive
* DESCRIPTION: 切换MCU内部UART到接收状态
* INPUT: u08 ChannelNo
* - 串口通道号
* OUTPUT:
* RETURN:
* OTHERS:
* HISTORY:
*******************************************************************************/
void SetMcuUartReceive (u08 ChannelNo)
{
UartDrvStatus[ChannelNo] = UART_RECV_STATUS;
/* 串口切换到接收 */
HT_UART_ITConfig(HT_UART3, UART_UARTCON_TXIE, DISABLE);
HT_UART_ITConfig(HT_UART3, UART_UARTCON_RXIE, ENABLE);
break;
default:
break;
}
置发送状态:
/*******************************************************************************
* FUNCTION: SetMcuUartSend
* DESCRIPTION: 切换MCU内部UART到发送状态
* INPUT: u08 ChannelNo
* - 串口通道号
* OUTPUT:
* RETURN:
* OTHERS:
* HISTORY:
*******************************************************************************/
void SetMcuUartSend (u08 ChannelNo)
{
/* 置状态 */
UartDrvStatus[ChannelNo] = UART_SEND_STATUS;
case UART_DRV_CHNL_3:
/* 关闭接收使能 */
// HT_UART3->UARTCON &= ~UART_UARTCON_RXEN;
/* 485串口切换到发送 */
HT_UART_ITConfig(HT_UART3, UART_UARTCON_RXIE, DISABLE);
HT_UART_ITConfig(HT_UART3, UART_UARTCON_TXIE, ENABLE);
break;
}
中断处理函数,在配置好串口模式以及中断后,当我们接收或发送数据完成时,均会触发中断从而进入到中断处理函数,这里主要是完成对标志位的清除和对串口SBUF缓存数据的捞取:
/*******************************************************************************
* FUNCTION: UART3_IRQHandler
* DESCRIPTION: 串口3中断处理函数, 用于红外通讯
* INPUT:
* OUTPUT:
* RETURN:
* OTHERS:
* HISTORY:
*******************************************************************************/
void UART3_IRQHandler (void)
{
/* 接收中断 */
if (SET == HT_UART_ITFlagStatusGet(HT_UART3, UART_UARTSTA_RXIF))
{
HT_UART_ClearITPendingBit(HT_UART3, UART_UARTSTA_RXIF);
/* 先判断校验状态 */
if (RESET == HT_UART_ITFlagStatusGet(HT_UART3, UART_UARTSTA_PARITY))
{
UartDrvBuff[UART_DRV_CHNL_3].Buff[UartDrvBuff[UART_DRV_CHNL_3].In++] = HT_UART_ReceiveData(HT_UART3);
if(UartDrvBuff[UART_DRV_CHNL_3].In >= UART_DRV_LEN)
{
UartDrvBuff[UART_DRV_CHNL_3].In = 0;
}
}
else
{
HT_UART_ClearITPendingBit(HT_UART3, UART_UARTSTA_PARITY);
}
}
/* 发送中断 */
if (SET == HT_UART_ITFlagStatusGet(HT_UART3, UART_UARTSTA_TXIF))
{
HT_UART_ClearITPendingBit(HT_UART3, UART_UARTSTA_TXIF);
if(UartDrvBuff[UART_DRV_CHNL_3].Out != UartDrvBuff[UART_DRV_CHNL_3].In)
{
HT_UART_SendData(HT_UART3, UartDrvBuff[UART_DRV_CHNL_3].Buff[UartDrvBuff[UART_DRV_CHNL_3].Out++]);
}
else
{
UartDrvBuff[UART_DRV_CHNL_3].In = 0;
UartDrvBuff[UART_DRV_CHNL_3].Out = 0;
SetMcuUartReceive(UART_DRV_CHNL_3);
}
}
}
总结: