comm.c

来自「这是一个AVR单片机的串行通讯模块 大家可以合理的用到自己的实验中」· C语言 代码 · 共 429 行 · 第 1/2 页

C
429
字号
*         2> COMM_TXD_OK   发送数据进入缓存OK
* 说 明 : 无
********************************************************************************************************/
#if    COMM1_UNIT_EN > 0 && COMM1_TXD_EN > 0
INT8U Comm1TxInBuf (INT8U Data)
{
    INT8U  err;
    
    err = COMM_TXD_FLOOD;                     // 设置发送缓存为满
    
    COMM_ENTER_CRITICAL();                    // 进入临界
    if (!bComm1CanSend) {                     // 判断串口直接发送允许标志位 0为允许
        bComm1CanSend = 1;                    // 设置为忙
        UDR           = Data;                 // 发送出数据
#if COMM_DATAFREE_ISR_EN > 0
        SETBIT(UCSRB,BIT(UDRIE));             // 数据发送开始,置数据寄存器中断使能位
#endif
        COMM_EXIT_CRITICAL();                 // 退出临界
        return (COMM_TXD_OK);                 // 返回代码为发送OK
    }
    
    if (Comm1TxBufCtr < COMM1_TXD_SIZE) {     // 处理发送缓存计数器
        err = COMM_TXD_OK;                    // 设置发送缓存为正常
        Comm1TxBufCtr++;                      // 发送缓存计数器加1
        Comm1TxBuf[Comm1TxInIx++] = Data;     // 来不及发送的数据进发送缓存
        if (Comm1TxInIx >= COMM1_TXD_SIZE) {  // 处理发送进缓存计数器
            Comm1TxInIx  = 0;                 // 复位发送进缓存计数器
        }
    }    
    COMM_EXIT_CRITICAL();                     // 退出临界 开始准备发送多字符
    return (err);
}
#endif

/********************************************************************************************************
* 功 能 : COMM1 发送1 BYTE数据
* 入 口 : 'Date' 发送的数据
* 返 回 : 1> COMM_TXD_OK    发送数据OK
*         2> COMM_TXD_FALSE 发送失败   一般是发送缓存已满
* 说 明 : 1> UDR发送寄存器为空时直接把要发送的数据放到发送缓存
*         2> UDR发送寄存器为忙时来不及发的数据进入到发送缓存
*         3> 发送缓存满时直接返回发送失败
********************************************************************************************************/

/*
INT8U Comm1TxPutChar (INT8U Data)
{
    COMM_ENTER_CRITICAL();                    // 进入临界
    if (!bComm1CanSend) {                     // 判断串口直接发送允许标志位 0为允许
        bComm1CanSend = 1;                    // 设置为忙
        UDR           = Data;                 // 发送出数据
        COMM_EXIT_CRITICAL();                 // 退出临界
        return (COMM_TXD_OK);                 // 返回代码为发送OK
    }

    if (Comm1TxBufCtr >= COMM1_TXD_SIZE) {    // 判断发送缓存计数器是否为最大发送缓存
        COMM_EXIT_CRITICAL();                 // 是退出临界 不处理
        return (COMM_TXD_FALSE);              // 发送缓存满 返回代码为发送失败
    } else {
        Comm1TxInBuf(Data);                   // 来不及发送的数据一直等到进入发送缓存
        COMM_EXIT_CRITICAL();                 // 退出临界
        return (COMM_TXD_OK);                 // 返回代码为发送OK
    }
} 
*/
    
/********************************************************************************************************
* 功 能 : COMM1 发送N BYTE数据
* 入 口 : 'p'   指向发送消息的指针
*         'len' 发送数据的长度
* 返 回 : 返回实际发送的数据长度
* 说 明 : 1> 如果是发送失败 则直接返回 这样在多任务里面就可以延时N个周期再尝试重发数据 这样就不会在这里
*            多等更多的时间  但这种情况不是绝对的 根据波特率是有很大的关系 
*         2> 建议发送时的缓存最好保证>=即将发送的数据长度 数据流之间能留一定的时间间隔保证发送数据
*         3> 发送的数据长度大于实际能缓存的长度时 波特率是影响其工作效率的主要因素 MCU中的RAM一般比较小
********************************************************************************************************/

INT8U Comm1TxPutsChar (INT8U *s, INT8U len)
{   
    INT8U i;
    
    //COMM_ENTER_CRITICAL();                  // 进入临界
    i = COMM1_TXD_SIZE - Comm1TxBufCtr;       // 实际还有多少可用缓冲区
    //COMM_EXIT_CRITICAL();                   // 退出临界
    if (i > len){                             // 发送数据长度小于可用缓冲区时,
        i = len;                              // 所有数据能全部发送成功
    }else{
        len = i;
    }
    
    while (i--) {                             // 发送数据处理
        Comm1TxInBuf(*s);                     // 发送的数据进入发送缓存
        s++;                                  // 数据指针加1
    }
    
    return (len);                             // 返回实际发送的数据长度
}


/********************************************************************************************************
* 功 能 : 串口1读1则数据
* 入 口 : 'err' 返回错误信息的指针
* 返 回 : 1> 读到的数据
*         2> err=COMM_RXD_EMPTY 接收缓存没有数据
*         3> err=COMM_RXD_OK    正确在接收缓存读到数据
* 说 明 : 1> 在调用此函数前 最好用Comm1RxGetNMsgs函数检查一下接收缓存里面有没有信息
*         2> 如果不按1>的用法用 则要对返回的错误代码分析
********************************************************************************************************/

INT8U  Comm1RxGetChar  (INT8U *Data)
{
    INT8U err = COMM_RXD_EMPTY;               // 返回代码为接收为空
	
    COMM_ENTER_CRITICAL();                    // 进入临界
    if (Comm1RxBufCtr > 0) {                  // 检测接收缓存是否有数据
        Comm1RxBufCtr--;                      // 有数据计数器减1
        *Data = Comm1RxBuf[Comm1RxOutIx++];    // 取出数据
        err   = COMM_RXD_OK;                   // 返回代码为读数据正确
        if (Comm1RxOutIx >= COMM1_RXD_SIZE) { // 检查出数据计数器 是否大于最大接收缓存
            Comm1RxOutIx  = 0;                // 是复位出数据计数器
        } 
    } 
    COMM_EXIT_CRITICAL();                     // 退出临界
    return (err);
}



/********************************************************************************************************
* 功 能 : 检测接收缓存中的数据个数
* 入 口 : 无
* 返 回 : 缓存中的数据个数
* 说 明 : 无
********************************************************************************************************/

INT8U   Comm1RxGetNMsgs (void)
{
    INT8U counter;
    COMM_ENTER_CRITICAL();                    // 进入临界
    counter = Comm1RxBufCtr;                  // 取接收计数器数据
    COMM_EXIT_CRITICAL();                     // 退出临界
    return (counter);                         // 返回接收缓存计数
}



/********************************************************************************************************
* 功 能 : 一次串口1读N则数据
* 入 口 : 'p'   返回数据信息的指针
*         'len' 读的数据长度 < COMM1_RXD_SIZE
* 返 回 : 1> COMM_RXD_EMPTY 读数据为空    一般是len为空 或接收缓存中没有数据
*         2> COMM_RXD_FALSE 错误读数据    一般为len大于数据接收缓存中的数据
*         3> COMM_RXD_OK    数据正确读到
* 说 明 : 1> 对于返回参数2> 可以使用Comm1RxGetNMsgs 先取得缓存中的数据个数再一次读走
********************************************************************************************************/
#if    COMM1_UNIT_EN > 0 && COMM1_RXD_EN > 0 && COMM1_GETS_EN > 0
INT8U  Comm1RxGetsChar (INT8U *s, INT8U len)
{    
    COMM_ENTER_CRITICAL();                    // 进入临界  处理Comm1RxBufCtr
    if ((len == 0) || (Comm1RxBufCtr == 0)) { // 检查数据长度 和接收缓存是否为空
        COMM_EXIT_CRITICAL();                 // 退出临界
        return (COMM_RXD_EMPTY);              // 返回代码为接收空
    } 

    if (len > Comm1RxBufCtr) {                // 检查读数长度跟实际接收缓存数据个数
        COMM_EXIT_CRITICAL();                 // 退出临界 
        return (COMM_RXD_FALSE);              // 返回代码为 读数据失败
    }    
    COMM_EXIT_CRITICAL();                     // 退出临界

                                              // 必须退出临界以便其他的中断响应 否则len大时就会影响中断
    while (len--) {                           // 读走len个数据
        COMM_ENTER_CRITICAL();                // 进入临界 处理Comm1RxBufCtr
        *s++ = Comm1RxBuf[Comm1RxOutIx++];    // 取出数据
        Comm1RxBufCtr--;                      // 接收缓存计数器减1
        if (Comm1RxOutIx >= COMM1_RXD_SIZE) { // 处理接收出数据计数器
            Comm1RxOutIx = 0;                 // 复位出数据计数器
        }
        COMM_EXIT_CRITICAL();                 // 退出临界
    }
    return (COMM_RXD_OK);                     // 返回代码为 接收到正确数据
}
#endif


/********************************************************************************************************
* 功 能 : 初始化串口1的各种变量
* 入 口 : 无
* 返 回 : 无
* 说 明 : 无
********************************************************************************************************/

void   Comm1VarInit (void)
{
#if COMM1_RXD_EN > 0                          // 初始化接收的各种变量
    Comm1RxBufCtr = 0;
    Comm1RxInIx   = 0;
    Comm1RxOutIx  = 0;
#endif

#if COMM1_TXD_EN > 0                          // 初始化发送的各种变量
    Comm1TxBufCtr = 0;
    Comm1TxInIx   = 0;
    Comm1TxOutIx  = 0;
    bComm1CanSend = 0;                        // 串口0寄存器发送忙标志
#endif
}


#endif 
/********************************************************************************************************
*                                             End Of File
********************************************************************************************************/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?