예제 #1
0
파일: spibus.c 프로젝트: Mars-Wu/djyos
// =============================================================================
// 功能:读发送缓冲区数据,由总线驱动调用,总线驱动读取到数据后将数据写入寄存器发送,
//       若阻塞发送,则直接读发送缓冲区指向的数据,若非阻塞发送,则需判断是否剩余数据
//       已达到缓冲区边界,若已到达缓冲区边界,则填写缓冲区,并释放阻塞信号量
// 参数:SPI,SPI控制块指针
//       buf,读数据缓冲区指针
//       len,读数据长度,字节单位
// 返回:字节数
// =============================================================================
s32 SPI_PortRead( struct tagSPI_CB *SPI,u8 *buf,u32 len)
{
    u32 Result = 0,RingLen,CpyLen = 0;
    u8 *pbuf;

    if((len > 0) && (SPI->Frame.SendLen > 0))
    {
        CpyLen = SPI->Frame.SendLen >= len ?len:SPI->Frame.SendLen;
        RingLen = SPI->SPI_Buf.MaxLen;

        if(SPI->BlockOption == true)                //阻塞发送直接读缓冲区
        {
            memcpy(buf,SPI->Frame.SendBuf,CpyLen);
            SPI->Frame.SendBuf += CpyLen;
        }
        else                                        //非阻塞发送,则需区别读取
        {
            //判断是否从缓冲区中读数据
            if(SPI->Frame.SendLen <= RingLen)       //从缓冲区中读数据
            {
                pbuf = &SPI->SPI_Buf.pBuf[SPI->SPI_Buf.Offset];
                SPI->SPI_Buf.Offset += CpyLen;
                memcpy(buf,pbuf,CpyLen);
            }
            else                                    //从pbuf中读数据
            {
                memcpy(buf,SPI->Frame.SendBuf,CpyLen);
                SPI->Frame.SendBuf += CpyLen;

                //将pbuf剩余数据写入缓冲,并释放阻塞信号量
                if(SPI->Frame.SendLen - CpyLen <= RingLen)
                {
                    memcpy(SPI->SPI_Buf.pBuf,SPI->Frame.SendBuf,
                            SPI->Frame.SendLen-CpyLen);
                    Lock_SempPost(SPI->SPI_BlockSemp);
                }
            }
        }
    }

    //只有发送接收都完成的时候才能拉高片选
    if(SPI->Frame.SendLen + SPI->Frame.RecvLen == 0)
    {
        if(SPI->BlockOption == true)
        {
            Lock_SempPost(SPI->SPI_BlockSemp);      //阻塞发送时,释放阻塞信号量
        }

        if(SPI->CurrentDev->AutoCs == true)
        {
            __SPI_AutoCsInactive(SPI,SPI->CurrentDev->Cs);
        }
    }

    SPI->Frame.SendLen -= CpyLen;
    Result = CpyLen;

    return Result;
}
예제 #2
0
파일: dm9000a.c 프로젝트: Mars-Wu/djyos
bool_t debug_dm9000a_write_reg(char *param)
{
    char *word, *next_param;
    u32 reg = 0;
    u32 value = 0;

    // 提取为SOCKET号
    if (param)
    {
        next_param = param;
        word = Sh_GetWord(next_param, &next_param);
        reg = __sh_atol(word);
        word = Sh_GetWord(next_param, &next_param);
        value = __sh_atol(word);
        word = Sh_GetWord(next_param, &next_param);
        if(word != NULL)
        {
            printf("\r\n参数错误\r\n");
            return false;
        }
    }

    if (Lock_SempPend(semp_dm9000, 10000*mS) == true)
    {
        Int_SaveAsynLine(cn_int_line_enet); // 关闭DM9000A的外部中断
        printf("\r\n写入DM9000A的【%4x】寄存器:%4x", reg, value);
        iow(reg, value);

        printf("\r\n");

        Int_RestoreAsynLine(cn_int_line_enet);  // 打开DM9000A的外部中断
        Lock_SempPost(semp_dm9000);
    }
    return true;
}
예제 #3
0
파일: spibus.c 프로젝트: Mars-Wu/djyos
// =============================================================================
// 功能:将接收到的数据写入用户提供的缓冲区中,接收是阻塞方式,因此使用用户的缓冲区
// 参数:SPI,SPI控制块指针
//       buf,数据指针
//       len,数据长度,字节单位
// 返回:字节数
// =============================================================================
s32 SPI_PortWrite(struct tagSPI_CB *SPI,u8 *buf,u32 len)
{
    u32 cpylen;
    if((len > 0) && (SPI->Frame.RecvLen > 0))
    {
        cpylen = SPI->Frame.RecvLen >= len ?len:SPI->Frame.RecvLen;
        memcpy(SPI->Frame.RecvBuf,buf,cpylen);
        SPI->Frame.RecvBuf += cpylen;
        SPI->Frame.RecvLen -= cpylen;
    }

    //只有发送接收都完成的时候才能拉高片选
    if(SPI->Frame.SendLen + SPI->Frame.RecvLen == 0)
    {
        if(SPI->BlockOption == true)
        {
            Lock_SempPost(SPI->SPI_BlockSemp);      //阻塞发送时,释放阻塞信号量
        }
        if(SPI->CurrentDev->AutoCs == true)
        {
            __SPI_AutoCsInactive(SPI,SPI->CurrentDev->Cs);
        }
    }

    return cpylen;
}
예제 #4
0
파일: cpu_peri_rtc.c 프로젝트: djyos/djyos
// =============================================================================
// 功能:设置RTC设备RTC时间,单位微秒,该时间从1970年1月1日0:0:0到现在的时间差
// 参数:time, 时间值
// 返回:true,正常操作,否则出错
// =============================================================================
bool_t Rtc_SetTime(s64 time)
{
    atom_low_t  atom_bak;
    atom_bak = Int_LowAtomStart();
    UpdateTime = time;
    Int_LowAtomEnd(atom_bak);

    Lock_SempPost(pRtcSemp);
    return true;
}
예제 #5
0
파일: multiplex.c 프로젝트: Mars-Wu/djyos
//----Multiplex执行------------------------------------------------------------
//功能:当MultiplexSets中的对象状态发生变化,由相关模块调用本函数告知Multiplex
//      模块。
//参数: ObjectHead,被操作的Object队列头指针
//      Status,Object的当前状态
//返回: true=成功,false=失败。
//-----------------------------------------------------------------------------
bool_t Multiplex_Set(struct tagMultiplexObjectCB *ObjectHead, u32 Status)
{
    struct tagMultiplexObjectCB *Object;
    struct tagMultiplexSetsCB *Sets;
    u32 Sensing, Type;
    u32 OldPend;
    if (ObjectHead == NULL)
        return false;
    Lock_MutexPend(&MultiplexMutex, CN_TIMEOUT_FOREVER);
    Object = ObjectHead;
    while (Object != NULL) {
        OldPend = Object->PendingBit;
        Sets = Object->MySets;
        Sensing = Object->SensingBit & ~0x80000000;
        Type = Object->SensingBit & 0x80000000;
        Object->PendingBit = Status & Sensing;          //更新PendingBit
        if (__ObjectIsActived(OldPend, Sensing, Type)) {    //调用前,Object已触发
            if (!__ObjectIsActived(Object->PendingBit, Sensing, Type)) {
                //调用Multiplex_Set导致对象变成未触发
                //把Object从Sets->ActiveQ队列拿出,放到ObjectQ队列中
                __ChangeList(&(Sets->ActiveQ), &(Sets->ObjectQ), Object);
                if (Sets->Actived != 0)
                    Sets->Actived--;
                if (Sets->Actived == 0)
                    Sets->SetsActived = false;
            }
        } else {                                            //调用前,Object未触发
            if (__ObjectIsActived(Object->PendingBit, Sensing, Type)) {
                //调用Multiplex_Set导致对象被触发

                //把Object从Sets->ObjectQ队列拿出,放到ActiveQ队列中
                __ChangeList(&(Sets->ObjectQ), &(Sets->ActiveQ), Object);
                if (Sets->Actived < Sets->ObjectSum)
                    Sets->Actived++;
                //异步触发模式,须释放信号量
                if ((Sets->Actived >= Sets->ActiveLevel)
                    || (Sets->Actived >= Sets->ObjectSum)) {
                    if (false == Sets->SetsActived) {
                        Sets->SetsActived = true;
                        Lock_SempPost(&Sets->Lock);
                    }
                }
            }
        }
        Object = Object->NextSets;
    }
    Lock_MutexPost(&MultiplexMutex);
    return true;
}
예제 #6
0
파일: spibus.c 프로젝트: Mars-Wu/djyos
// =============================================================================
// 功能:片选拉高,若传输为阻塞方式,则由该函数释放总线信号量和拉高片选,否则,拉高总
//       线和释放信号量由底层驱动完成。因为非阻塞方式时,运行到该函数时,传输未必完成
// 参数:Dev,器件指针
//       block_option,阻塞选项,为true时,表明最后一次传输为阻塞方式,否则为非阻塞
// 返回:true,成功;false,失败
// =============================================================================
bool_t SPI_CsInactive(struct tagSPI_Device *Dev)
{
    struct tagSPI_CB *SPI;
    if(NULL == Dev)
        return false;

    SPI = (struct tagSPI_CB *)Rsc_GetParent(&Dev->DevNode);
    if(NULL == SPI)
        return false;

    if(Dev->AutoCs == false)                        //自动片选时,手动调用无效
    {
        Lock_SempPost(SPI->SPI_BusSemp);
        SPI->pCsInActive(SPI->SpecificFlag,Dev->Cs);
    }
    else
    {
        ;
    }

    return true;
}
예제 #7
0
파일: multiplex.c 프로젝트: Mars-Wu/djyos
//----添加对象到MultiplexSets--------------------------------------------------
//功能: MultiplexSets中添加一个对象。如果该Object的初始状态是已经触发,则加入到
//      ActiveQ队列,否则加入ObjectQ队列。
//参数: Sets,被操作的MultiplexSets指针
//      ObjectHead,被操作的Object队列头指针的指针,*ObjectHead=NULL表示该对象尚
//          未加入任何MultiplexSets,因此,*ObjectHead初始化值应该是NULL。Object
//          允许加入多个MultiplexSets,每加入一个MultiplexSets,将增加一个
//          struct tagMultiplexObjectCB *类型的结点,所有结点的NextSets指针连接
//          成一个单向链表,*ObjectHead指向该链表头。*ObjectHead再也不允许在外部
//          修改,否则结果不可预料。
//      ObjectStatus,加入时的状态,31bit的位元组,bit31无效
//      ObjectID,被Multiplex的对象的ID。
//      SensingBit,对象敏感位标志,31个bit,设为1表示本对象对这个bit标志敏感
//          bit31表示敏感类型,CN_SENSINGBIT_AND,或者CN_SENSINGBIT_OR
//返回: true=成功,false=失败。
//-----------------------------------------------------------------------------
bool_t Multiplex_AddObject(struct tagMultiplexSetsCB *Sets,
    struct tagMultiplexObjectCB **ObjectHead,
    u32 ObjectStatus, ptu32_t ObjectID, u32 SensingBit)
{
    struct tagMultiplexObjectCB *temp;
    struct tagMultiplexObjectCB **TargetQ;
    bool_t repeat = false;
    u32 ActivedInc = 0;
    if (Sets == NULL)
        return false;
    ObjectStatus &= ~0x80000000;
    //下面检查新加入的Object是否已经触发,以决定加入到MultiplexSets的哪个队列中
    if (__ObjectIsActived(ObjectStatus,
            SensingBit & ~0x80000000,
            SensingBit & 0x80000000)) {
        TargetQ = &Sets->ActiveQ;
        ActivedInc = 1;
    } else
        TargetQ = &Sets->ObjectQ;
    Lock_MutexPend(&MultiplexMutex, CN_TIMEOUT_FOREVER);
    temp = *ObjectHead;
    //循环检查一个Object是否重复加入同一个MultiplexSets
    //如果ObjectHead=NULL,检查结果是不重复,后续处理能够正确运行。
    while (temp != NULL) {
        if (temp->MySets != Sets)
            temp = temp->NextSets;
        else {
            repeat = true;
            break;
        }
    }
    Lock_MutexPost(&MultiplexMutex);

    if (repeat == false) {
        temp = Mb_Malloc(g_ptMultiplexObjectPool, CN_TIMEOUT_FOREVER);
        if (temp != NULL) {
            Sets->ObjectSum++;
            temp->SensingBit = SensingBit;
            temp->PendingBit = ObjectStatus;
            temp->ObjectID = ObjectID;
            Lock_MutexPend(&MultiplexMutex, CN_TIMEOUT_FOREVER);
            temp->MySets = Sets;            //设定对象所属MultiplexSets
                                            //同一个MultiplexSets包含多个对象,NextObject把这些对象链接起来。
            if (*TargetQ == NULL) {
                *TargetQ = temp;
                temp->NextObject = temp;
                temp->PreObject = temp;
            } else {
                //新加入MultiplexSets的对象插入队列头部
                temp->PreObject = (*TargetQ)->PreObject;
                temp->NextObject = *TargetQ;
                (*TargetQ)->PreObject->NextObject = temp;
                (*TargetQ)->PreObject = temp;

                (*TargetQ) = temp;
            }
            //同一个对象被多个MultiplexSets包含,用NextSets链接。
            //NextSets是单向链表,新对象插入链表头部
            temp->NextSets = *ObjectHead;
            *ObjectHead = temp;
            Lock_MutexPost(&MultiplexMutex);
            if (ActivedInc == 1) {
                Sets->Actived += ActivedInc;
                if ((Sets->Actived >= Sets->ActiveLevel)
                    || (Sets->Actived >= Sets->ObjectSum)) {
                    if (false == Sets->SetsActived) {
                        Sets->SetsActived = true;
                        Lock_SempPost(&Sets->Lock);
                    }
                }
            }
        } else
            return false;
    } else {
        //重复加入,无须做任何处理
    }
    return true;
}
예제 #8
0
파일: dm9000a.c 프로젝트: Mars-Wu/djyos
//----从DM9000A中读出所有数据----------------------------------------------------
//功能:把DM9000A中的所有数据都读取出来,这些数据包会组织在lst链表中。
//参数:lst,数据包的接收链表头指针
//返回:数据包的接收链表头指针(可能与输入的lst不同)
//-----------------------------------------------------------------------------
struct enet_rcv_packet *__hw_read_in(struct enet_rcv_packet *lst)
{
    u32 tmp;
    u32 len;
    u32 totlen = 0;
    static u32 times = 0;
    struct enet_rcv_packet *nlst = NULL;

    // 请求DM9000A硬件操作的信号量,等待5S秒如果没有发出去,则返回
    if (Lock_SempPend(semp_dm9000, 0) == true)
    {
        // 接收过程中如果有中断发生,中断响应函数读 写DM9000的其他寄存器会打断接收过程。
        Int_SaveAsynLine(cn_int_line_enet); // 关闭DM9000A的外部中断
        ior(DM9000A_MRCMDX);    // dummy read
        tmp = (u8)DATAR16();
        if (tmp == 0x01)    // 第一个字节读出为01h
        {
            switch (ehi.io)
            {
            case ENUM_DM9000A_IO_16BIT: // 16-bit
                while (tmp == 0x01)
                {
                    len = dump_data16(lst, &nlst);
                    if (len == -1)
                    {
                        dm9000a_reset_to_new();
                        totlen = 0;
                    }
                    else
                    {
                        totlen += len;
                        // 试读下一帧数据,若为01h则继续读数,若为0则表示没有有效数据
                        ADDRW8(DM9000A_MRCMDX);
                        tmp = (u8)DATAR16();
                        lst = nlst;
                    }
                }
                __hw_ctrl(enum_enet_hw_ctrl_clear_rx_int);  // 清除接收中断
                break;
            case ENUM_DM9000A_IO_32BIT: // 32-bit
                break;
            case ENUM_DM9000A_IO_8BIT:  // 8-bit
                break;
            default:
                break;
            }
        }
        else if (tmp != 0)
        {
            times++;
            if (times > 5)
            {
                debug_dm9000a_read_reg(NULL);
            }
            dm9000a_reset_to_new();
            totlen = 0;
            if (times > 5)
            {
                debug_dm9000a_read_reg(NULL);
                times = 0;
            }
        }

        Int_RestoreAsynLine(cn_int_line_enet);  // 打开DM9000A的外部中断
        Lock_SempPost(semp_dm9000);
    }

    return nlst;
}
예제 #9
0
파일: dm9000a.c 프로젝트: Mars-Wu/djyos
bool_t debug_dm9000a_read_reg(char *param)
{
    char *word, *next_param;
    int i;
    u32 reg = 0xFFFF;

    // 提取为SOCKET号
    if (param)
    {
        next_param = param;
        word = Sh_GetWord(next_param, &next_param);
        reg = __sh_atol(word);
        word = Sh_GetWord(next_param, &next_param);
        if(word != NULL)
        {
            printf("\r\n参数错误\r\n");
            return false;
        }
    }

    if (Lock_SempPend(semp_dm9000, 10000*mS) == true)
    {
        Int_SaveAsynLine(cn_int_line_enet); // 关闭DM9000A的外部中断
        if (reg != 0xFFFF)
        {
            printf("\r\n读取DM9000A的【%4x】寄存器:", reg);
            printf("\r\n %4x:%4x", reg, ior(reg));
        }
        else
        {
            printf("\r\n读取DM9000A的【所有】寄存器:");
            printf("\r\n");
            for (i=0; i<=0x1f; i++)
            {
                printf("\r\n %4x:%4x", i, ior(i));
            }
            printf("\r\n");
            for (i=0x22; i<=0x25; i++)
            {
                printf("\r\n %4x:%4x", i, ior(i));
            }
            printf("\r\n");
            for (i=0x28; i<=0x34; i++)
            {
                printf("\r\n %4x:%4x", i, ior(i));
            }

            printf("\r\n");
            i = 0x38;
            printf("\r\n %4x:%4x", i, ior(i));
            i = 0x39;
            printf("\r\n %4x:%4x", i, ior(i));

            printf("\r\n");
            i = 0x50;
            printf("\r\n %4x:%4x", i, ior(i));
            i = 0x51;
            printf("\r\n %4x:%4x", i, ior(i));

            printf("\r\n");
            i = 0xF0;
            printf("\r\n %4x:%4x", i, ior(i));
            i = 0xF1;
            printf("\r\n %4x:%4x", i, ior(i));
            i = 0xF2;
            printf("\r\n %4x:%4x", i, ior(i));
            i = 0xF4;
            printf("\r\n %4x:%4x", i, ior(i));
            i = 0xF5;
            printf("\r\n %4x:%4x", i, ior(i));
            i = 0xF6;
            printf("\r\n %4x:%4x", i, ior(i));
            i = 0xF8;
            printf("\r\n %4x:%4x", i, ior(i));

            printf("\r\n");
            for (i=0xFA; i<=0xFF; i++)
            {
                printf("\r\n %4x:%4x", i, ior(i));
            }
        }

        printf("\r\n");

        Int_RestoreAsynLine(cn_int_line_enet);  // 打开DM9000A的外部中断
        Lock_SempPost(semp_dm9000);
    }
    return true;
}
예제 #10
0
// =============================================================================
// 功能:IIC接收与发送中断服务函数。该函数实现的功能如下:
//       1.每发送与接收一个或若干字节发生一次中断;
//       2.若有多个中断使用同一个中断号,则需根据具体情况区分使用的是哪个中断;
//       3.清中断标志,并判断ACK信号,每读写字节,计数器都需相应修改;
//       4.接收达到倒数第一个字节时,需配置不发送ACK信号;
//       5.接收或发送完成时,需post信号量IntParam->pDrvPostSemp;
//       6.接收或发送完成时,需产生停止时序。
// 参数:i2c_int_line,中断号,本函数没用到
// 返回:无意义
// =============================================================================
static u32 __IIC_ISR(ufast_t i2c_int_line)
{

    static struct tagIIC_IntParamSet *IntParam;
    static struct tagIIC_CB *ICB;
    tagI2CReg *reg;
    u8 ch;
    u32 IicErrorNo;
    u32 irptl_temp=*rTWIIRPTL;//read IRPTL

    reg = (tagI2CReg*)CN_IIC_REGISTER_BADDR0;
    ICB=&s_IIC0_CB;
    IntParam=&IntParamset0;

        //MASTER TX\RX COMPLETE
        if( (irptl_temp & TWITXINT) != 0 )      //发送中断
        {
            if(!(CHKBIT(reg->rTWIMSTAT, TWIANAK)|CHKBIT(reg->rTWIMSTAT, TWIDNAK)))
            {
                //从泛设备读一个字节的数据,并发送
                if(IIC_PortRead(ICB,&ch,1) > 0)
                {
                    *rTXTWI8 = ch;
                    IntParam->TransCount++;
                }
                else if(IntParam->TransCount == IntParam->TransTotalLen)
                {
                    //in Master TX Mode , we need to STOP TWI by ourself
                    Lock_SempPost(IntParam->pDrvPostSemp);
                     __IIC_GenerateStop(reg);
                }
                else
                {
                 IicErrorNo = CN_IIC_NO_ACK_ERR;//调用错处处理API函数
                 IIC_ErrPop(ICB,IicErrorNo);
                }
            }
            else    //TX no ACK
            {
                IicErrorNo = CN_IIC_NO_ACK_ERR;//调用错处处理API函数
                IIC_ErrPop(ICB,IicErrorNo);
                return 1;
            }
            //clear IIC interrupt
            irptl_temp = TWITXINT;
            *rTWIIRPTL = irptl_temp;
        }
        else if( (irptl_temp & TWIRXINT) != 0 )      //接收中断
        {
            if(!(CHKBIT(reg->rTWIMSTAT, TWIANAK)|CHKBIT(reg->rTWIMSTAT, TWIDNAK)))
            {
                ch = *rRXTWI8;
                IIC_PortWrite(ICB,&ch,1);
                IntParam->TransCount ++;
                if(IntParam->TransCount == IntParam->TransTotalLen)
                {
                    __IIC_GenerateStop(reg);
                    Lock_SempPost(IntParam->pDrvPostSemp);//释放总线信号量
                }
            }

            else    //RX no ACK
            {

            }
            //clear IIC interrupt
            irptl_temp = TWIRXINT;
            *rTWIIRPTL = irptl_temp;
        }
        else    //TWIMERR
        {
        }

    irptl_temp==*rTWIIRPTL; //update TWI_IRPTL

        //MASTER TRANS COMPLETE
        if( (irptl_temp & TWIMCOM) != 0 )
        {
            _IIC_GenerateDisable(reg);

            Lock_SempPost(ICB->iic_bus_semp);//释放总线信号量

            //clear STOP
            CLRBIT(reg->rTWIMCTL, TWISTOP);
            //clear IIC interrupt
            irptl_temp |= TWIMCOM;
            *rTWIIRPTL = irptl_temp;
        }

    return 0;
}
예제 #11
0
파일: spibus.c 프로젝트: Mars-Wu/djyos
bool_t __SPI_AutoCsInactive(struct tagSPI_CB *SPI,u8 CS)
{
    Lock_SempPost(SPI->SPI_BusSemp);
    SPI->pCsInActive(SPI->SpecificFlag,CS);
    return true;
}
예제 #12
0
파일: cpu_peri_iic.c 프로젝트: djyos/djyos
// =============================================================================
// 功能:        IIC接收与发送中断服务函数。该函数实现的功能如下:
//       1.每发送与接收一个或若干字节发生一次中断;
//       2.若有多个中断使用同一个中断号,则需根据具体情况区分使用的是哪个中断;
//       3.清中断标志,并判断ACK信号,每读写字节,计数器都需相应修改;
//       4.接收达到倒数第一个字节时,需配置不发送ACK信号;
//       5.接收或发送完成时,需post信号量IntParam->pDrvPostSemp;
//       6.接收或发送完成时,需产生停止时序。
// 参数:i2c_int_line,中断号,本函数没用到
// 返回:true falst
// =============================================================================
static u32 __IIC_ISR(ufast_t i2c_int_line)
{
    static struct IIC_CB *ICB;
    static struct IIC_IntParamSet *IntParam;
    tagI2CReg *reg;
    u8 ch;
    u32 IicErrorNo;
    switch (i2c_int_line)
    {
        case CN_INT_LINE_I2C1_EV:
                reg = (tagI2CReg*)CN_IIC1_BASE;
                ICB = &s_IIC1_CB;
                IntParam = &IntParamset0;
                break;
        case CN_INT_LINE_I2C2_EV:
                reg = (tagI2CReg*)CN_IIC2_BASE;
                ICB = &s_IIC2_CB;
                IntParam = &IntParamset1;
                break;
        default:
                return false;
    }

    if(reg->SR1 & I2C_SR1_BTF_MASK)        //已经启动传输
    {
        if(reg->SR1 & I2C_SR1_TxE_MASK)      //发送中断
        {
            if(!(reg->SR1 & I2C_SR1_RxNE_MASK))
            {
                //从发送缓冲区读一个字节的数据,并发送
                if(IIC_PortRead(ICB,&ch,1) > 0)
                {
                    reg->DR = ch;
                    IntParam->TransCount ++;;
                }
                else if(IntParam->TransCount == IntParam->TransTotalLen)
                {
                  Lock_SempPost(IntParam->pDrvPostSemp);
                  __IIC_IntDisable(reg);//关中断
                  __IIC_GenerateStop(reg);
                }
            }
            else                        //未收到ACK信号
            {
                IicErrorNo = CN_IIC_POP_NO_ACK_ERR;//调用错处处理API函数
                IIC_ErrPop(ICB,IicErrorNo);
                return 1;
            }
        }
        else                            //接收中断
        {
            while((IntParam->TransCount < IntParam->TransTotalLen))
            {
                // 最后一个字节master不发ACK,表示读操作终止
                if(IntParam->TransCount == IntParam->TransTotalLen - 1)
                {
                    reg->CR1 &=~ I2C_CR1_ACK_MASK;
                }
                while (!(reg->SR1 & I2C_SR1_RxNE_MASK));//等待接收完成
                    ch = reg->DR;
                //写数据
                IIC_PortWrite(ICB,&ch,1);
                IntParam->TransCount ++;
            }
            if((IntParam->TransCount == IntParam->TransTotalLen)  &&
                                        (reg->SR1 & I2C_SR1_BTF_MASK))
            {
                __IIC_GenerateStop(reg);
                __IIC_IntDisable(reg);//关中断
                Lock_SempPost(IntParam->pDrvPostSemp);//释放总线信号量
            }
        }
    }
    else//未启动通信
    {
        if(reg->SR1 & I2C_SR1_ARLO_MASK)//仲裁丢失中断
        {
            reg->SR1 &= ~I2C_SR1_ARLO_MASK;//清除仲裁丢失中断标志位
            IicErrorNo = CN_IIC_POP_MAL_LOST_ERR;
            IIC_ErrPop(ICB,IicErrorNo);
        }
    }

    return true;
}