一个相当经典的AVR中断程序

一个不错的avr的串口通讯代码,收藏于此,以备后用。

在此谢谢原创者。

 

[code]
/**************************************************************************************************
* 文 件 名 : Comm.H
* 说    明 :
*            1> 这一版本中最大的接收和发送缓存为255为INT8U类型的最大值
**************************************************************************************************/

 

#ifdef  COMM_GLOBALS
#define COMM_EXT
#else
#define COMM_EXT extern
#endif

 

/**************************************************************************************************
* 全局常量
**************************************************************************************************/
#define COMM_MODULE_EN          1            // 串口模块总使能   0禁止


                                              // 当串口的接收需要任务协助处理时下面两个定义有效
//#define TaskComm1Prio           1           // 定义串口0接收任务ID 注意: 在CONFIG.H中统一定义
//#define TaskComm2Prio           2           // 定义串口1接收任务ID
#define COMM1_MEM_SEL                         // 串口0各种控制变量存储区选择    非C51一般为空
#define COMM2_MEM_SEL                         // 串口1各种控制变量存储区选择    非C51一般为空
#define COMM_CONST_SEL                        // 串口数据常量存储区选择        非C51一般为const或static
#define COMM0_VECTOR                          // 串口0中断函数入口编号
#define COMM1_VECTOR                          // 串口1中断函数入口编号
#define X0N                     17            // 流控制字符 继续发送  20%
#define XOFF                    19            // 流控制字符 停止发送  70%

------------串口配置----------
#define COMM_MODE               1             // 通信模式     0异步正常模式 1异步倍速模式 2同步主机模式                                             
#define COMM_MORE_CPU_MODE      0             // 多处理器模式 1为多处理器模式有效 0为无效
#define COMM_ACCEPT_ISR_EN      1             // 接收结束中断          (1)使能   (0)禁止
#define COMM_SEND_ISR_EN        1             // 发送结束中断          (1)使能   (0)禁止
#define COMM_DATAFREE_ISR_EN    1             // 数据寄存器空中断      (1)使能   (0)禁止
#define COMM_SYN_CLOCK          1             // 同步工作模式时钟极性  (1)下降沿 (0)上升沿

 

                                              // 两个处理CLK模块临界数据的两个宏 这里使用OS的临界宏 
#define COMM_ENTER_CRITICAL()   OS_ENTER_CRITICAL() // 进入临界宏  默认COMM_ENTER_CRITICAL() EA=0   
#define COMM_EXIT_CRITICAL()    OS_EXIT_CRITICAL()  //退出临界宏  默认COMM_ENTER_CRITICAL() EA=1
    
                                              // 串口0的常量定义
#define COMM1_UNIT_EN           1             // 串口0模块使能                                  0禁止
  #define COMM1_DATA_STREAM_EN  0             // ASCII方式通讯时可采样XON/XOFF数据流模式来保证数据传输
  #define COMM1_OS_SEL          1             // 选择在RTOS中使用则调用OSIntSendSignal 通知接收任务处理
                                              //  串口数据 则启用定义TaskComm1Prio即接收任务ID   0=禁止
  #define COMM1_OS_SIGNAL_SEL   1             // 0选择发送信号 1选择释放信号量 同时COMM1_OS_SEL要使能 
                                              //   来通知接收任务处理数据                           
  #define COMM1_RXD_EN          1             // 串口0接收部分使能                              0禁止
  #define COMM1_GETNMSGS_EN     0             // 串口0的数据计数检测函数使能                    0禁止
  #define COMM1_GETS_EN         0             // 串口0接收多数据                                0禁止
  #define COMM1_RXD_SIZE        255           // 串口0的接收缓存配置 需要立即读数据 否则弃数据  必须>=1
  #define COMM1_TXD_EN          1             // 串口0发送部分使能                              0禁止
  #define COMM1_PUTS_EN         0             // 串口0发送多数据                                0禁止
  #define COMM1_TXD_SIZE        128           // 串口0的发送缓存配置                            必须>=1
                                                                               

--------------串口的各种返回信息 不能更改------------
#define COMM_ERR                0             // 串口配置有错误 
#define COMM_NO_ERR             1             // 串口配置没有错误
#define COMM_BAD_BAUD           2             // 波特率错误
#define COMM_BAD_MODE           3             // 串口工作为错误的工作方式
#define COMM_RXD_EMPTY          4             // 接收缓存没有数据 为空
#define COMM_RXD_FALSE          5             // 接收数据失败 只多字节接收时返回此信息
#define COMM_RXD_OK             6             // 接收数据正确
#define COMM_TXD_FALSE          7             // 发送失败
#define COMM_TXD_OK             8             // 发送正确
#define COMM_TXD_FLOOD          9             // 发送数据溢出 快速或多字节数据发送时 缓存溢出
           

#if   (COMM_MODE == 0)||(COMM_MODE == 1)         // 异步正常模式串,异步倍速模式串
    #define UMSEL_MODE          0
    #define UCPOL_MODE          0
  #elif COMM_MODE == 2                           // 同步模式串
    #define UMSEL_MODE          BIT(UMSEL)
    #if COMM_SYN_CLOCK == 0                       // 同步工作模式时钟极性
        #define UCPOL_MODE      0
      #else
        #define UCPOL_MODE      BIT(UCPOL)
    #endif
  #else                                          // 选择其他模式 则停止编译
    #error "(COMM_MODE)通信模式设置错误!  "
#endif

#if     COMM_MORE_CPU_MODE  ==  0                // 处理器模式 1为多处理器模式有效 0为无效
    #define MPCM_MODE               0            //
  #elif   COMM_MORE_CPU_MODE  ==  1
    #define MPCM_MODE               BIT(MPCM)
  #else
    #error "请正确配置多处理器模式中断使能信号 (COMM_MORE_CPU_MODE)!"
#endif

#if     COMM_ACCEPT_ISR_EN  ==  0                // 接收结束中断 (1)使能  (0)禁止
    #define RXCIE_MODE              0            //
  #elif   COMM_ACCEPT_ISR_EN  ==  1
    #define RXCIE_MODE              BIT(RXCIE)
  #else
    #error "请正确配置接收结束中断中断使能信号 (COMM_ACCEPT_ISR_EN)!"
#endif

#if     COMM_SEND_ISR_EN  ==  0                  // 发送结束中断 (1)使能  (0)禁止
    #define TXCIE_MODE               0           //
  #elif   COMM_SEND_ISR_EN  ==  1
    #define TXCIE_MODE               BIT(TXCIE)
  #else
    #error "请正确配置发送结束中断中断使能信号 (COMM_SEND_ISR_EN)!"
#endif

#if     COMM_DATAFREE_ISR_EN == 0                // 数据寄存器空中断 (1)使能  (0)禁止
    #define UDRIE_MODE              0            //
  #elif   COMM_DATAFREE_ISR_EN == 1
    #define UDRIE_MODE              BIT(UDRIE)
  #else
    #error "请正确配置数据寄存器空中断使能信号 (COMM_DATAFREE_ISR_EN)!"
#endif

#define none 0
#define even 2
#define odd  3
/********************************************************************************************************
* 全局变量和数据类型
********************************************************************************************************/
#if COMM_MODULE_EN  > 0


#endif

/********************************************************************************************************
* 函数
********************************************************************************************************/
                                              /* COMM1有关接口函数集                                   */
INT8U    Comm1CfgPort     (INT32U baud, INT8U parity, INT8U bits, INT8U stops);
void     Comm1VarInit     (void);            
                                              /* COMM1接收有关函数                                     */
INT8U    Comm1RxGetChar   (INT8U *Data);
INT8U    Comm1RxGetNMsgs  (void);
INT8U    Comm1RxGetsChar  (INT8U *s, INT8U len);

                                              /* COMM1发送有关函数                                     */
INT8U    Comm1TxInBuf  (INT8U Data);           // 数据进入发送缓存    
#define Comm1TxPutChar  Comm1TxInBuf
//INT8U    Comm1TxPutChar   (INT8U Data);
INT8U    Comm1TxPutsChar  (INT8U *s, INT8U len);

/********************************************************************************************************
*                                             End Of File
********************************************************************************************************/

[/code]

[code]
/**************************************************************************************************
* 文 件 名 : Comm.C
* 说    明 : 暂不支持9位数据流
*            1> 这一版本中最大的接收和发送缓存为255为INT8U类型的最大值
****************************************************************************************************/

#define  COMM_GLOBALS
#include "includes.h"

 
#if      COMM_MODULE_EN > 0
    
/**************************************************************************************************
* 局部常数
**************************************************************************************************/
#ifndef MCU_Fosc                              // MCU的晶振频率设置 这是计算波特率必须的参数 
#error "no defien MCU_Fosc       e.g.  #define MCU_Fosc 11059200L"
#endif

/********************************************************************************************************
* 局部变量
********************************************************************************************************/

static INT8U COMM1_MEM_SEL Comm1RxBuf[COMM1_RXD_SIZE];  // 串口1接收分配缓存
static INT8U COMM1_MEM_SEL Comm1RxBufCtr;               // 串口1接收数据个数计数器
static INT8U COMM1_MEM_SEL Comm1RxInIx;                 // 串口1接收数据入缓存位置索引
static INT8U COMM1_MEM_SEL Comm1RxOutIx;                // 串口1接收数据出缓存位置索引

static BOOL                bComm1CanSend;               // 串口1发送忙标志 0=不忙 1=忙
static INT8U COMM1_MEM_SEL Comm1TxBuf[COMM1_TXD_SIZE];  // 串口1发送分配缓存
static INT8U COMM1_MEM_SEL Comm1TxBufCtr;               // 串口1发送数据个数计数器
static INT8U COMM1_MEM_SEL Comm1TxInIx;                 // 串口1发送数据入缓存位置索引
static INT8U COMM1_MEM_SEL Comm1TxOutIx;                // 串口1发送数据出缓存位置索引


/**************************************************************************************************
* 局部函数
**************************************************************************************************/

 

 

/**************************************************************************************************
*                                     COMM1相关函数集
**************************************************************************************************/

#define CR PutString("/r/n")                  //发送一个回车换行
#define NUL putstring("{post.content}")                   //发送一个空格

/**************************************************************************************************
* 功 能 : COMM1 工作状态初始化
* 入 口 : 'baud'   波特率 最大波特率为实际硬件能支持的波特率和数据处理能力设置
*         'parity' 奇偶效验 none(无)  even(偶校验)  odd(奇校验) 
*         'bits'   数据位  为5,6,7,8,9位
*         'stops'  停止位  为1,2位
* 返 回 : 1> COMM_ON_ERR   串口设置没有错误
*         2> COMM_BAD_BUAD 错误的波特率
*         3> COMM_BAD_MODE 错误的工作模式
* 说 明 :
***************************************************************************************************/
#if    (COMM1_UNIT_EN > 0 && COMM1_RXD_EN > 0) || ( COMM1_UNIT_EN > 0 && COMM1_TXD_EN > 0)
INT8U  Comm1CfgPort (INT32U baud, INT8U parity, INT8U bits, INT8U stops)
{
    INT8U UCSRC_TEMP;                            //UBRRH和UCSRC的读写操作很特殊
   
   
    COMM_ENTER_CRITICAL();
#if   COMM_MODE == 0
    UBRRH = (INT8U)((MCU_Fosc/16/(baud+1))>>8);  // 设异步正常模式串口波特率
    UBRRL = (INT8U)((MCU_Fosc/16/(baud+1)));
    UCSRA = MPCM_MODE;                           // 多机模式设定
#elif COMM_MODE == 1
    UBRRH = (INT8U)((MCU_Fosc/8/(baud+1))>>8);   // 设异步倍速模式串口波特率
    UBRRL = (INT8U)((MCU_Fosc/8/(baud+1)));
    UCSRA = BIT(U2X)|MPCM_MODE;                  // 倍速发送和多机模式设定
#elif COMM_MODE == 2
    UBRRH = (INT8U)((MCU_Fosc/2/(baud+1))>>8);   // 设同步模式串口波特率
    UBRRL = (INT8U)((MCU_Fosc/2/(baud+1)));
    UCSRA = MPCM_MODE;                           //
#endif
          // 接收中断,发送中断,数据寄存器空中断,同步时钟极性,发送使能,接收使能设定
    UCSRB =RXCIE_MODE|TXCIE_MODE|UDRIE_MODE|UCPOL_MODE|BIT(RXEN)|BIT(TXEN);
   
    switch (bits) {
        case 5 :
            UCSRC_TEMP = BIT(URSEL)|UMSEL_MODE;
            break;
        case 6:
            UCSRC_TEMP = BIT(URSEL)|UMSEL_MODE|BIT(UCSZ0);
            break;
        case 7:
            UCSRC_TEMP = BIT(URSEL)|UMSEL_MODE|BIT(UCSZ1);
            break;
        case 8 :
            UCSRC_TEMP = BIT(URSEL)|UMSEL_MODE|BIT(UCSZ1)|BIT(UCSZ0);
            break;
        case 9 :
            SETBIT(UCSRB,BIT(UCSZ2));
            UCSRC_TEMP = BIT(URSEL)|UMSEL_MODE|BIT(UCSZ1)|BIT(UCSZ0);
            break;
        default:
            UCSRC_TEMP = BIT(URSEL)|UMSEL_MODE|BIT(UCSZ1)|BIT(UCSZ0);  //默认为8BIT
            break;
    }
   
    if (stops == 2){                                                  // 设停止位
        SETBIT(UCSRC_TEMP,(BIT(URSEL)+BIT(USBS)));
    }

    switch (parity) {
        case none :                                                  // 无校验
            break;
        case 1:                                                      // 系统保留
            break;
        case even:
            SETBIT(UCSRC_TEMP,(BIT(URSEL)+BIT(UPM1)));               // 偶校验
            break;
        case odd :
            SETBIT(UCSRC_TEMP,(BIT(URSEL)+BIT(UPM1)+BIT(UPM0)));     // 奇校验
            break;
        default:                                                     //默认为无校验
            break;
    }
    UCSRC = UCSRC_TEMP;
   
    COMM_EXIT_CRITICAL();
    return (COMM_NO_ERR);
}
#endif


/**************************************************************************************************
* 功 能 : 串口接收中断响应函数
* 入 口 : 无
* 返 回 : 无
* 说 明 : 1> 使用串口中断前 先用Comm1CfgPort 函数配置好波特率 工作模式等信息
*         2> 使用串口中断前 再调用Comm1VarInit 函数初始化各种变量 否则工作可能出错
*         3> 如果使能串口0接收部分则 需要配置接收缓存 此缓存不能太小 发送方的数据根据波特率的关系处
*            理发送速度和MCU的处理速度(串口进缓存24MHz <40us)决定发送速度不能太快 否则后面的数据会
*            抛弃 造成数据的丢失
*         4> 如果使能串口发送部分 需要配置好发送缓存 此发送缓存的大小不做特殊要求 但太小会影响本地
*            的MCU的处理本地事务的能力 (特别是前后模式的程序和波特率低的情况)
*         5> 如果是在OS中使用 可以启用通知函数给串口接收分析任务 分析接收的数据 参考程序中屏蔽的函数
*         6> 中断响应的速度与COMM_MEM_SEL和高优先级中断的响应时间有关 如果接收数据很快可以加 DISABLE命令
**************************************************************************************************/

ISR(SIG_UART_RECV){
    //COMM_ENTER_CRITICAL();                  // 进入临界处理
   
    if (Comm1RxBufCtr < COMM1_RXD_SIZE) {
        Comm1RxBufCtr++;                      // 接收缓存计数器加1
        Comm1RxBuf[Comm1RxInIx++] = UDR;      // 接收到的数据进缓存
        if (Comm1RxInIx >= COMM1_RXD_SIZE) {
            Comm1RxInIx  = 0;
        }
    }       
    //COMM_EXIT_CRITICAL();                   // 退出临界
}

/**************************************************************************************************
* 功 能 : 串口发送完中断响应函数
* 入 口 : 无
* 返 回 : 无
* 说 明 : 1> 使用串口中断前 先用Comm1CfgPort 函数配置好波特率 工作模式等信息
*         2> 使用串口中断前 再调用Comm1VarInit 函数初始化各种变量 否则工作可能出错
*         3> 如果使能串口发送部分 需要配置好发送缓存 此发送缓存的大小不做特殊要求 但太小会影响本地
*            的MCU的处理本地事务的能力 (特别是前后模式的程序和波特率低的情况)
*         4> 如果是在OS中使用 可以启用通知函数给串口接收分析任务 分析接收的数据 参考程序中屏蔽的函数
*         5> 中断响应的速度与COMM_MEM_SEL和高优先级中断的响应时间有关 如果接收数据很快可以加 DISABLE命令
**************************************************************************************************/

ISR(SIG_UART_TRANS){
    //COMM_ENTER_CRITICAL();                  // 进入临界
#if COMM_DATAFREE_ISR_EN == 0
    if (Comm1TxBufCtr > 0) {                  // 检查发送消息缓存区是否为空 不为空则继续发数据
        Comm1TxBufCtr--;                      // 缓存计数器减1
        UDR = Comm1TxBuf[Comm1TxOutIx++];     // 读走一个数据到发送寄存器,自动清发送中断标志
        if (Comm1TxOutIx >= COMM1_TXD_SIZE) {
            Comm1TxOutIx  = 0;
        }
    } else {
        bComm1CanSend     = 0;                // 发送标志为0表示 可以直接发送信息
    }
#endif
    //COMM_EXIT_CRITICAL();                   // 退出临界
}

/**************************************************************************************************
* 功 能 : 串口发送数据寄存器空中断函数
* 入 口 : 无
* 返 回 : 无
* 说 明 : 数据寄存器空UDRE标志位为1表示发送缓冲区可以接受一个新的数据
**************************************************************************************************/
#if COMM_DATAFREE_ISR_EN > 0
ISR(SIG_UART_DATA){
    //COMM_ENTER_CRITICAL();                  // 进入临界
    if (Comm1TxBufCtr > 0) {                  // 检查发送消息缓存区是否为空 不为空则继续发数据
        Comm1TxBufCtr--;                      // 缓存计数器减1
        UDR = Comm1TxBuf[Comm1TxOutIx++];     // 读走一个数据到发送寄存器,自动清发送中断标志
        if (Comm1TxOutIx >= COMM1_TXD_SIZE) {
            Comm1TxOutIx  = 0;
        }
    } else {
        CLRBIT(UCSRB,BIT(UDRIE));             // 数据发送完,清数据寄存器中断使能位
        bComm1CanSend     = 0;                // 发送标志为0表示 可以直接发送信息
    }
    //COMM_EXIT_CRITICAL();                   // 退出临界
}
#endif

/********************************************************************************************************
* 功 能 : 发送的数据进入发送缓存
* 入 口 : 'Data' 进入缓存的消息数据
* 返 回 : 1> COMM_TXD_FLOODL 发送数据进入缓存满 (失败)
*         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
********************************************************************************************************/
[/code]

你可能感兴趣的:(嵌入式综合开发实践与交流)