[嵌入式開發模組]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 例行優化