1. 程式人生 > >[嵌入式開發模組]MC9S12XEP100 SCI(UART)驅動程式

[嵌入式開發模組]MC9S12XEP100 SCI(UART)驅動程式

忙著畢設,很久沒有寫文章了,終於答辯完了,得了個校優秀畢業設計。畢設做的是個智慧介面模組,用一週時間入門了MC9S12XEP100的開發,又用一週時間入門了uC/OS-II嵌入式作業系統,在做畢設的過程中學到了很多,現在把一些工具發上來分享。

首先先發個自己封裝的MC9S12XEP100的SCI模組(也就是UART模組)的驅動。這些程式碼參考了 Li Yuan http://blog.csdn.net/liyuanbhu/article/details/7764851 的程式碼,整個程式碼風格是按照uCOS-II作業系統原始碼的風格來寫的,在此表示感謝。
目前還不是特別完整完善,但基本使用是沒有問題了。
首先是.h檔案,除了硬體驅動程式,還有在基於uCOS-II作業系統的SCI驅動程式,這章先講硬體驅動部分

/*
*******************************************************************************************
*
*
*                    SCI(Serial Communication Interface) SUPPORT PACKAGE
*                                   Freescale MC9S12XEP100
*                           飛思卡爾   MC9S12XEP100  SCI支援包
*
* File : SCI_def.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2018/02/23
* version: V2.2
* History: 2017/04/24  V1.0  the prototype of SCI_uCOS,only support SCI0 and SCI1
*          2017/07/20  V2.0  a. update the module to support the SCI0 to SCI7
*                            b. expend the configure option for all SCI port
*                            c. add SCI_SEND_MULTIBYTE_EN option to ignore SCI_PutLong() and SCI_PutShort()
*                            d. add many marco error check
*          2017/10/27  V2.1  fix a bug in SCI_uCos.c
*          2018/02/23  V2.2  a. optimize the struct referencing to the register
*                            b. delete some configuration marco, because the unused function will not be linked
*                               in the project, so there is no need to hide the function.
*                            c. add more error check.
*                            d. add a marco(SCI_ARGUMENT_CHECK_EN) to turn off argument check for saving code.
*                            e. add the support for define buffer in paged addressing area.
*                            f. use semaphore in replace of the origional mutex, so the user don't need to take
*                               care of the priority thing. The cost is the possibility of priority inversion.
*                               But I think it's worth it.
* NOTE(s):a.refer to Li Yuan's  (http://blog.csdn.net/liyuanbhu/article/details/7764851)
*                      and 
*                  uCOS-II's Code
*         b.記得把SCI_uCOS.s中的SCIx_RxTxISR中斷服務程式指向對應的中斷向量地址
*                  this SCI PACKAGE include files —— SCI_def.h, SCI.c, SCI_uCos.c, SCI_uCos.s
*                  這個SCI 開發包有以下檔案:SCI_def.h,SCI.c,SCI_uCos.c, SCI_uCos.s
*         c.記得把SCI_uCOS.s中不用的埠的中斷服務程式刪掉,因為彙編程式就算不使用,編譯器也不會自動幫忙優化掉。
*********************************************************************************************
*/
#ifndef SCI_DEF_H #define SCI_DEF_H /* ******************************************************************************************** * MISCELLANEOUS ******************************************************************************************** */ #ifndef FALSE #define FALSE 0
#endif #ifndef TRUE #define TRUE 1 #endif /* ******************************************************************************************* * MAIN CONFIGURE 主配置 ******************************************************************************************* */ #define SCI_MODULE_ENABLE TRUE /* TRUE: 啟用SCI驅動模組 */ #define SCI_UCOS_MODULE_ENABLE TRUE /* TRUE: 啟用基於uCOS-II的SCI驅動 */ /* ******************************************************************************************* * INCLUDES ******************************************************************************************* */ #include <MC9S12XEP100.h> #if(SCI_UCOS_MODULE_ENABLE == TRUE) #include <ucos_ii.h> #endif /* ****************************************************************************************** * CONSTANT ****************************************************************************************** */ #define SCI0 0x00 /* SCI0 */ #define SCI1 0x01 /* SCI1 */ #define SCI2 0x02 /* SCI2 */ #define SCI3 0x03 /* SCI3 */ #define SCI4 0x04 /* SCI4 */ #define SCI5 0x05 /* SCI5 */ #define SCI6 0x06 /* SCI6 */ #define SCI7 0x07 /* SCI7 */ // PARITY BIT #define SCI_PARITY_NO 0 #define SCI_PARITY_EVEN 1 #define SCI_PARITY_ODD 2 // ENDIAN #define SCI_ENDIAN_LITTLE 0 #define SCI_ENDIAN_BIG 1 /* **************************************************************************************** * ERROR CODES **************************************************************************************** */ #define SCI_NO_ERR 0 /* Function call was successful */ #define SCI_BAD_CH 1 /* Invalid communications port channel */ #define SCI_RX_EMPTY 2 /* Rx buffer is empty, no character available */ #define SCI_TX_FULL 3 /* Tx buffer is full, could not deposit character */ #define SCI_TX_EMPTY 4 /* If the Tx buffer is empty. */ #define SCI_RX_TIMEOUT 5 /* If a timeout occurred while waiting for a character*/ #define SCI_TX_TIMEOUT 6 /* If a timeout occurred while waiting to send a char.*/ #define SCI_PEND_ISR 7 #define SCI_PEND_LOCKED 8 /* If you called this function when the scheduler is locked*/ //#define SCI_PARITY_NONE 0 /* Defines for setting parity */ #define SCI_ERR_UNKNOWN 9 /* ****************************************************************************************** * TYPE DEFINITION ****************************************************************************************** */ // struct of SCI register typedef struct{ SCI0BDSTR BD; SCI0ACR2STR CR1; SCI0CR2STR CR2; SCI0SR1STR SR1; SCI0SR2STR SR2; SCI0DRHSTR DRH; SCI0DRLSTR DRL; } SCISTR,*pSCISTR; #define SCIBD(i) (pSCI(i)->BD.Word) #define SCICR1(i) (pSCI(i)->CR1.Byte) #define SCICR2(i) (pSCI(i)->CR2.Byte) #define SCISR1(i) (pSCI(i)->SR1.Byte) #define SCISR2(i) (pSCI(i)->SR2.Byte) #define SCIDRH(i) (pSCI(i)->DRH.Byte) #define SCIDRL(i) (pSCI(i)->DRL.Byte) /* ****************************************************************************************** * REGISTER VARIABLE DECLARATION(INTERNAL USE) ****************************************************************************************** */ // Map to SCI register extern pSCISTR const Ptr_SCI[]; #define SCI_CNT 8 #define pSCI(port) (Ptr_SCI[port]) /* ****************************************************************************************** * Configure 配置 ****************************************************************************************** */ #define SCI_ARGUMENT_CHECK_EN TRUE // TRUE: arguments will be checked, however,this will // cause a little code volume. /************ 硬體驅動 **************/ #define SCI_INIT_DYNAMIC FALSE /* (TRUE):include function for dynamic Initialize SCI:... ...SCI_Init(unsigned char port, unsigned long baudRate, unsigned long busClk)... ...(FALSE):include function:void SCI_Init(unsigned char port), ... ... use the argument below to initialize SCI*/ /* The argument to initialize SCI when SCI_INIT_DYNAMIC == FALSE ... ... 當SCI_INIT_DYNAMIC為FALSE時直接使用以下引數初始化SCI*/ #if(SCI_INIT_DYNAMIC != TRUE) #define SCI_BAUDRATE 9600 #define SCI_BUSCLK 32000000L #define SCI_DATABIT 8 /*Data bits, 8 or 9; 資料位,8 或9位*/ #define SCI_PARITY SCI_PARITY_NO /*SCI_PARITY_NO for disable Parity,SCI_PARITY_EVEN... for Even Parity, SCI_ODD_PARITY for Odd Parity; SCI_PARITY_NO 靜止奇偶校驗,SCI_PARITY_EVEN 啟用奇校驗,... ... SCI_PARITY_ODD 啟用偶校驗*/ #endif // of (SCI_INIT_DYNAMIC != TRUE) #define SCI_SEND_ENDIANNESS SCI_ENDIAN_BIG /* the endianness when send mult-byte type; (see SCI_ENDIAN_XXX) 設定傳送多位元組型別時使用的位元組序*/ /************ RTOS驅動 **************/ #define SCI_RX_BUFFER_SIZE 25 /* Number of characters in Rx ring buffer by default */ #define SCI_TX_BUFFER_SIZE 25 /* Number of characters in Tx ring buffer by default */ #define SCI0_UCOS_CODE_EN TRUE /* (TRUE):include codes for SCI0;(TRUE):包含SCI0的程式碼 */ #define SCI0_RX_BUFFER_SIZE SCI_RX_BUFFER_SIZE /* the size of receive buffer for SCI0; 0: turn off receive buffer for SCI0; SCI0的接收緩衝區大小; 0表示SCI0不使用接收緩衝區 */ #define SCI0_TX_BUFFER_SIZE SCI_TX_BUFFER_SIZE /* the size of transmit buffer for SCI0; 0: turn off transmit buffer for SCI0; SCI0的傳送緩衝區大小; 0表示SCI0不使用傳送緩衝區 */ #define SCI1_UCOS_CODE_EN TRUE /* (TRUE):include codes for SCI1;(TRUE):包含SCI1的程式碼 */ #define SCI1_RX_BUFFER_SIZE SCI_RX_BUFFER_SIZE /* the size of receive buffer for SCI1; 0: turn off receive buffer for SCI1; SCI1的接收緩衝區大小; 0表示SCI1不使用接收緩衝區 */ #define SCI1_TX_BUFFER_SIZE SCI_TX_BUFFER_SIZE /* the size of transmit buffer for SCI1; 0: turn off transmit buffer for SCI1; SCI1的傳送緩衝區大小; 0表示SCI1不使用傳送緩衝區 */ #define SCI2_UCOS_CODE_EN FALSE /* (TRUE):include codes for SCI2;(TRUE):包含SCI2的程式碼 */ #define SCI2_RX_BUFFER_SIZE SCI_RX_BUFFER_SIZE /* the size of receive buffer for SCI2; 0: turn off receive buffer for SCI2; SCI2的接收緩衝區大小; 0表示SCI2不使用接收緩衝區 */ #define SCI2_TX_BUFFER_SIZE SCI_TX_BUFFER_SIZE /* the size of transmit buffer for SCI2; 0: turn off transmit buffer for SCI2; SCI2的傳送緩衝區大小; 0表示SCI2不使用傳送緩衝區 */ #define SCI3_UCOS_CODE_EN FALSE /* (TRUE):include codes for SCI3;(TRUE):包含SCI3的程式碼 */ #define SCI3_RX_BUFFER_SIZE SCI_RX_BUFFER_SIZE /* the size of receive buffer for SCI3; 0: turn off receive buffer for SCI3; SCI3的接收緩衝區大小; 0表示SCI3不使用接收緩衝區 */ #define SCI3_TX_BUFFER_SIZE SCI_TX_BUFFER_SIZE /* the size of transmit buffer for SCI3; 0: turn off transmit buffer for SCI3; SCI3的傳送緩衝區大小; 0表示SCI3不使用傳送緩衝區 */ #define SCI4_UCOS_CODE_EN FALSE /* (TRUE):include codes for SCI4;(TRUE):包含SCI4的程式碼 */ #define SCI4_RX_BUFFER_SIZE SCI_RX_BUFFER_SIZE /* the size of receive buffer for SCI4; 0: turn off receive buffer for SCI4; SCI4的接收緩衝區大小; 0表示SCI4不使用接收緩衝區 */ #define SCI4_TX_BUFFER_SIZE SCI_TX_BUFFER_SIZE /* the size of transmit buffer for SCI4; 0: turn off transmit buffer for SCI4; SCI4的傳送緩衝區大小; 0表示SCI4不使用傳送緩衝區 */ #define SCI5_UCOS_CODE_EN FALSE /* (TRUE):include codes for SCI5;(TRUE):包含SCI5的程式碼 */ #define SCI5_RX_BUFFER_SIZE SCI_RX_BUFFER_SIZE /* the size of receive buffer for SCI5; 0: turn off receive buffer for SCI5; SCI5的接收緩衝區大小; 0表示SCI5不使用接收緩衝區 */ #define SCI5_TX_BUFFER_SIZE SCI_TX_BUFFER_SIZE /* the size of transmit buffer for SCI5; 0: turn off transmit buffer for SCI5; SCI5的傳送緩衝區大小; 0表示SCI5不使用傳送緩衝區 */ #define SCI6_UCOS_CODE_EN FALSE /* (TRUE):include codes for SCI6;(TRUE):包含SCI6的程式碼 */ #define SCI6_RX_BUFFER_SIZE SCI_RX_BUFFER_SIZE /* the size of receive buffer for SCI6; 0: turn off receive buffer for SCI6; SCI6的接收緩衝區大小; 0表示SCI6不使用接收緩衝區 */ #define SCI6_TX_BUFFER_SIZE SCI_TX_BUFFER_SIZE /* the size of transmit buffer for SCI6; 0: turn off transmit buffer for SCI6; SCI6的傳送緩衝區大小; 0表示SCI6不使用傳送緩衝區 */ #define SCI7_UCOS_CODE_EN FALSE /* (TRUE):include codes for SCI7;(TRUE):包含SCI7的程式碼 */ #define SCI7_RX_BUFFER_SIZE SCI_RX_BUFFER_SIZE /* the size of receive buffer for SCI7; 0: turn off receive buffer for SCI7; SCI7的接收緩衝區大小; 0表示SCI7不使用接收緩衝區 */ #define SCI7_TX_BUFFER_SIZE SCI_TX_BUFFER_SIZE /* the size of transmit buffer for SCI7; 0: turn off transmit buffer for SCI7; SCI7的傳送緩衝區大小; 0表示SCI7不使用傳送緩衝區 */ /* ************************************************************************************ * FUNCTION PROTOTYPES 函式原型 ************************************************************************************ */ /************ 硬體驅動 **************/ #if(SCI_INIT_DYNAMIC == TRUE) void SCI_Init(unsigned char port, unsigned long baudRate, unsigned long busClk, unsigned char databits,unsigned char parity); #else void SCI_Init(unsigned char port); #endif // of SCI_INIT_DYNAMIC == TRUE void SCI_EnableTxInt(unsigned char port); void SCI_DisableTxInt(unsigned char port); void SCI_EnableRxInt(unsigned char port); void SCI_DisableRxInt(unsigned char port); void SCI_EnableRecv(unsigned char port); void SCI_DisableRecv(unsigned char port); void SCI_EnableTrans(unsigned char port); void SCI_DisableTrans(unsigned char port); void SCI_PutChar( unsigned char port, unsigned char c); unsigned char SCI_GetChar(unsigned char port); void SCI_PutShort (unsigned char port, short i); void SCI_PutLong (unsigned char port, unsigned long i); /************ RTOS驅動 **************/ void SCI_BufferInit (void); INT8U SCI_GetCharB (INT8U port, INT16U timeout, INT8U *err); INT8U SCI_PutCharB_Mutex (INT8U port, INT8U c, INT16U timeout); INT8U SCI_PutCharsB_Mutex (INT8U port, const INT8U *buf,INT16U length, INT16U timeout); #define SCI_PutStringB_Mutex(port,pStr,timeout) SCI_PutCharsB_Mutex(port,str,strlen(str),timeout) void SCI_SendBuf_hold (INT8U port, INT16U timeout, INT8U *perr); INT8U SCI_PutCharB (INT8U port, INT8U c, INT16U timeout); INT8U SCI_PutCharsB(INT8U port, const INT8U *buf,INT16U length, INT16U timeout); #define SCI_PutStringB(port,pStr,timeout) SCI_PutCharsB(port,str,strlen(str),timeout) void SCI_SendBuf_release(INT8U port); INT8U SCI_RxBufferIsEmpty (INT8U port); INT8U SCI_TxBufferIsFull (INT8U port); /* ************************************************************************************ * ERROR CHECK 錯誤檢查 ************************************************************************************ */ #ifndef SCI_MODULE_ENABLE #error "SCI_MODULE_ENABLE must be defined." #endif #ifndef SCI_UCOS_MODULE_ENABLE #error "SCI_UCOS_MODULE_ENABLE must be defined." #endif #if(SCI_UCOS_MODULE_ENABLE == TRUE) #if( SCI_RX_BUFFER_SIZE < 0 || SCI_RX_BUFFER_SIZE >= 65536 || SCI0_RX_BUFFER_SIZE < 0 || SCI0_RX_BUFFER_SIZE >= 65536 \ || SCI1_RX_BUFFER_SIZE < 0 || SCI1_RX_BUFFER_SIZE >= 65536 || SCI2_RX_BUFFER_SIZE < 0 || SCI2_RX_BUFFER_SIZE >= 65536 \ || SCI3_RX_BUFFER_SIZE < 0 || SCI3_RX_BUFFER_SIZE >= 65536 || SCI4_RX_BUFFER_SIZE < 0 || SCI4_RX_BUFFER_SIZE >= 65536 \ || SCI5_RX_BUFFER_SIZE < 0 || SCI5_RX_BUFFER_SIZE >= 65536 || SCI6_RX_BUFFER_SIZE < 0 || SCI6_RX_BUFFER_SIZE >= 65536 \ || SCI7_RX_BUFFER_SIZE < 0 || SCI7_RX_BUFFER_SIZE >= 65536) #error "SCI buffer size must between 0 and 65535" #endif #if( SCI_TX_BUFFER_SIZE < 0 || SCI_TX_BUFFER_SIZE >= 65536 || SCI0_TX_BUFFER_SIZE < 0 || SCI0_TX_BUFFER_SIZE >= 65536 \ || SCI1_TX_BUFFER_SIZE < 0 || SCI1_TX_BUFFER_SIZE >= 65536 || SCI2_TX_BUFFER_SIZE < 0 || SCI2_TX_BUFFER_SIZE >= 65536 \ || SCI3_TX_BUFFER_SIZE < 0 || SCI3_TX_BUFFER_SIZE >= 65536 || SCI4_TX_BUFFER_SIZE < 0 || SCI4_TX_BUFFER_SIZE >= 65536 \ || SCI5_TX_BUFFER_SIZE < 0 || SCI5_TX_BUFFER_SIZE >= 65536 || SCI6_TX_BUFFER_SIZE < 0 || SCI6_TX_BUFFER_SIZE >= 65536 \ || SCI7_TX_BUFFER_SIZE < 0 || SCI7_TX_BUFFER_SIZE >= 65536) #error "SCI buffer size must between 0 and 65535" #endif #if(SCI0_UCOS_CODE_EN != TRUE) #undef SCI0_RX_BUFFER_SIZE #undef SCI0_TX_BUFFER_SIZE #define SCI0_RX_BUFFER_SIZE 0 #define SCI0_TX_BUFFER_SIZE 0 #endif #if(SCI1_UCOS_CODE_EN != TRUE) #undef SCI1_RX_BUFFER_SIZE #undef SCI1_TX_BUFFER_SIZE #define SCI1_RX_BUFFER_SIZE 0 #define SCI1_TX_BUFFER_SIZE 0 #endif #if(SCI2_UCOS_CODE_EN != TRUE) #undef SCI2_RX_BUFFER_SIZE #undef SCI2_TX_BUFFER_SIZE #define SCI2_RX_BUFFER_SIZE 0 #define SCI2_TX_BUFFER_SIZE 0 #endif #if(SCI3_UCOS_CODE_EN != TRUE) #undef SCI3_RX_BUFFER_SIZE #undef SCI3_TX_BUFFER_SIZE #define SCI3_RX_BUFFER_SIZE 0 #define SCI3_TX_BUFFER_SIZE 0 #endif #if(SCI4_UCOS_CODE_EN != TRUE) #undef SCI4_RX_BUFFER_SIZE #undef SCI4_TX_BUFFER_SIZE #define SCI4_RX_BUFFER_SIZE 0 #define SCI4_TX_BUFFER_SIZE 0 #endif #if(SCI5_UCOS_CODE_EN != TRUE) #undef SCI5_RX_BUFFER_SIZE #undef SCI5_TX_BUFFER_SIZE #define SCI5_RX_BUFFER_SIZE 0 #define SCI5_TX_BUFFER_SIZE 0 #endif #if(SCI6_UCOS_CODE_EN != TRUE) #undef SCI6_RX_BUFFER_SIZE #undef SCI6_TX_BUFFER_SIZE #define SCI6_RX_BUFFER_SIZE 0 #define SCI6_TX_BUFFER_SIZE 0 #endif #if(SCI7_UCOS_CODE_EN != TRUE) #undef SCI7_RX_BUFFER_SIZE #undef SCI7_TX_BUFFER_SIZE #define SCI7_RX_BUFFER_SIZE 0 #define SCI7_TX_BUFFER_SIZE 0 #endif #endif // of SCI_UCOS_MODULE_ENABLE == TRUE #endif // of SCI_DEF_H

這個.h檔案中包含了硬體驅動與uCOS的驅動的定義。巨集定義了SCI0-7(MC9S12XEP100有8個SCI口),在剩下的程式中名為port的引數需要傳的就是這個巨集定義的名稱。然後還定義了對映暫存器的陣列以及對應的巨集等,這樣可以很方便的直接訪問任意埠的暫存器。
如果不想編譯SCI相關程式碼,則把#define SCI_MODULE_ENABLE 後面改為FALSE就行。如果不使用uCOS的驅動,則把SCI_UCOS_MODULE_ENABLE 後面改為FALSE(這章只說硬體驅動部分,所以直接改為了FALSE)。SCI0_CODE_INCLUDE和SCI1_CODE_INCLUDE只用於基於uCOS的驅動程式碼。
配置部分應該已經註釋的很清楚了,就是一些裁剪程式碼的功能,其中SCI_INIT_DYNAMIC 這個巨集決定了方法SCI_Init()是要使用固定的值初始化埠還是使用可變的值(多很多輸入引數)來初始化,這根據需求決定。還有個傳送多位元組時的位元組序選擇。
而函式宣告部分沒有註釋,因為註釋都寫在函式實現部分的前面了,以下是SCI硬體驅動模組.c檔案。

/*
*********************************************************************************************************
*
*
*                    SCI(Serial Communication Interface) SUPPORT PACKAGE
*                                         Freescale MC9S12XEP100
*                               飛思卡爾   MC9S12XEP100  SCI支援包
*
* File : SCI.c
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date : 2018/02/23
* version: V2.2
* History: 2017/04/24  V1.0   the prototype of SCI_uCOS,only support SCI0 and SCI1
*          2017/10/27  V2.1   modify some #pragma statement
*          2018/02/23  V2.2   a.optimize the struct referencing to the register
*                             b.add argument check
* NOTE(s): refer to Li Yuan's  (http://blog.csdn.net/liyuanbhu/article/details/7764851)
*                    and 
*                  uCOS-II's Code
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                          INCLUDES
*********************************************************************************************************
*/

#include "SCI_def.h"
#if(SCI_MODULE_ENABLE == TRUE)

/*
*********************************************************************************************************
*                                LOCAL FUNCTION DECLARATION
*********************************************************************************************************
*/

#if(SCI_ARGUMENT_CHECK_EN == TRUE)
  #define argCheck(arg,ceil)           if((arg) >= (ceil)) return;
  #define argCheck2(arg,ceil,rVal)     if((arg) >= (ceil)) return (rVal);
#else
  #define argCheck(arg,ceil)
  #define argCheck2(arg,ceil,rVal)
#endif // of (SPI_ARGUMENT_CHECK_EN == TRUE)
#define portCheck()       argCheck(port,SCI_CNT)
#define portCheck2(rVal)  argCheck2(port,SCI_CNT,rVal)

/*
*********************************************************************************************************
*                                 REGISTER VARIABLE DEFINITION
*********************************************************************************************************
*/

pSCISTR const Ptr_SCI[] = {(pSCISTR)&_SCI0BD,(pSCISTR)&_SCI1BD,(pSCISTR)&_SCI2BD,(pSCISTR)&_SCI3BD \
       ,(pSCISTR)&_SCI4BD,(pSCISTR)&_SCI5BD,(pSCISTR)&_SCI6BD,(pSCISTR)&_SCI7BD};

/*
*********************************************************************************************************
*                                        SCI_Init()
*
* Description : Initialize SCI support hardware.  初始化SCI硬體
*
* Arguments   : port               SCI0-SCI7 the port to Initialize;       選擇要初始化的埠;
*                       baudRate       baudRate to set;                               要設定的波特率;
*                       busClk           the current bus clock;                       當前的匯流排時鐘頻率;
*                       databits          Data bits,  8 or 9;                         資料位,8 或9位;
*                       parity             SCI_PARITY_NO for disable Parity,SCI_PARITY_EVEN for Even Parity, ...
*                                              ... SCI_ODD_PARITY for Odd Parity;
*                                             SCI_PARITY_NO禁用奇偶校驗, SCI_PARITY_EVEN啟用奇校驗, ...
*                                              ... SCI_ODD_PARITY啟用偶校驗;
*Note(s):  1.this function is availible only when SCI_INIT_DYNAMIC == TRUE
*               2. this will disable all function accosiated with transmit and receive.
*                        使用這個函式會禁能對應SCI口的傳送接收相關功能(傳送(中斷)使能,接收(中斷)使能)
*********************************************************************************************************
*/

#if(SCI_INIT_DYNAMIC == TRUE)
     void SCI_Init(unsigned char port, unsigned long baudRate, unsigned long busClk,
                unsigned char databits,unsigned char parity)
{
     portCheck();
     // 用baudRate臨時儲存最終賦予BD暫存器的值
     baudRate = ( busClk >> 4) /baudRate;    // SCI0BD = BUS_CLOCK/16/BAUD
     baudRate &= 0x1FFF;
     // 用databits 臨時儲存最終賦予CR1暫存器的值
     databits =  (databits > 8 ) << 4;                                                // M
     if(parity > SCI_PARITY_NO) {                                               // PE = 1
          if(parity>SCI_PARITY_EVEN) {
               databits |= 0x02;                                                            // PT = 0
          }else{
               databits |= 0x03;                                                            // PT = 1
          }
     }
     SCICR2(port) = 0x00;
     SCIBD(port) = (word)baudRate;
     SCICR1(port) = databits;
}
#else
/*
*********************************************************************************************************
*                                        SCI_Init()
*
* Description : Initialize SCI support hardware.  初始化SCI硬體
*
* Arguments   : port               SCI0-SCI7 the port to Initialize;       選擇要初始化的埠;
*
*Note(s):  1.this function is availible only when SCI_INIT_DYNAMIC == FALSE;
*               2.will use the SCI_BAUDRATE & SCI_BUSCLK & SCI_DATABIT & SCI_PARITY to Initialize SCI;
*               3. this will disable all function accosiated with transmit and receive.
*                        使用這個函式會禁能對應SCI口的傳送接收相關功能(傳送(中斷)使能,接收(中斷)使能)
*********************************************************************************************************
*/
void SCI_Init(unsigned char port){
  portCheck();
  SCICR2(port) = 0x00;
  SCIBD(port) = SCI_BUSCLK/16/SCI_BAUDRATE & 0x1FFF; 
  SCICR1(port) = 0x00
#if(SCI_DATABIT >8) 
  |SCI0CR1_M_MASK
#endif
#if(SCI_PARITY == 0)

#elif (SCI_PARITY > 1)
  |SCI0CR1_PE_MASK
#else
  |SCI0CR1_PE_MASK|SCI0CR1_PT_MASK
#endif
  ;
}

#endif


/*
*********************************************************************************************************
*                                        SCI_EnableTxInt()
*
* Description : Enable Tx interrupt(Transmitter Interrupt Enable Bit)   使能傳輸中斷
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
*
* Note: 
*********************************************************************************************************
*/

void SCI_EnableTxInt(unsigned char port){
  portCheck();
  SCICR2(port) |= SCI0CR2_TIE_MASK;
}

 /*
*********************************************************************************************************
*                                        SCI_EnableRxInt()
*
* Description : Enable Rx interrupt(Receiver Interrupt Enable Bit)   使能接收中斷
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
*
* Note: 
*********************************************************************************************************
*/

void SCI_EnableRxInt(unsigned char port){
  portCheck();
  SCICR2(port) |= SCI0CR2_RIE_MASK;
}
 /*
*********************************************************************************************************
*                                        SCI_EnableRecv()
*
* Description : Enable SCI Receiver    使能接收
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
*
* Note: 
*********************************************************************************************************
*/
void SCI_EnableRecv(unsigned char port){
  portCheck();
  SCICR2(port) |= SCI0CR2_RE_MASK;
}

/*
*********************************************************************************************************
*                                        SCI_EnableTrans()
*
* Description : Enable SCI Transmitter    使能傳送
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
*
* Note: 
*********************************************************************************************************
*/
void SCI_EnableTrans(unsigned char port){
  portCheck();
  SCICR2(port) |= SCI0CR2_TE_MASK;
}


 /*
*********************************************************************************************************
*                                        SCI_DisableTxInt()
*
* Description : Disable The Tx interrupt  (Transmitter Interrupt Enable Bit)     禁能傳送
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
*
* Note: 
*********************************************************************************************************
*/

void SCI_DisableTxInt(unsigned char port){
  portCheck();
  SCICR2(port) &= ~(byte)SCI0CR2_TIE_MASK;
}

/*
*********************************************************************************************************
*                                        SCI_DisableRxInt()
*
* Description : Disable The Rx interrupt  (Receiver Interrupt Enable Bit)     禁能接收中斷
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
*
* Note: 
*********************************************************************************************************
*/
void SCI_DisableRxInt(unsigned char port) {
  portCheck();
  SCICR2(port) &= ~(byte)SCI0CR2_RIE_MASK;
}

/*
*********************************************************************************************************
*                                        SCI_DisableTrans()
*
* Description : Disable SCI Transmitter    禁能傳送
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
*
* Note: 
*********************************************************************************************************
*/
void SCI_DisableTrans(unsigned char port) {
  portCheck();
  SCICR2(port) &= ~(byte)SCI0CR2_TE_MASK;
}
/*
*********************************************************************************************************
*                                        SCI_DisableRecv()
*
* Description : Disable SCI Receiver    禁能接收
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
*
* Note: 
*********************************************************************************************************
*/
void SCI_DisableRecv(unsigned char port) {
  portCheck();
  SCICR2(port) &= ~(byte)SCI0CR2_RE_MASK;
}

/*
*********************************************************************************************************
*                                        SCI_PutChar()
*
* Description : Transmit one char    傳送一個字元/位元組
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
*                       c                    the char to transmit;                        要傳送的字元;                   
* Note:   1. this function will block until transmiter idle and transmit the char;
*              這個函式會阻塞到傳送器空閒,然後傳送字元
*             2. not implement bit 9
*********************************************************************************************************
*/

void SCI_PutChar( unsigned char port, unsigned char c) {
  portCheck();
  while((SCISR1(port) & SCI0SR1_TDRE_MASK) == 0);    // 等待發送暫存器為空
  SCIDRL(port) = c;
}

/*
*********************************************************************************************************
*                                        SCI_GetChar()
*
* Description : Receive one char    接收一個字元/位元組
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
*                       
* Return       : 0                 invalid port or the char received is 0.
*                others            the char received;                             接收到的字元;          
* Note:   1.this function will block until receiver get a char,and return the char;
*              這個函式會阻塞到接收器暫存器滿,然後返回字元
*         2. not implement bit 9
*********************************************************************************************************
*/

unsigned char SCI_GetChar(unsigned char port){
  portCheck2(0);
  while((SCISR1(port) & SCI0SR1_RDRF_MASK) == 0);    // 等待接收暫存器滿
  return SCIDRL(port);
}

/*
*********************************************************************************************************
*                                        SCI_PutShort()
*
* Description : Transmit one short int.    傳送一個短整型
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
* 
* Return       :                        the char received;                             接收到的字元;          
* Note:   1. this function will block until transmiter idle and transmit the char;
*              這個函式會阻塞到傳送器空閒,然後傳送字元
*********************************************************************************************************
*/

void SCI_PutShort (unsigned char port, short i)  
{
  char * p = (char *)&i;
  portCheck();
#if(SCI_SEND_ENDIANNESS == SCI_ENDIAN_BIG)
  SCI_PutChar( port, p[0]);  
  SCI_PutChar( port, p[1]);  
#endif
#if(SCI_SEND_ENDIANNESS == SCI_ENDIAN_LITTLE)
  SCI_PutChar( port, p[1]);  
  SCI_PutChar( port, p[0]);  
#endif
}
/*
*********************************************************************************************************
*                                        SCI_PutLong()
*
* Description : Transmit one long int.    傳送一個長整型
*
* Arguments   : port               SCI0-SCI7 the port to Choose;       選擇埠;
* 
* Return       :                        the char received;                             接收到的字元;          
* Note:   1. this function will block until transmiter idle and transmit the char;
*              這個函式會阻塞到傳送器空閒,然後傳送字元
*********************************************************************************************************
*/
void SCI_PutLong (unsigned char port, unsigned long i){
  char * p = (char *)&i;  
  portCheck();
#if(SCI_SEND_ENDIANNESS == SCI_ENDIAN_BIG)
    SCI_PutChar( port, p[0]);  
    SCI_PutChar( port, p[1]);  
    SCI_PutChar( port, p[2]);  
    SCI_PutChar( port, p[3]);  
#endif
#if(SCI_SEND_ENDIANNESS == SCI_ENDIAN_LITTLE)
    SCI_PutChar( port, p[3]);  
    SCI_PutChar( port, p[2]);  
    SCI_PutChar( port, p[1]);  
    SCI_PutChar( port, p[0]);  
#endif
}

#endif  // of SCI_MODULE_ENABLE == TRUE

硬體驅動並沒有完整實現SCI模組的全部功能,比如目前實際上資料位只能是8位,因為傳送和接收函式都不支援第9位;而且那些LOOPS,等待模式之類的也沒有封裝,主要是因為目前用不到。
硬體驅動實現了所有8個SCI口的驅動。然後是示例:

#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */
#include "SCI_def.h"

#define  BUS_CLOCK         32000000    //匯流排頻率
#define  OSC_CLOCK         16000000    //晶振頻率

/*************************************************************/
/*                      初始化鎖相環                         */
/*************************************************************/
void INIT_PLL(void) 
{
    CLKSEL &= 0x7f;       //設定OSCCLK作為系統時鐘
    PLLCTL &= 0x8F;       //禁止鎖相環

    #if(BUS_CLOCK == 32000000)
      SYNR = 0x43;     
   #endif 

    REFDV = 0x81;
    PLLCTL |=0x70;  //使能鎖相環
    asm NOP;
    asm NOP;
    while(!(CRGFLG&0x08)); //PLLCLK鎖定
    CLKSEL |= 0x80;        //設定PLLCLK為系統時鐘
}

void main(void) {
    unsigned char c;
    // 設定匯流排頻率為32MHz
    DisableInterrupts;
    INIT_PLL();
    EnableInterrupts;
    SCI_Init(SCI0,9600,BUS_CLOCK,8,SCI_PARITY_NO);
    SCI_EnableRecv(SCI0);  
    SCI_EnableTrans(SCI0);  
    // 每接收一個字元就返回0x33和那個字元
    for(;;) {
        c = SCI_GetChar(SCI0);
        SCI_PutShort(SCI0,c | 0x3300);
     } 
}

通訊測試

然後下一章來講基於uCOS的SCI驅動。

更改歷史:

2017/10/29 更新到 V2.1
2018/02/24 更新到 V2.2 例行優化