/*!
* COPYRIGHT NOTICE
* Copyright (c) 2013,山外科技
* All rights reserved.
* 技术讨论:山外论坛 http://www.vcan123.com
*
* 除注明出处外,以下所有内容版权均属山外科技所有,未经允许,不得用于商业用途,
* 修改内容时必须保留山外科技的版权声明。
*
* @file MK60_uart.c
* @brief uart串口函数
* @author 山外科技
* @version v5.2
* @date 2014-10-09
*/
#include "common.h"
#include "MK60_uart.h"
UART_MemMapPtr UARTN[UART_MAX] = {UART0_BASE_PTR, UART1_BASE_PTR, UART2_BASE_PTR, UART3_BASE_PTR, UART4_BASE_PTR, UART5_BASE_PTR}; //定义五个指针数组保存 UARTN 的地址
/*!
* @brief 初始化串口,设置波特率
* @param UARTn_e 模块号(UART0~UART5)
* @param baud 波特率,如9600、19200、56000、115200等
* @since v5.0
* @note UART所用的管脚在 App\Inc\PORT_cfg.h 里进行配置,
printf所用的管脚和波特率在 App\Inc\MK60_conf.h 里进行配置
* Sample usage: uart_init (UART3, 9600); //初始化串口3,波特率为9600
*/
void uart_init (UARTn_e uratn, uint32 baud)
{
register uint16 sbr, brfa;
uint8 temp;
uint32 sysclk; //时钟
/* 配置 UART功能的 复用管脚 */
switch(uratn)
{
case UART0:
SIM_SCGC4 |= SIM_SCGC4_UART0_MASK; //使能 UART0 时钟
if(UART0_RX_PIN == PTA1)
{
port_init( UART0_RX_PIN, ALT2);
}
else if((UART0_RX_PIN == PTA15) || (UART0_RX_PIN == PTB16) || (UART0_RX_PIN == PTD6) )
{
port_init( UART0_RX_PIN, ALT3);
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
if(UART0_TX_PIN == PTA2)
{
port_init( UART0_TX_PIN, ALT2);
}
else if((UART0_TX_PIN == PTA14) || (UART0_TX_PIN == PTB17) || (UART0_TX_PIN == PTD7) )
{
port_init( UART0_TX_PIN, ALT3);
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
break;
case UART1:
SIM_SCGC4 |= SIM_SCGC4_UART1_MASK;
if((UART1_RX_PIN == PTC3) || (UART1_RX_PIN == PTE1))
{
port_init( UART1_RX_PIN, ALT3);
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
if((UART1_TX_PIN == PTC4) || (UART1_TX_PIN == PTE0))
{
port_init( UART1_TX_PIN, ALT3);
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
break;
case UART2:
SIM_SCGC4 |= SIM_SCGC4_UART2_MASK;
if(UART2_TX_PIN == PTD3)
{
port_init( UART2_TX_PIN, ALT3);
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
if(UART2_RX_PIN == PTD2)
{
port_init( UART2_RX_PIN, ALT3);
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
break;
case UART3:
SIM_SCGC4 |= SIM_SCGC4_UART3_MASK;
if((UART3_RX_PIN == PTB10)|| (UART3_RX_PIN == PTC16) || (UART3_RX_PIN == PTE5) )
{
port_init( UART3_RX_PIN, ALT3);
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
if((UART3_TX_PIN == PTB11) || (UART3_TX_PIN == PTC17) || (UART3_TX_PIN == PTE4) )
{
port_init( UART3_TX_PIN, ALT3); //在PTB11上使能UART3_RXD
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
break;
case UART4:
SIM_SCGC1 |= SIM_SCGC1_UART4_MASK;
if((UART4_RX_PIN == PTC14) || (UART4_RX_PIN == PTE25) )
{
port_init( UART4_RX_PIN, ALT3); //在PTC14上使能UART4_RXD
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
if((UART4_TX_PIN == PTC15) || (UART4_TX_PIN == PTE24) )
{
port_init( UART4_TX_PIN, ALT3);
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
break;
case UART5:
SIM_SCGC1 |= SIM_SCGC1_UART5_MASK;
if((UART5_RX_PIN == PTD8) || (UART5_RX_PIN == PTE9))
{
port_init( UART5_RX_PIN, ALT3);
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
if((UART5_TX_PIN == PTD9) ||(UART5_TX_PIN == PTE8))
{
port_init( UART5_TX_PIN, ALT3); //在PTD9上使能UART5_RXD
}
else
{
ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误?
}
break;
default:
break;
}
//设置的时候,应该禁止发送接受
UART_C2_REG(UARTN[uratn]) &= ~(0
| UART_C2_TE_MASK
| UART_C2_RE_MASK
);
//配置成8位无校验模式
//设置 UART 数据格式、校验方式和停止位位数。通过设置 UART 模块控制寄存器 C1 实现;
UART_C1_REG(UARTN[uratn]) |= (0
//| UART_C1_M_MASK //9 位或 8 位模式选择 : 0 为 8位 ,1 为 9位(注释了表示0,即8位) (如果是9位,位8在UARTx_C3里)
//| UART_C1_PE_MASK //奇偶校验使能(注释了表示禁用)
//| UART_C1_PT_MASK //校验位类型 : 0 为 偶校验 ,1 为 奇校验
);
//计算波特率,串口0、1使用内核时钟,其它串口使用bus时钟
if ((uratn == UART0) || (uratn == UART1))
{
sysclk = core_clk_khz * 1000; //内核时钟
}
else
{
sysclk = bus_clk_khz * 1000; //bus时钟
}
//UART 波特率 = UART 模块时钟 / (16 × (SBR[12:0] + BRFA))
//不考虑 BRFA 的情况下, SBR = UART 模块时钟 / (16 * UART 波特率)
sbr = (uint16)(sysclk / (baud * 16));
if(sbr > 0x1FFF)sbr = 0x1FFF; //SBR 是 13bit,最大为 0x1FFF
//已知 SBR ,则 BRFA = = UART 模块时钟 / UART 波特率 - 16 ×SBR[12:0]
brfa = (sysclk / baud) - (sbr * 16);
ASSERT( brfa <= 0x1F); //断言,如果此值不符合条件,则设置的条件不满足寄存器的设置
//可以通过增大波特率来解决这个问题
//写 SBR
temp = UART_BDH_REG(UARTN[uratn]) & (~UART_BDH_SBR_MASK); //缓存 清空 SBR 的 UARTx_BDH的值
UART_BDH_REG(UARTN[uratn]) = temp | UART_BDH_SBR(sbr >> 8); //先写入SBR高位
UART_BDL_REG(UARTN[uratn]) = UART_BDL_SBR(sbr); //再写入SBR低位
//写 BRFD
temp = UART_C4_REG(UARTN[uratn]) & (~UART_C4_BRFA_MASK) ; //缓存 清空 BRFA 的 UARTx_C4 的值
UART_C4_REG(UARTN[uratn]) = temp | UART_C4_BRFA(brfa); //写入BRFA
//设置FIFO(FIFO的深度是由硬件决定的,软件不能设置)
UART_PFIFO_REG(UARTN[uratn]) |= (0
| UART_PFIFO_TXFE_MASK //使能TX FIFO(注释表示禁止)
//| UART_PFIFO_TXFIFOSIZE(0) //(只读)TX FIFO 大小,0为1字节,1~6为 2^(n+1)字节
| UART_PFIFO_RXFE_MA