一个不错的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]