[嵌入式开发模块]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 例行优化

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值