⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comm.c

📁 这是一个AVR单片机的串行通讯模块 大家可以合理的用到自己的实验中
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************************************
* 文 件 名 : 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("\0")                   //发送一个空格 

/**************************************************************************************************
* 功 能 : 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 发送数据进入缓存满 (失败)

⌨️ 快捷键说明

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