忙着毕设,很久没有写文章了,终于答辩完了,得了个校优秀毕业设计。毕设做的是个智能接口模块,用一周时间入门了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 例行优化