//**************************************************************************
//SCI.c：SCI通信函数
//**************************************************************************

//头文件
#include "SCI.h"    //SCI头文件
#include <string.h>

//**************************************************************************
//函数名称：SCIInit 
//函数功能：初始化指定SCI模块并设置波特率。
//入口参数：port-SCI模块号(1或者2),如果带入1和2以外的参数,均默认为1
//          fbus-系统总线时钟频率,单位为MHz
//          baud-SCI通信波特率,如9600,19200,38400 等
//出口参数：无
//备    注：SCI初始化完成以后,SCI的中断是禁止的。
//**************************************************************************
void SCIInit(UINT8 cPort, UINT16 nBusClk_In_MHz, UINT32 nBaud)
{
    UINT32 tmp;
    
    //1. 参数有效性检查
    if (cPort > 2)
    {
        cPort = 1;
    }
    //2. SCI1设置
    if (cPort == 1)
    {
        //2.1 设置SCI1通信波特率(fsci = fbus / (16 * BR)),BR为波特率分频因子
        tmp = nBusClk_In_MHz * 1000000;
        tmp >>= 4;
        tmp /= nBaud;
        SCI1BDH = (UINT8)((tmp & 0x0000FF00)>>8);
        SCI1BDL = (UINT8)(tmp & 0x000000FF);
        //2.2 配置SCI1
        SCI1C1 = 0x00;    //8位数据,不进行奇偶校验
        SCI1C2 = 0x0C;    //禁止SCI发送接收中断,开SCI发送和接收器
    }
    //3. SCI2设置
    else if (cPort == 2)
    {
        //3.1 设置SCI2通信波特率(fsci = fbus / (16 * BR)),BR为波特率分频因子
        tmp = nBusClk_In_MHz * 1000000;
        tmp >>= 4;
        tmp /= nBaud;
        SCI2BDH = (UINT8)((tmp & 0x0000FF00)>>8);
        SCI2BDL = (UINT8)(tmp & 0x000000FF);
        //3.2 配置SCI2
        SCI2C1 = 0x00;    //8位数据,不进行奇偶校验
        SCI2C2 = 0x0C;    //禁止SCI发送接收中断,开SCI发送和接收器
    }
}

//**************************************************************************
//函数名称：SCISend1 
//函数功能：从指定SCI端口发送1字节数据
//入口参数：cPort-SCI模块号(1或者2),如果带入1和2以外的参数,均默认为1
//          cData-要发送的1字节数据
//出口参数：无
//备    注：
//**************************************************************************
void SCISend1(UINT8 cPort, UINT8 cData)
{

    //1. 参数有效性检查
    if (cPort > 2)
    {
        cPort = 1;
    }
    //2. 发送1字节数据
    //2.1 从SCI1发送1字节数据
    if (cPort == 1)
    {
        //判断SCI1发送数据寄存器是否为空
        while (!SCI1S1_TDRE);
        //将要发送的字节写到SCI1数据寄存器
        SCI1D = cData;
        //等待发送完成
        while (!SCI1S1_TC);
    }
    //2.2 从SCI2发送1字节数据
    else if (cPort == 2)
    {
        //判断SCI2发送数据寄存器是否为空
        while (!SCI2S1_TDRE);
        //将要发送的字节写到SCI2数据寄存器
        SCI2D = cData;
        //等待发送完成
        while (!SCI2S1_TC);
    } 
}

//**************************************************************************
//函数名称：SCISendN 
//函数功能：从指定SCI端口发送数组中的nNum个字节数据
//入口参数：cPort-SCI模块号(1或者2),如果带入1和2以外的参数,均默认为1
//          nNum-要发送数组的字节数
//          pData-要发送数组的首地址
//出口参数：无
//备    注：本函数调用了SCISend1函数
//**************************************************************************
void SCISendN(UINT8 cPort, UINT16 nNum, UINT8 *pData)
{
    UINT16 i;
    UINT8 *pIndex = pData;
    
    if (pData != NULL)
    {
        //发送数组中的数据
        for (i=0; i<nNum; i++)
        {
            SCISend1(cPort, *pIndex++);
        }
    }
}

//**************************************************************************
//函数名称：SCIRe1 
//函数功能：从指定SCI端口接收1字节数据
//入口参数：cPort-SCI模块号(1或者2),如果带入1和2以外的参数,均默认为1
//          pRecData-存放接收到的1字节数据的指针(接收失败则返回0xFF)
//出口参数：TRUE-成功接收1字节数据; FALSE-未接收到1字节数据
//备    注：
//**************************************************************************
UINT8 SCIRe1(UINT8 cPort ,UINT8 *pRecData)
{  
    UINT16 i;

    i=0;
    
    //1. 参数有效性检查
    //1.1 SCI端口号检查
    if (cPort > 2)
    {
        cPort = 1;
    }
    //1.2 存放接收到的1字节数据的指针有效性检查
    if (pRecData == NULL)
    {
        return FALSE;
    }
    //2. 在指定的时间内接收1字节数据,超时则返回错误标志
    //2.1 从SCI1接收1字节数据
    if (cPort == 1)
    {
        do
        {
            //接收成功
            if (SCI1S1_RDRF)
            {
                *pRecData = SCI1D;
                return TRUE;
            }
            i++;
        }while(i<0xFBBB);
    }
    //2.2 从SCI2接收1字节数据
    else if (cPort == 2)
    {
        do
        {
            //接收成功
            if (SCI2S1_RDRF)
            {
                *pRecData = SCI2D;
                return TRUE;
            }
            i++;
        }while(i<0xFBBB);
    }
    
    //接收失败
    *pRecData = 0xFF;
    return FALSE;
}

//**************************************************************************
//函数名称：SCIReN 
//函数功能：从指定SCI端口接收nNum个字节数据,并存放在pData为首地址的数组中
//入口参数：cPort-SCI模块号(1或者2),如果带入1和2以外的参数,均默认为1
//          nNum-要接收的数据字节数(0到65535)
//          pData-存放接收数据的数组首地址
//出口参数：TRUE-接收数据成功; FALSE-接收数据失败
//备    注：本函数调用了SCIRe1函数
//**************************************************************************
UINT8 SCIReN(UINT8 cPort, UINT16 nNum, UINT8 *pData)
{
    UINT16 i;
    UINT8 *pIndex = pData;
    
    i = 0;
    
    //接收nNum个字节数据
    while (i < nNum)
    {
        if (!SCIRe1(cPort, pIndex++))
        {
            return FALSE;    //只要有1个字节未接收成功就返回报错
        }
        i++;
    }
}

//**************************************************************************
//函数名称：SCITransmitStr 
//函数功能：从指定SCI端口发送一个以'\0'结束的字符串
//入口参数：cPort-SCI模块号(1或者2),如果带入1和2以外的参数,均默认为1
//          pStr-要发送的字符串的首地址
//出口参数：无
//备    注：字符串的长度范围从0到65535,内部调用了SCISendN函数
//**************************************************************************
void SCISendStr(UINT8 cPort, UINT8 *pStr)
{
    UINT16 nStrLen;
    
    //1. 取得要发送的字符串的长度
    nStrLen=strlen(pStr);
    //2. 从指定SCI端口发送字符串数据
    SCISendN(cPort, nStrLen, pStr);
    SCISend1(cPort,0x0D);SCISend1(cPort,0x0A);
}

void SCISendLine(UINT8 cPort, UINT16 nNum, UINT8 *pData)
{
    SCISendN(cPort,nNum,pData);
    SCISend1(cPort,0x0D);SCISend1(cPort,0x0A);
}



