MC9S12XEP100 SCI(UART)驱动程序2
来源:互联网 发布:powermill10软件下载 编辑:程序博客网 时间:2024/06/05 10:06
忙着毕设,很久没有写文章了,终于答辩完了,得了个校优秀毕业设计。毕设做的是个智能接口模块,用一周时间入门了MC9S12XEP100的开发,又用一周时间入门了uC/OS-II嵌入式操作系统,在做毕设的过程中学到了很多,现在把一些工具发上来分享。
首先先发一个自己封装的MC9S12XEP100的SCI模块(也就是UART模块)的驱动。这些代码参考了 Li Yuan http://blog.csdn.net/liyuanbhu/article/details/7764851 的代码,整个代码风格是按照uCOS-II操作系统源码的风格来写的,在此表示感谢。
目前还不是特别完整完善,但基本使用是没有问题了。
在上一章中已经发了硬件驱动部分,这里发下基于uCOS-II嵌入式操作系统的驱动部分以及顺便说下怎么用。
首先要记得到上一章中把两个文件存了,顺便还要把.h文件中的
SCI_UCOS_MODULE_ENABLE 后面改为 TRUE 以开启RTOS(嵌入式操作系统)驱动部分。
目前这个版本已经支持所有8个SCI口了。
首先是按照uCOS-II操作系统的要求写的中断服务程序。
;********************************************************************************************************; uC/OS-II; The Real-Time Kernel;; (c) Copyright 2002, Jean J. Labrosse, Weston, FL; All Rights Reserved;;; PAGED S12X Specific code; (CODEWARRIOR);; File : SCI_uCos.s; By : Lin Shijun(http://blog.csdn.net/lin_strong);; Notes : THIS FILE *MUST* BE LINKED INTO NON_BANKED MEMORY! 这个文件必须放在非分页内存中; modified according to uC/OS-II's example. 依据uC/OS-II的模版修改。;********************************************************************************************************NON_BANKED: section;********************************************************************************************************; I/O PORT ADDRESSES I/O口地址;********************************************************************************************************PPAGE: equ $0015 ; Addres of PPAGE register (assuming MC9S12XEP100 part)RPAGE: equ $0016 ; Addres of RPAGE register (assuming MC9S12XEP100 part)EPAGE: equ $0017 ; Addres of EPAGE register (assuming MC9S12XEP100 part)GPAGE: equ $0010 ; Addres of GPAGE register (assuming MC9S12XEP100 part);********************************************************************************************************; PUBLIC DECLARATIONS 公开声明;******************************************************************************************************** xdef SCI0_RxTxISR xdef SCI1_RxTxISR xdef SCI2_RxTxISR xdef SCI3_RxTxISR xdef SCI4_RxTxISR xdef SCI5_RxTxISR xdef SCI6_RxTxISR xdef SCI7_RxTxISR;********************************************************************************************************; EXTERNAL DECLARATIONS 外部声明;******************************************************************************************************** xref OSIntExit xref OSIntNesting xref OSTCBCur xref SCI0_ISR_Handler xref SCI1_ISR_Handler xref SCI2_ISR_Handler xref SCI3_ISR_Handler xref SCI4_ISR_Handler xref SCI5_ISR_Handler xref SCI6_ISR_Handler xref SCI7_ISR_Handler;********************************************************************************************************; SCI RxTx ISR;; Description : This routine is the uC/Probe RxTx interrupt service routine;; Arguments : none;; Notes : 1) All USER interrupts should be modeled EXACTLY like this where the only; line to be modified is the call to your ISR_Handler and perhaps the call to; the label name SCI0_ISR_Handler.;********************************************************************************************************SCI0_RxTxISR: ldaa GPAGE ; Get current value of GPAGE register psha ; Push GPAGE register onto current task's stack ldaa EPAGE ; Get current value of EPAGE register psha ; Push EPAGE register onto current task's stack ldaa RPAGE ; Get current value of RPAGE register psha ; Push RPAGE register onto current task's stack ldaa PPAGE ; Get current value of PPAGE register psha ; Push PPAGE register onto current task's stack inc OSIntNesting ; Notify uC/OS-II about ISR ldab OSIntNesting ; if (OSIntNesting == 1) { cmpb #$01 bne SCI0_RxTxISR1 ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer sts 0,y ; }SCI0_RxTxISR1: call SCI0_ISR_Handler ; Call TxRx ISR handler. (See SCI_uCos.c); cli ; Optionally enable interrupts to allow interrupt nesting call OSIntExit ; Notify uC/OS-II about end of ISR, a context switch may occur from within OSIntExit(). pula ; Get value of PPAGE register staa PPAGE ; Store into CPU's PPAGE register pula ; Get value of RPAGE register staa RPAGE ; Store into CPU's RPAGE register pula ; Get value of EPAGE register staa EPAGE ; Store into CPU's EPAGE register pula ; Get value of GPAGE register staa GPAGE ; Store into CPU's GPAGE register rti ; Return from interrupt to interrupted task.SCI1_RxTxISR: ldaa GPAGE ; Get current value of GPAGE register psha ; Push GPAGE register onto current task's stack ldaa EPAGE ; Get current value of EPAGE register psha ; Push EPAGE register onto current task's stack ldaa RPAGE ; Get current value of RPAGE register psha ; Push RPAGE register onto current task's stack ldaa PPAGE ; Get current value of PPAGE register psha ; Push PPAGE register onto current task's stack inc OSIntNesting ; Notify uC/OS-II about ISR ldab OSIntNesting ; if (OSIntNesting == 1) { cmpb #$01 bne SCI1_RxTxISR1 ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer sts 0,y ; }SCI1_RxTxISR1: call SCI1_ISR_Handler ; Call TxRx ISR handler. (See SCI_uCos.c); cli ; Optionally enable interrupts to allow interrupt nesting call OSIntExit ; Notify uC/OS-II about end of ISR, a context switch may occur from within OSIntExit(). pula ; Get value of PPAGE register staa PPAGE ; Store into CPU's PPAGE register pula ; Get value of RPAGE register staa RPAGE ; Store into CPU's RPAGE register pula ; Get value of EPAGE register staa EPAGE ; Store into CPU's EPAGE register pula ; Get value of GPAGE register staa GPAGE ; Store into CPU's GPAGE register rti ; Return from interrupt to interrupted task.SCI2_RxTxISR: ldaa GPAGE ; Get current value of GPAGE register psha ; Push GPAGE register onto current task's stack ldaa EPAGE ; Get current value of EPAGE register psha ; Push EPAGE register onto current task's stack ldaa RPAGE ; Get current value of RPAGE register psha ; Push RPAGE register onto current task's stack ldaa PPAGE ; Get current value of PPAGE register psha ; Push PPAGE register onto current task's stack inc OSIntNesting ; Notify uC/OS-II about ISR ldab OSIntNesting ; if (OSIntNesting == 1) { cmpb #$01 bne SCI2_RxTxISR1 ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer sts 0,y ; }SCI2_RxTxISR1: call SCI2_ISR_Handler ; Call TxRx ISR handler. (See SCI_uCos.c); cli ; Optionally enable interrupts to allow interrupt nesting call OSIntExit ; Notify uC/OS-II about end of ISR, a context switch may occur from within OSIntExit(). pula ; Get value of PPAGE register staa PPAGE ; Store into CPU's PPAGE register pula ; Get value of RPAGE register staa RPAGE ; Store into CPU's RPAGE register pula ; Get value of EPAGE register staa EPAGE ; Store into CPU's EPAGE register pula ; Get value of GPAGE register staa GPAGE ; Store into CPU's GPAGE register rti ; Return from interrupt to interrupted task.SCI3_RxTxISR: ldaa GPAGE ; Get current value of GPAGE register psha ; Push GPAGE register onto current task's stack ldaa EPAGE ; Get current value of EPAGE register psha ; Push EPAGE register onto current task's stack ldaa RPAGE ; Get current value of RPAGE register psha ; Push RPAGE register onto current task's stack ldaa PPAGE ; Get current value of PPAGE register psha ; Push PPAGE register onto current task's stack inc OSIntNesting ; Notify uC/OS-II about ISR ldab OSIntNesting ; if (OSIntNesting == 1) { cmpb #$01 bne SCI3_RxTxISR1 ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer sts 0,y ; }SCI3_RxTxISR1: call SCI3_ISR_Handler ; Call TxRx ISR handler. (See SCI_uCos.c); cli ; Optionally enable interrupts to allow interrupt nesting call OSIntExit ; Notify uC/OS-II about end of ISR, a context switch may occur from within OSIntExit(). pula ; Get value of PPAGE register staa PPAGE ; Store into CPU's PPAGE register pula ; Get value of RPAGE register staa RPAGE ; Store into CPU's RPAGE register pula ; Get value of EPAGE register staa EPAGE ; Store into CPU's EPAGE register pula ; Get value of GPAGE register staa GPAGE ; Store into CPU's GPAGE register rti ; Return from interrupt to interrupted task.SCI4_RxTxISR: ldaa GPAGE ; Get current value of GPAGE register psha ; Push GPAGE register onto current task's stack ldaa EPAGE ; Get current value of EPAGE register psha ; Push EPAGE register onto current task's stack ldaa RPAGE ; Get current value of RPAGE register psha ; Push RPAGE register onto current task's stack ldaa PPAGE ; Get current value of PPAGE register psha ; Push PPAGE register onto current task's stack inc OSIntNesting ; Notify uC/OS-II about ISR ldab OSIntNesting ; if (OSIntNesting == 1) { cmpb #$01 bne SCI4_RxTxISR1 ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer sts 0,y ; }SCI4_RxTxISR1: call SCI4_ISR_Handler ; Call TxRx ISR handler. (See SCI_uCos.c); cli ; Optionally enable interrupts to allow interrupt nesting call OSIntExit ; Notify uC/OS-II about end of ISR, a context switch may occur from within OSIntExit(). pula ; Get value of PPAGE register staa PPAGE ; Store into CPU's PPAGE register pula ; Get value of RPAGE register staa RPAGE ; Store into CPU's RPAGE register pula ; Get value of EPAGE register staa EPAGE ; Store into CPU's EPAGE register pula ; Get value of GPAGE register staa GPAGE ; Store into CPU's GPAGE register rti ; Return from interrupt to interrupted task.SCI5_RxTxISR: ldaa GPAGE ; Get current value of GPAGE register psha ; Push GPAGE register onto current task's stack ldaa EPAGE ; Get current value of EPAGE register psha ; Push EPAGE register onto current task's stack ldaa RPAGE ; Get current value of RPAGE register psha ; Push RPAGE register onto current task's stack ldaa PPAGE ; Get current value of PPAGE register psha ; Push PPAGE register onto current task's stack inc OSIntNesting ; Notify uC/OS-II about ISR ldab OSIntNesting ; if (OSIntNesting == 1) { cmpb #$01 bne SCI5_RxTxISR1 ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer sts 0,y ; }SCI5_RxTxISR1: call SCI5_ISR_Handler ; Call TxRx ISR handler. (See SCI_uCos.c); cli ; Optionally enable interrupts to allow interrupt nesting call OSIntExit ; Notify uC/OS-II about end of ISR, a context switch may occur from within OSIntExit(). pula ; Get value of PPAGE register staa PPAGE ; Store into CPU's PPAGE register pula ; Get value of RPAGE register staa RPAGE ; Store into CPU's RPAGE register pula ; Get value of EPAGE register staa EPAGE ; Store into CPU's EPAGE register pula ; Get value of GPAGE register staa GPAGE ; Store into CPU's GPAGE register rti ; Return from interrupt to interrupted task.SCI6_RxTxISR: ldaa GPAGE ; Get current value of GPAGE register psha ; Push GPAGE register onto current task's stack ldaa EPAGE ; Get current value of EPAGE register psha ; Push EPAGE register onto current task's stack ldaa RPAGE ; Get current value of RPAGE register psha ; Push RPAGE register onto current task's stack ldaa PPAGE ; Get current value of PPAGE register psha ; Push PPAGE register onto current task's stack inc OSIntNesting ; Notify uC/OS-II about ISR ldab OSIntNesting ; if (OSIntNesting == 1) { cmpb #$01 bne SCI6_RxTxISR1 ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer sts 0,y ; }SCI6_RxTxISR1: call SCI6_ISR_Handler ; Call TxRx ISR handler. (See SCI_uCos.c); cli ; Optionally enable interrupts to allow interrupt nesting call OSIntExit ; Notify uC/OS-II about end of ISR, a context switch may occur from within OSIntExit(). pula ; Get value of PPAGE register staa PPAGE ; Store into CPU's PPAGE register pula ; Get value of RPAGE register staa RPAGE ; Store into CPU's RPAGE register pula ; Get value of EPAGE register staa EPAGE ; Store into CPU's EPAGE register pula ; Get value of GPAGE register staa GPAGE ; Store into CPU's GPAGE register rti ; Return from interrupt to interrupted task.SCI7_RxTxISR: ldaa GPAGE ; Get current value of GPAGE register psha ; Push GPAGE register onto current task's stack ldaa EPAGE ; Get current value of EPAGE register psha ; Push EPAGE register onto current task's stack ldaa RPAGE ; Get current value of RPAGE register psha ; Push RPAGE register onto current task's stack ldaa PPAGE ; Get current value of PPAGE register psha ; Push PPAGE register onto current task's stack inc OSIntNesting ; Notify uC/OS-II about ISR ldab OSIntNesting ; if (OSIntNesting == 1) { cmpb #$01 bne SCI7_RxTxISR1 ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer sts 0,y ; }SCI7_RxTxISR1: call SCI7_ISR_Handler ; Call TxRx ISR handler. (See SCI_uCos.c); cli ; Optionally enable interrupts to allow interrupt nesting call OSIntExit ; Notify uC/OS-II about end of ISR, a context switch may occur from within OSIntExit(). pula ; Get value of PPAGE register staa PPAGE ; Store into CPU's PPAGE register pula ; Get value of RPAGE register staa RPAGE ; Store into CPU's RPAGE register pula ; Get value of EPAGE register staa EPAGE ; Store into CPU's EPAGE register pula ; Get value of GPAGE register staa GPAGE ; Store into CPU's GPAGE register rti ; Return from interrupt to interrupted task.
要记得修改中断向量表把用到的端口的ISR分别指向其中断地址,如SCI0_RxTxISR指向0xFFD6、SCI1_RxTxISR1指向0xFFD4,也就是SCI0和SCI1的中断地址。
然后是.c文件:
/*********************************************************************************************** SCI(Serial Communication Interface) Buffered Serial I/O * Freescale MC9S12XEP100* 飞思卡尔 MC9S12XEP100 SCI支持包** File : SCI_uCos.c* By : Lin Shijun(http://blog.csdn.net/lin_strong)* Date: 2017/10/27* version: V2.1* History: 2017/04/24 V1.0 the prototype of SCI_uCOS,only support SCI0 and SCI1* 2017/07/20 V2.0 update the module to support the SCI0 to SCI7* 2017/10/27 V2.1 fix a bug: when disable a port between two active port,the upper one can't work.* this is due to the statment: * for(port = 0;port < 8 && isSCIEnable(port);port++)* in SCI_BufferInit().* the judgment statment port < 8 && isSCIEnable(port) will jump out the init loop * the first time meet the first disabled SCI port.* NOTE(s): 1.refer to Li Yuan's (http://blog.csdn.net/liyuanbhu/article/details/7768914)* and * uCOS-II's Code* 2.记得把SCI_uCOS.s中的SCIx_RxTxISR中断服务程序指向对应的中断向量地址*********************************************************************************************//********************************************************************************************** INCLUDES*********************************************************************************************/#include "SCI_def.h"#if(SCI_MODULE_ENABLE == TRUE && SCI_UCOS_MODULE_ENABLE == TRUE)#include <stddef.h>#include <string.h>#include <ucos_ii.h> #include "RingQueue.h"/* ********************************************************************************************** DATA TYPES **********************************************************************************************/typedef struct{ INT8U port; /* Hold the port number */ OS_EVENT *RingBufRxSem; /* Pointer to Rx semaphore */ RING_QUEUE* RingBufRx; /* Ring buffer character storage (Rx) */ OS_EVENT *RingBufTxMutex; /* Pointer to Tx MUTUAL semaphore */ OS_EVENT *RingBufTxSem; /* Pointer to Tx semaphore */ RING_QUEUE* RingBufTx; /* Ring buffer character storage (Tx) */ } SCI_RING_BUF;/****************************************************************************************** CONSTANT *****************************************************************************************/// Flag of SCI enable.#define EnableFlag ((SCI0_UCOS_CODE_EN << 0) | (SCI1_UCOS_CODE_EN << 1) | (SCI2_UCOS_CODE_EN << 2) | \ (SCI3_UCOS_CODE_EN << 3) | (SCI4_UCOS_CODE_EN << 4) | (SCI5_UCOS_CODE_EN << 5) | \ (SCI6_UCOS_CODE_EN << 6) | (SCI7_UCOS_CODE_EN << 7))#define isSCIEnable(port) ((EnableFlag >> port) & 0x01)static const INT8U SCITxMutexPrios[] = { SCI0_TX_MUTEX_PRIO, SCI1_TX_MUTEX_PRIO, SCI2_TX_MUTEX_PRIO, SCI3_TX_MUTEX_PRIO, SCI4_TX_MUTEX_PRIO, SCI5_TX_MUTEX_PRIO, SCI6_TX_MUTEX_PRIO, SCI7_TX_MUTEX_PRIO,};#define SCI_TX_MUTEX_PRIO(port) SCITxMutexPrios[port]// const of RxBuffer Sizes#if(SCI0_RX_BUFFER_SIZE < 256 && SCI1_RX_BUFFER_SIZE < 256 && SCI2_RX_BUFFER_SIZE < 256 && \ SCI3_RX_BUFFER_SIZE < 256 && SCI4_RX_BUFFER_SIZE < 256 && SCI5_RX_BUFFER_SIZE < 256 && \ SCI6_RX_BUFFER_SIZE < 256 && SCI7_RX_BUFFER_SIZE < 256) #define RxSizeArrType INT8U#else #define RxSizeArrType INT16U#endifstatic const RxSizeArrType SCIRxBufferSize[]={ SCI0_RX_BUFFER_SIZE, SCI1_RX_BUFFER_SIZE, SCI2_RX_BUFFER_SIZE, SCI3_RX_BUFFER_SIZE, SCI4_RX_BUFFER_SIZE, SCI5_RX_BUFFER_SIZE, SCI6_RX_BUFFER_SIZE, SCI7_RX_BUFFER_SIZE, };#define SCIRxBufSize(port) SCIRxBufferSize[port]#define isSCIRxEnable(port) (SCIRxBufferSize[port] > 0)// const of TxBuffer Sizes#if(SCI0_TX_BUFFER_SIZE < 256 && SCI1_TX_BUFFER_SIZE < 256 && SCI2_TX_BUFFER_SIZE < 256 && SCI3_TX_BUFFER_SIZE < 256 \ && SCI4_TX_BUFFER_SIZE < 256 && SCI5_TX_BUFFER_SIZE < 256 && SCI6_TX_BUFFER_SIZE < 256 && SCI7_TX_BUFFER_SIZE < 256) #define TxSizeArrType INT8U#else #define TxSizeArrType INT16U#endifstatic const TxSizeArrType SCITxBufferSize[]={ SCI0_TX_BUFFER_SIZE, SCI1_TX_BUFFER_SIZE, SCI2_TX_BUFFER_SIZE, SCI3_TX_BUFFER_SIZE, SCI4_TX_BUFFER_SIZE, SCI5_TX_BUFFER_SIZE, SCI6_TX_BUFFER_SIZE, SCI7_TX_BUFFER_SIZE, };#define SCITxBufSize(port) SCITxBufferSize[port]#define isSCITxEnable(port) (SCITxBufferSize[port] > 0)#define SCI_RX_BUFFER_SIZE_SUM (SCI0_RX_BUFFER_SIZE + SCI1_RX_BUFFER_SIZE + SCI2_RX_BUFFER_SIZE + SCI3_RX_BUFFER_SIZE \ + SCI4_RX_BUFFER_SIZE + SCI5_RX_BUFFER_SIZE + SCI6_RX_BUFFER_SIZE + SCI7_RX_BUFFER_SIZE)#define SCI_TX_BUFFER_SIZE_SUM (SCI0_TX_BUFFER_SIZE + SCI1_TX_BUFFER_SIZE + SCI2_TX_BUFFER_SIZE + SCI3_TX_BUFFER_SIZE \ + SCI4_TX_BUFFER_SIZE + SCI5_TX_BUFFER_SIZE + SCI6_TX_BUFFER_SIZE + SCI7_TX_BUFFER_SIZE)#define SCI_BUFFER_SIZE_SUM (SCI_RX_BUFFER_SIZE_SUM + SCI_TX_BUFFER_SIZE_SUM)#define SCI_RX_BUFFERS_COUNT ((SCI0_RX_BUFFER_SIZE>0) + (SCI1_RX_BUFFER_SIZE>0) + (SCI2_RX_BUFFER_SIZE>0) + \ (SCI3_RX_BUFFER_SIZE>0) + (SCI4_RX_BUFFER_SIZE>0) + (SCI5_RX_BUFFER_SIZE>0) + \ (SCI6_RX_BUFFER_SIZE>0) + (SCI7_RX_BUFFER_SIZE>0))#define SCI_TX_BUFFERS_COUNT ((SCI0_TX_BUFFER_SIZE>0) + (SCI1_TX_BUFFER_SIZE>0) + (SCI2_TX_BUFFER_SIZE>0) + \ (SCI3_TX_BUFFER_SIZE>0) + (SCI4_TX_BUFFER_SIZE>0) + (SCI5_TX_BUFFER_SIZE>0) + \ (SCI6_TX_BUFFER_SIZE>0)) + (SCI7_TX_BUFFER_SIZE>0)#define SCI_BUFFERS_COUNT (SCI_RX_BUFFERS_COUNT + SCI_TX_BUFFERS_COUNT)#define SCI_RING_QUEUE_COUNT SCI_BUFFERS_COUNT/****************************************************************************************** GLOBAL VARIABLES *****************************************************************************************/#define SCI_RING_BUFS_COUNT SCI0_UCOS_CODE_EN + SCI1_UCOS_CODE_EN + SCI2_UCOS_CODE_EN + SCI3_UCOS_CODE_EN + \ SCI4_UCOS_CODE_EN + SCI5_UCOS_CODE_EN + SCI6_UCOS_CODE_EN + SCI7_UCOS_CODE_ENSCI_RING_BUF SCIBufs[SCI_RING_BUFS_COUNT];SCI_RING_BUF * const Ptr_SCIBuf[] = { #if(SCI0_UCOS_CODE_EN == TRUE) &SCIBufs[0], #else NULL, #endif #if(SCI1_UCOS_CODE_EN == TRUE) &SCIBufs[SCI0_UCOS_CODE_EN], #else NULL, #endif #if(SCI2_UCOS_CODE_EN == TRUE) &SCIBufs[SCI0_UCOS_CODE_EN + SCI1_UCOS_CODE_EN], #else NULL, #endif #if(SCI3_UCOS_CODE_EN == TRUE) &SCIBufs[SCI0_UCOS_CODE_EN + SCI1_UCOS_CODE_EN + SCI2_UCOS_CODE_EN], #else NULL, #endif #if(SCI4_UCOS_CODE_EN == TRUE) &SCIBufs[SCI0_UCOS_CODE_EN + SCI1_UCOS_CODE_EN + SCI2_UCOS_CODE_EN + SCI3_UCOS_CODE_EN], #else NULL, #endif #if(SCI5_UCOS_CODE_EN == TRUE) &SCIBufs[SCI0_UCOS_CODE_EN + SCI1_UCOS_CODE_EN + SCI2_UCOS_CODE_EN + SCI3_UCOS_CODE_EN + SCI4_UCOS_CODE_EN], #else NULL, #endif #if(SCI6_UCOS_CODE_EN == TRUE) &SCIBufs[SCI0_UCOS_CODE_EN + SCI1_UCOS_CODE_EN + SCI2_UCOS_CODE_EN + SCI3_UCOS_CODE_EN + SCI4_UCOS_CODE_EN \ + SCI5_UCOS_CODE_EN], #else NULL, #endif #if(SCI7_UCOS_CODE_EN == TRUE) &SCIBufs[SCI0_UCOS_CODE_EN + SCI1_UCOS_CODE_EN + SCI2_UCOS_CODE_EN + SCI3_UCOS_CODE_EN + SCI4_UCOS_CODE_EN \ + SCI5_UCOS_CODE_EN + SCI6_UCOS_CODE_EN], #else NULL, #endif};#define pSCIBuf(port) Ptr_SCIBuf[port]/*********************************************************************************************** LOCAL VARIABLES **********************************************************************************************/static union{ byte FLAG; struct { byte Inited :1; //Initialized Flag byte :1; byte :1; byte :1; byte :1; byte :1; byte :1; byte :1; } Bits;} flag = {0};// 所有SCI的所有收发缓冲区其实都在同一个大数组中,每个小块分别由不同的环形队列对象管理即可#if (SCI_BUFFER_SIZE_SUM > 0) static INT8U SCIBuffer[SCI_BUFFER_SIZE_SUM];#else static INT8U *SCIBuffer = NULL;#endif// 管理SCI的所有环形队列对象都在一个数组中#if (SCI_RING_QUEUE_COUNT > 0) static RING_QUEUE SCIRingQueues[SCI_BUFFERS_COUNT];#else static RING_QUEUE* SCIRingQueues = NULL;#endif#define pSCI_RingBufRx(port) (pSCIBuf(port)->RingBufRx)#define pSCI_RingBufTx(port) (pSCIBuf(port)->RingBufTx)#if (APP_TRACE_LEVEL >= TRACE_LEVEL_INFO) // 调试用变量 INT16U ClearTimes;#endif/******************************************************************************************** LOCAL FUNCTION DECLARE*******************************************************************************************/#pragma CODE_SEG __NEAR_SEG NON_BANKED static INT8U _SCI_TxPutCharB(SCI_RING_BUF* pbuf, INT8U c, INT16U timeout);static SCI_RING_BUF* _SCI_getRingBuf_chkRx(INT8U port);static SCI_RING_BUF* _SCI_getRingBuf_chkTx(INT8U port);#pragma CODE_SEG DEFAULT/******************************************************************************************** SCI_BufferInit()** Description : To initialize the communications module. * 初始化通信模型.* You must call this function before calling any other functions. * 必须在调用其他函数前调用它.* Arguments : * * Return:**Note(s):*******************************************************************************************/void SCI_BufferInit (void) { SCI_RING_BUF *pSCIRingBuf; INT8U err,port; RING_QUEUE* pRingQueue = SCIRingQueues; INT8U *pBuf = SCIBuffer; // 简单的保护 if(flag.Bits.Inited) return; // Initialize all buffers for(port = 0;port < 8;port++){ if(!isSCIEnable(port)) // continue when the current port is not enable. continue; pSCIRingBuf = pSCIBuf(port); pSCIRingBuf->port = port; if(isSCITxEnable(port)) { pSCIRingBuf->RingBufTxMutex = OSMutexCreate(SCI_TX_MUTEX_PRIO(port),&err); pSCIRingBuf->RingBufTxSem = OSSemCreate(SCITxBufSize(port)); pSCIRingBuf->RingBufTx = RingQueueInit(pRingQueue++,pBuf,SCITxBufSize(port),&err); pBuf += SCITxBufSize(port); } if(isSCIRxEnable(port)) { pSCIRingBuf->RingBufRxSem = OSSemCreate(0); pSCIRingBuf->RingBufRx = RingQueueInit(pRingQueue++,pBuf,SCIRxBufSize(port),&err); pBuf += SCIRxBufSize(port); } } flag.Bits.Inited = 1;}/******************************************************************************************** SCI_GetCharB()** Description : To obtain a character from the communications channel. * 从通信信道中获取一个字符** Arguments : port port can be SCI0 / SCI1; 选择端口;* timeout the amount of time (in clock ticks) that the calling function is willing to ...* ...wait for a character to arrive. If you specify a timeout of 0,...* ...the function will wait forever for a character to arrive.* 调用者最久愿意等待一个字符到达的时钟节拍数,为0表示永久等待.* err is a pointer to where an error code will be placed: 用于返回故障码:* SCI_NO_ERR if a character has been received 正确收到字符* SCI_RX_TIMEOUT if a timeout occurred 接收超时* SCI_BAD_CH if you specify an invalid channel number 通道号错误* Return: The character in the buffer (or NUL if a timeout occurred); 缓冲区内的字符(或者发生了超时);* Note(s):********************************************************************************************/INT8U SCI_GetCharB (INT8U port, INT16U timeout, INT8U *err) {#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif INT8U c; INT8U oserr; SCI_RING_BUF *pbuf; pbuf = _SCI_getRingBuf_chkRx(port); if(pbuf == NULL){ *err = SCI_BAD_CH; return (NUL); } OSSemPend(pbuf->RingBufRxSem, timeout, &oserr); /* Wait for character to arrive */ if (oserr == OS_TIMEOUT) { /* See if characters received within timeout*/ *err = SCI_RX_TIMEOUT; /* No, return error code */ return (NUL); } else { OS_ENTER_CRITICAL(); c = RingQueueOut(pbuf->RingBufRx,&oserr); /* Get next one from ring queue.*/ OS_EXIT_CRITICAL(); *err = SCI_NO_ERR; return (c); } } /************************************************************************************************ SCI_PutCharB_Mutex()** Description : This function is called by your application to send a character on the communications * channel. The function will wait for the buffer to empty out if the buffer is full. * The function returns to your application if the buffer doesn't empty within the specified * timeout. A timeout value of 0 means that the calling function will wait forever for the * buffer to empty out. The character to send is first inserted into the Tx buffer and will * be sent by the Tx ISR. If this is the first character placed into the buffer, the Tx ISR * will be enabled.** equal to call: * SCI_SendBuf_hold (port, timeout, &perr);* perr = SCI_PutCharB(port, INT8U c, INT16U timeout);* SCI_SendBuf_release(port);** Arguments : port port can be SCI0 / SCI1; 选择端口;* c the character to send; 要发送的字符;* timeout is the timeout (in clock ticks) to wait in case the buffer is full. If you ...* ...specify a timeout of 0, the function will wait forever for the buffer to empty. * 在缓冲区满的情况下, 调用者最久愿意等待的时钟节拍数,为0表示永久等待.* Return: SCI_NO_ERR if the character was placed in the Tx buffer; * 字符成功放入Tx缓冲区内;* SCI_TX_TIMEOUT if the buffer didn't empty or can't access within the specified timeout period;* 超时后还是没有清空缓冲区或者还无法访问* SCI_BAD_CH if you specify an invalid channel number 通道号错误*Note(s): ***********************************************************************************************/INT8U SCI_PutCharB_Mutex (INT8U port, INT8U c, INT16U timeout) { SCI_RING_BUF *pbuf; INT8U oserr; pbuf = _SCI_getRingBuf_chkTx(port); if(pbuf == NULL) return (SCI_BAD_CH); OSMutexPend(pbuf->RingBufTxMutex,timeout,&oserr); /* Wait for the right of use Tx buffer*/ if(oserr == OS_ERR_NONE) /* If get the right then */ oserr = _SCI_TxPutCharB(pbuf,c,timeout); /* Put INT8U into Tx buffer*/ OSMutexPost(pbuf->RingBufTxMutex); /* Release the the right of use Tx buffer*/ if (oserr == OS_TIMEOUT) /* If Timeout happen */ return (SCI_TX_TIMEOUT); /* Timed out, return error code */ return (SCI_NO_ERR); }/*********************************************************************************************** SCI_PutCharsB_Mutex()** Description : This function is called by your application to send chars on the communications * channel. The function will wait for the buffer to empty out if the buffer is full. * The function returns to your application if the buffer doesn't empty within the specified * timeout. A timeout value of 0 means that the calling function will wait forever for the * buffer to empty out. The character to send is first inserted into the Tx buffer and will * be sent by the Tx ISR. If this is the first character placed into the buffer, the Tx ISR * will be enabled. * equal to call: * SCI_SendBuf_hold (port, timeout, &perr);* perr = SCI_PutCharsB(port, INT8U c, INT16U timeout);* SCI_SendBuf_release(port);** Arguments : port port can be SCI0 / SCI1; 选择端口;* buf the buffer; 要发送的字符;* length the length of the buffer; * timeout is the timeout (in clock ticks) to wait in case the buffer is full. If you * specify a timeout of 0, the function will wait forever for the buffer to empty. * 在缓冲区满的情况下, 调用者最久愿意等待的时钟节拍数,为0表示永久等待.* Return: SCI_NO_ERR if the character was placed in the Tx buffer; 字符成功放入Tx缓冲区内;* SCI_TX_TIMEOUT if the buffer didn't empty or can't access within the specified timeout period;* 超时后还是没有清空缓冲区或者还无法访问* SCI_BAD_CH if you specify an invalid channel number 通道号错误*Note(s): ************************************************************************************************/INT8U SCI_PutCharsB_Mutex (INT8U port, const INT8U *buf,INT16U length, INT16U timeout) { SCI_RING_BUF *pbuf; INT8U oserr; pbuf = _SCI_getRingBuf_chkTx(port); if(pbuf == NULL) return (SCI_BAD_CH); OSMutexPend(pbuf->RingBufTxMutex,timeout,&oserr); /* Wait for the right of use Tx buffer*/ if(oserr == OS_ERR_NONE) while(length--){ oserr = _SCI_TxPutCharB(pbuf,*buf++,timeout); /* Put INT8U into Tx buffer*/ if (oserr != OS_ERR_NONE) /* if any err happen */ break; /* break */ } OSMutexPost(pbuf->RingBufTxMutex); if (oserr == OS_TIMEOUT) return (SCI_TX_TIMEOUT); /* Timed out, return error code */ return (SCI_NO_ERR); }/********************************************************************************************** SCI_PutStringB_Mutex()** Description : This function is called by your application to send a string,which ends with '\0', on the communications * channel. The function will wait for the buffer to empty out if the buffer is full. * The function returns to your application if the buffer doesn't empty within the specified * timeout. A timeout value of 0 means that the calling function will wait forever for the * buffer to empty out. The character to send is first inserted into the Tx buffer and will * be sent by the Tx ISR. If this is the first character placed into the buffer, the Tx ISR * ill be enabled. ** Arguments : port port can be SCI0 / SCI1; 选择端口;* buf the buffer; 要发送的字符;* length the length of the buffer; * timeout is the timeout (in clock ticks) to wait in case the buffer is full. If you ...* ...specify a timeout of 0, the function will wait forever for the buffer to empty. * 在缓冲区满的情况下, 调用者最久愿意等待的时钟节拍数,为0表示永久等待.* Return: SCI_NO_ERR if the character was placed in the Tx buffer; 字符成功放入Tx缓冲区内;* SCI_TX_TIMEOUT if the buffer didn't empty or can't access within the specified timeout period;* 超时后还是没有清空缓冲区或者还无法访问* SCI_BAD_CH if you specify an invalid channel number 通道号错误*Note(s): ***********************************************************************************************///INT8U SCI_PutStringB_Mutex(INT8U port, const INT8U *str, INT16U timeout){ // return SCI_PutCharsB_Mutex(port,str,strlen(str),timeout);//}/*********************************************************************************************** SCI_SendBuf_hold()** Description : This function is called by your application to own the exclusive right of ...* ...sending INT8U on particular SCI port. your function should look like this:** SCI_SendBuf_hold(port,timeout,&err);* if (*err == SCI_NO_ERR){* .......* SCI_PutCharB(port,c,&err);* .......* }* SCI_SendBuf_release(port);** Arguments : port port can be SCI0/SCI1; 选择端口;* timeout is the timeout (in clock ticks) to wait in case the buffer is occupied. If you ...* ...specify a timeout of 0, the function will wait forever for the buffer to empty. * 在其他地方占有使用权的情况下, 调用者最久愿意等待的时钟节拍数,为0表示永久等待.* perr SCI_NO_ERR if get the exclusive right of sending INT8U on particular SCI port successfully; * 成功获取对应端口的发送权* SCI_TX_TIMEOUT if can't get the exclusive right of sending INT8U on particular...* ... SCI port within the specified timeout period;* 超时后还是没有获得对应端口的发送权* SCI_BAD_CH if you specify an invalid channel number. 通道号错误* SCI_ERR_UNKNOWN unknow err happen. 发生了未知的错误* Return:*Note(s): 1.Once call this function successfully, you must call SCI_SendBuf_release in the end of your function. ...* ... Otherwise, other caller to SCI_SendBuf_hold or SCI_XXX_Mutex mothod will fail.*********************************************************************************************/void SCI_SendBuf_hold(INT8U port, INT16U timeout, INT8U *perr){ SCI_RING_BUF *pbuf; pbuf = _SCI_getRingBuf_chkTx(port); if(pbuf == NULL){ *perr = SCI_BAD_CH; return; } OSMutexPend(pbuf->RingBufTxMutex,timeout,perr); /* Wait for the right of use Tx buffer*/ if(*perr == OS_ERR_NONE) *perr = SCI_NO_ERR; else if(*perr == OS_TIMEOUT) *perr = SCI_TX_TIMEOUT; /* Timed out, return error code */ else *perr = SCI_ERR_UNKNOWN;}/*********************************************************************************************** SCI_PutCharB()** Description : This function is called by your application to send INT8U on the communications * channel. The function will wait for the buffer to empty out if the buffer is full. * The function returns to your application if the buffer doesn't empty within the specified * timeout. A timeout value of 0 means that the calling function will wait forever for the * buffer to empty out. The character to send is first inserted into the Tx buffer and will * be sent by the Tx ISR. If this is the first character placed into the buffer, the Tx ISR * will be enabled. ** Arguments : port port can be SCI0 / SCI1; 选择端口;* c the INT8U to send; 要发送的字符;* timeout is the timeout (in clock ticks) to wait in case the buffer is full. If you ...* ...specify a timeout of 0, the function will wait forever for the buffer to empty. * 在缓冲区满的情况下, 调用者最久愿意等待的时钟节拍数,为0表示永久等待.** Return: SCI_NO_ERR if the character was placed in the Tx buffer; * 字符成功放入Tx缓冲区内;* SCI_TX_TIMEOUT if the buffer didn't empty within the specified timeout period;* 超时后还是没有清空缓冲区* SCI_BAD_CH if you specify an invalid channel number 通道号错误**Note(s): 1. you should call SCI_SendBuf_hold() first unless you know what you are doing.* 调用这个函数前你应该先调用SCI_SendBuf_hold(),除非你知道你在干什么**********************************************************************************************/INT8U SCI_PutCharB (INT8U port, INT8U c, INT16U timeout){ SCI_RING_BUF *pbuf; INT8U oserr; pbuf = _SCI_getRingBuf_chkTx(port); if(pbuf == NULL) return (SCI_BAD_CH); oserr = _SCI_TxPutCharB(pbuf,c,timeout); /* Put INT8U into Tx buffer*/ if (oserr == OS_TIMEOUT) /* If Timeout happen */ return (SCI_TX_TIMEOUT); /* Timed out, return error code */ return (SCI_NO_ERR); }/*********************************************************************************************** SCI_PutCharsB()** Description : This function is called by your application to send INT8U on the communications * channel. The function will wait for the buffer to empty out if the buffer is full. * The function returns to your application if the buffer doesn't empty within the specified * timeout. A timeout value of 0 means that the calling function will wait forever for the * buffer to empty out. The character to send is first inserted into the Tx buffer and will * be sent by the Tx ISR. If this is the first character placed into the buffer, the Tx ISR * will be enabled. ** Arguments : port port can be SCI0 / SCI1; 选择端口;* buf the buffer; 要发送的缓冲区;* length the length of the buffer; 缓冲区长度;* timeout is the timeout (in clock ticks) to wait in case the buffer is full. If you * specify a timeout of 0, the function will wait forever for the buffer to empty. * 在缓冲区满的情况下, 调用者最久愿意等待的时钟节拍数,为0表示永久等待.** Return: SCI_NO_ERR if the character was placed in the Tx buffer; * 字符成功放入Tx缓冲区内;* SCI_TX_TIMEOUT if the buffer didn't empty within the specified timeout period;* 超时后还是没有清空缓冲区* SCI_BAD_CH if you specify an invalid channel number 通道号错误**Note(s): 1. you should call SCI_SendBuf_hold() first unless you know what you are doing.***********************************************************************************************/INT8U SCI_PutCharsB(INT8U port, const INT8U *buf,INT16U length, INT16U timeout) { SCI_RING_BUF *pbuf; INT8U oserr; pbuf = _SCI_getRingBuf_chkTx(port); if(pbuf == NULL) return (SCI_BAD_CH); while(length--){ oserr = _SCI_TxPutCharB(pbuf,*buf++,timeout); /* Put INT8U into Tx buffer*/ if (oserr != OS_ERR_NONE) /* if any err happen */ break; /* break */ } if (oserr == OS_TIMEOUT) /* If Timeout happen */ return (SCI_TX_TIMEOUT); /* Timed out, return error code */ return (SCI_NO_ERR); }/*********************************************************************************************** SCI_SendBuf_release()** Description : This function is called by your application to release the exclusive right...* ... of sending INT8U on particular SCI port.** Arguments : port port can be SCI0/SCI1; 选择端口;** Return:**Note(s): **********************************************************************************************/void SCI_SendBuf_release(INT8U port){ SCI_RING_BUF *pbuf; pbuf = _SCI_getRingBuf_chkTx(port); if(pbuf != NULL) OSMutexPost(pbuf->RingBufTxMutex);}/************************************************************************************************ SCI_RxBufferIsEmpty()** Description : To see if any character is available from the communications channel. * 查看是否接收缓冲区为空** Arguments : port port can be SCI0 / SCI1; 选择端口;** Return : If at least one character is available, the function returns FALSE(0) otherwise,...* ... the function returns TRUE(1).* 0xff if you specify an invalid channel number.* 如果缓冲区内存在字符,则返回FALSE,否则返回TRUE. 0xff 如果通道号无效.*Note(s): ***********************************************************************************************/#if (SCI_CHECK_EMPTY_EN == TRUE)INT8U SCI_RxBufferIsEmpty (INT8U port) {#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif INT8U empty; SCI_RING_BUF *pbuf; pbuf = _SCI_getRingBuf_chkRx(port); if(pbuf == NULL) return (0xff); OS_ENTER_CRITICAL(); empty = RingQueueIsEmpty(pbuf->RingBufRx); OS_EXIT_CRITICAL(); return (empty);}#endif/********************************************************************************************** SCI_TxBufferIsFull()** Description: To see if any more characters can be placed in the Tx buffer. * 是否发送缓冲区已满** Arguments : port port can be SCI0 / SCI1; 选择端口;** Return : If the buffer is full, the function returns TRUE. Otherwise, the function returns FALSE. * 0xff if you specify an invalid channel number.* 如果发送缓冲区满,则返回TRUE,否则返回FALSE. 0xff 如果通道号无效.*Note(s): **********************************************************************************************/#if(SCI_CHECK_FULL_EN == TRUE)INT8U SCI_TxBufferIsFull (INT8U port) { #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif INT8U full; SCI_RING_BUF *pbuf; pbuf = _SCI_getRingBuf_chkTx(port); if(pbuf == NULL) return (0xff); OS_ENTER_CRITICAL(); full = RingQueueIsFull(pbuf->RingBufTx); OS_EXIT_CRITICAL(); return (full); } #endif/*********************************************************************************************************** LOCAL FUNCTION**********************************************************************************************************/#pragma CODE_SEG __NEAR_SEG NON_BANKED // 内部用来放字符到发送缓冲区, 返回的是SemPend的错误,默认RingQueueIn是不可能出错的(因为有信号量保证有空间可用)static INT8U _SCI_TxPutCharB(SCI_RING_BUF* pbuf, INT8U c, INT16U timeout){#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif INT8U err,tmperr; OSSemPend(pbuf->RingBufTxSem, timeout, &err); /* Wait for space in Tx buffer */ OS_ENTER_CRITICAL(); if (RingQueueIn(pbuf->RingBufTx,c,RQ_OPTION_WHEN_FULL_DISCARD_FIRST,&tmperr) == 1) /* Get next one from ring queue, and see whether... ... this is the first character */ SCI_EnableTxInt(pbuf->port); /* Yes, Enable Tx interrupts */ OS_EXIT_CRITICAL(); return err;}// 返回对应端口的SCI_RING_BUF, 如果端口不存在/未启用,或没启用Tx功能,则返回NULLstatic SCI_RING_BUF* _SCI_getRingBuf_chkTx(INT8U port){ if(port < 8 && isSCITxEnable(port)) return pSCIBuf(port); return NULL;}// 返回对应端口的SCI_RING_BUF, 如果端口不存在/未启用,或没启用Rx功能,则返回NULLstatic SCI_RING_BUF* _SCI_getRingBuf_chkRx(INT8U port){ if(port < 8 && isSCIRxEnable(port)) return pSCIBuf(port); return NULL;}// This function is called by the Rx ISR to insert a character into the receive ring buffer. // 这个函数由Rx ISR来插入一个字符到缓冲区内static void SCIPutRxChar (INT8U port, INT8U c) { SCI_RING_BUF *pbuf; INT8U oserr; pbuf = _SCI_getRingBuf_chkRx(port); //if(pbuf == NULL) // return; RingQueueIn(pbuf->RingBufRx,c,RQ_OPTION_WHEN_FULL_DISCARD_FIRST,&oserr); if(oserr == RQ_ERR_NONE) (void)OSSemPost(pbuf->RingBufRxSem); /* Indicate that character was received */ }// This function is called by the Tx ISR to extract the next character from the Tx buffer. // The function returns FALSE if the buffer is empty after the character is extracted from // the buffer. This is done to signal the Tx ISR to disable interrupts because this is the // last character to send. // 这个函数由Tx ISR调用来从Tx缓冲区内提取下一个字符.如果在提取完字符后缓冲区空了,函数就返回FALSE.// 这是用来通知Tx ISR禁止中断的。static INT8U SCIGetTxChar (INT8U port, INT8U *perr) { INT8U c; SCI_RING_BUF *pbuf; pbuf = _SCI_getRingBuf_chkTx(port); //if(pbuf == NULL){ // *err = SCI_BAD_CH; // return (0); //} c = RingQueueOut(pbuf->RingBufTx,perr); /* Get next one from ring queue.*/ if(*perr == RQ_ERR_NONE){ OSSemPost(pbuf->RingBufTxSem); *perr = SCI_NO_ERR; return c; }else{ *perr = SCI_TX_EMPTY; return (NUL); /* Buffer is empty */ }}#pragma CODE_SEG DEFALUT// 发现如果放到非分页区,则SCISR1的值会被清0,所以只能放在分页区了。static void SCI_ISR_Handler(INT8U port){ INT8U status,err; volatile INT8U data; status = SCISR1(port); if(status & 0x0F) // 0x1F = 0001 1111, if status is not Receive Data Reg Full Flag { // See if we have some kind of error // Clear interrupt (do nothing about it!) data = SCIDRL(port); // in case that compiler optimize this assignment,the 'data' must prefix volatile #if (APP_TRACE_LEVEL >= TRACE_LEVEL_INFO) ClearTimes++; #endif } else if(status & 0x20) //Receive Data Reg Full Flag { data = SCIDRL(port); SCIPutRxChar(port, data); // Insert received character into buffer } else if(status & 0x80) { data = SCIGetTxChar(port, &err); // Get next character to send. if (err == SCI_TX_EMPTY) { // Do we have anymore characters to send ? // No, Disable Tx interrupts SCI_DisableTxInt(port); } else { SCIDRL(port) = data; // Yes, Send character } }}void SCI0_ISR_Handler(void) {#if(SCI0_UCOS_CODE_EN == TRUE) SCI_ISR_Handler(SCI0);#endif}void SCI1_ISR_Handler (void) {#if(SCI1_UCOS_CODE_EN == TRUE) SCI_ISR_Handler(SCI1);#endif}void SCI2_ISR_Handler(void) {#if(SCI2_UCOS_CODE_EN == TRUE) SCI_ISR_Handler(SCI2);#endif}void SCI3_ISR_Handler (void) { #if(SCI3_UCOS_CODE_EN == TRUE) SCI_ISR_Handler(SCI3);#endif} void SCI4_ISR_Handler(void) { #if(SCI4_UCOS_CODE_EN == TRUE) SCI_ISR_Handler(SCI4);#endif}void SCI5_ISR_Handler (void) { #if(SCI5_UCOS_CODE_EN == TRUE) SCI_ISR_Handler(SCI5);#endif} void SCI6_ISR_Handler(void) { #if(SCI6_UCOS_CODE_EN == TRUE) SCI_ISR_Handler(SCI6);#endif}void SCI7_ISR_Handler(void){ #if(SCI7_UCOS_CODE_EN == TRUE) SCI_ISR_Handler(SCI7);#endif} #endif // of (SCI_MODULE_ENABLE == TRUE && SCI_UCOS_MODULE_ENABLE == TRUE)
头文件就不再发了,在上一章中。
其中使用到了环形缓冲区,具体实现可以到我的另一篇博文中找到。还使用了uCOS-II嵌入式操作系统提供的互斥型信号量以及信号量来保证不同任务对SCI口缓冲区的访问不发生冲突。每个SCI口都会对应一个接收以及一个发送缓冲区,对应的大小可以在.h文件中配置。
这个驱动的主要作用就是为每个SCI口提供缓冲区,一方面,SCI模块会不断的从发送缓冲区内获取字符并发送,另一方面,它会把接收到的字符不断放入接收缓冲区,这样所有经过SCI口的字节流都经过缓冲,有效缓解了处理不及时等现象。提供的函数也是围绕缓冲区的。
首先使用这个模块前一定要先调用SCI_BufferInit函数来进行初始化。
而由于一般来说一个SCI口只会有一个任务来接收SCI口的字节流,没有竞争的问题,所以只提供了SCI_GetCharB函数来监听SCI口(和硬件驱动提供的SCI_GetChar相比多了一个B,即Buffer)。一般来说会专门开个任务阻塞地监听这个信道,类似这样:
static void SCI0ListenTask (void *p_arg){ INT8U c,err; …… while(true) { c = SCI_GetCharB(SCI0,RX_MAX_TIME_INTERVAL,&err); //从SCI0获得一个字符,最大等待RX_MAX_TIME_INTERVAL次TICK。 if( err == SCI_RX_TIMEOUT ){ //超时导致的返回 …… // 超时的处理 continue; } // 正常获得字符后的处理 …… }}
而对于发送,因为有不同任务同时想用一个SCI口发送的问题,所以提供了互斥的方法,即SCI_PutCharB_Mutex和SCI_PutCharsB_Mutex,只要保证所有地方都使用这些互斥的方法发送,就可以保证不同任务间的发送互不干扰。
比如:
任务一发送:abcde\r 任务二发送:12345\r
如果不使用互斥/独占的方法发送的话(比如直接调用硬件驱动提供的函数),由于任务调度的原因,可能最后另外一头收到的就成了:abc12de\r345\r了。
而如果使用互斥的方法的话,另一头就能保证收到的是 abcde\r12345\r
另外,还提供的等价的互斥发送方法:SCI_SendBuf_hold、SCI_PutCharB、SCI_PutCharsB和SCI_SendBuf_release,他们需要成套使用,先用hold获取发送权,然后发送字节,最后释放发送权。这样就能保证在hold和release之间发送的字节的连续性了。
就讲到这里把,有什么建议或意见请留言。
更改历史:
2017/10/29 更新到 V2.1 支持了所有的SCI口。
- MC9S12XEP100 SCI(UART)驱动程序2
- MC9S12XEP100 SCI(UART)驱动程序
- MC9S12XEP100 ATD模块 驱动程序
- SCI、UART与RS232区别
- SCI、UART与RS232区别
- UART驱动程序设计
- SCI,SPI,UART三种串行总线协议的区别
- Linux串口(serial、uart)驱动程序设计
- Linux串口(serial、uart)驱动程序设计
- Linux串口(serial、uart)驱动程序设计
- Linux串口(serial、uart)驱动程序设计
- Linux串口(serial、uart)驱动程序设计
- Linux串口(serial、uart)驱动程序设计
- Linux串口(serial、uart)驱动程序设计
- Linux串口(serial、uart)驱动程序设计
- Linux串口(serial、uart)驱动程序设计
- Linux串口(serial、uart)驱动程序设计
- Linux串口(serial、uart)驱动程序设计
- Server IPC version 9 cannot communicate with client version 4
- mysql可扩展性
- 端口分类调研
- 多线程经常使用的3个关键字:synchronized、ReentrantLock、volatile
- 31 《象与骑象人:幸福的假设》 -豆瓣评分8.4
- MC9S12XEP100 SCI(UART)驱动程序2
- Eclipse的操作技巧
- vs2015单元测试总结——3种方法可用
- UVa 563
- SQL Server 2008如何开启数据库的远程连接
- 在《JavaScript高级程序设计》的一些笔记
- 字符串面试题
- app自动化测试5---定位元素方法
- 【旧资料整理】解决firefox3迅雷插件右键查看页面源代码无效问题