⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comm_mcu8051.c

📁 用quartusII编写的
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "..\..\includes.h"
#if CFG_UART_EN > 0

#if CFG_UART_RX_BUF_EN > 0
// 串口接收缓冲区的存储空间
static INT8U idata UART0_RxBuf[UART0_RX_BUF_SIZE];
static INT8U idata UART1_RxBuf[UART1_RX_BUF_SIZE];

// 串口接收缓冲区
static RING_QUEUE UART0_RingRxBuf;
static RING_QUEUE UART1_RingRxBuf;
#endif


//-------------------------------------------------------------------
static COMM_ERR_TYPE CommCfgPort( INT8U commNum, INT32U baudRate );


//-------------------------------------------------------------------
// 串口初始化
//-------------------------------------------------------------------
extern COMM_ERR_TYPE CommInit( INT8U commNum, INT32U baudRate )
{
      COMM_ERR_TYPE err;
     
      // 配置端口
      err = CommCfgPort( commNum, baudRate );
      
      if( err!=COMM_NO_ERR )
            return err;

#if CFG_UART_RX_BUF_EN > 0
	// 初始化接收缓冲区
	if( commNum == UART0 )
	{
	      Queue_Init( &UART0_RingRxBuf, UART0_RX_BUF_SIZE, UART0_RxBuf );
	}
	else if( commNum == UART1 )
	{
	      Queue_Init( &UART1_RingRxBuf, UART1_RX_BUF_SIZE, UART1_RxBuf );
	}
#endif
	      
	return COMM_NO_ERR;
}

/*

//------------------------------------------------------
// 串口0中断服务程序
//------------------------------------------------------
void UART0_ISR( void ) interrupt UART0_VECTOR_NUMBER
{
      INT8U ch;
      
	// 必须由软件来清除串口的中断源
	if( TI==1 )
	{
		TI=0;
	}
	else if( RI==1 )
	{
		RI=0;
		
		ch = SBUF;
		CommSendByte( UART0, ch );
	}
}


//------------------------------------------------------
// 串口1中断服务程序
//------------------------------------------------------
void UART1_ISR( void ) interrupt UART1_VECTOR_NUMBER
{
      INT8U ch;
      
	// 必须由软件来清除串口的中断源
	if( TI1==1 )
	{
		TI1=0;
	}
	else if( RI1==1 )
	{
		RI1=0;
		
		ch = SBUF1;
		CommSendByte( UART1, ch );
	}
}
*/



//-------------------------------------------------------------------
// 设置串口的波特率
//
// 说明:
// 		在Winbond77E58中,串口0可以用定时器1或2做波特率发生器,串口1只能用定时器1
// 	做波特率发生器。
//          为了避免冲突,我们约定:在本程序中,串口0用定时器2做波特率发生器,
//    串口1用定时器1做波特率发生器。
//
//		如果使用定时器2的波特率发生器模式作为波特率发生器,则波特率和以下几个因素有关:
//	(1) Fosc 晶振
//    (2) 特殊寄存器PMR中的CD1 CD0位
//    (3) 定时器2的计数初值
//
//		如果使用定时器1作为波特率发生器,则波特率和以下几个因素有关:
//	(1) Fosc 晶振
//    (2) 特殊寄存器PMR中的CD1 CD0位
//    (3) 特殊寄存器CKCON中的T1M位
//    (4) 特殊寄存器PCON中的SMOD位(控制串口0的波特率是否倍增),
//	    或特殊寄存器WDCON中的SMOD_1位(控制串口1的波特率是否倍增)
//    (5) 定时器1的计数初值
//-------------------------------------------------------------------
static COMM_ERR_TYPE CommCfgPort( INT8U commNum, INT32U baudRate )
{
	INT16U initValue;
	
	if( commNum == UART0 )
	{
	      
#if CFG_UART0_BAUDRATE_TIMER==2 // 串口0的波特率发生器使用定时器2
		// 串口方式1,8个数据位,1个停止位,允许接收
      	SCON = 0x50;
      	
      	// 使用定时器2的波特率发生器模式作为波特率发生器
		RCLK = 1;
		TCLK = 1;
		
		// 根据波特率计算定时器的计数初值
		initValue = (INT32U)65536 - (Fosc/32)/baudRate;
		
		// 装入波特率对应的初值
		TH2 = (INT8U)(initValue>>8);
      	TL2 = (INT8U)(initValue&0xff);
      
      	RCAP2H = (INT8U)(initValue>>8);
      	RCAP2L = (INT8U)(initValue&0xff);
		
		// 启动定时器2
	      TR2 = 1;
#endif

#if CFG_UART0_BAUDRATE_TIMER==1 // 串口0的波特率发生器使用定时器1
            // 串口方式1,8个数据位,1个停止位,允许接收
      	SCON = 0x50;
      	
      	// 定时器1,定时用,软启动,模式2,8位自动重装
      	Timer_Init( TIMER1, TIMER_WORK_MODE_TIMER, TIMER_START_MODE_SOFT, 2 );
      	
      	// 波特率倍增
      	// 注意:串口1的波特率倍增位是WDCON中的bit7位(SMOD_1)
      	//       参见Winbond77E58 datasheet 的27页
      	// 	   串口0的波特率倍增位是PCON中的bit7位(SMOD)
      	PCON |= 0x80;
      	
      	// 根据波特率计算定时器的计数初值
		initValue = 256 - ( (Fosc/16)/CFG_TIMER_DIVIDE_CLOCK )/baudRate;
		
		// 装入波特率对应的初值
      	TH1 = (INT8U)(initValue&0xff);
      	TL1 = (INT8U)(initValue&0xff);
      	
      	// 启动定时器1
      	TIMER1_START();
#endif
	     
	}
	else if( commNum == UART1 )
	{
		// 串口方式1,8个数据位,1个停止位,允许接收
      	SCON1 = 0x50;
      	
      	// 定时器1,定时用,软启动,模式2,8位自动重装
      	Timer_Init( TIMER1, TIMER_WORK_MODE_TIMER, TIMER_START_MODE_SOFT, 2 );
      	
      	// 波特率倍增
      	// 注意:串口1的波特率倍增位是WDCON中的bit7位(SMOD_1)
      	//       参见Winbond77E58 datasheet 的27页
      	// 	   串口0的波特率倍增位是PCON中的bit7位(SMOD)
      	SMOD_1 = 1;
      	
      	// 根据波特率计算定时器的计数初值
		initValue = 256 - ( (Fosc/16)/CFG_TIMER_DIVIDE_CLOCK )/baudRate;
		
		// 装入波特率对应的初值
      	TH1 = (INT8U)(initValue&0xff);
      	TL1 = (INT8U)(initValue&0xff);
      	
      	// 启动定时器1
      	TIMER1_START();
	}
	else
	{
		return COMM_BAD_CH;
	}
	
	return COMM_NO_ERR;
}


//-------------------------------------------------------------------
// 串口查询方式发送一个字节
//
// 参数说明:
// 		commNum	串口号
//          byte        要发送的字节数据
//
// 返回值:
//		如果发送成功,函数返回COMM_NO_ERR
//          如果串口编号出错,函数返回COMM_BAD_CH
//          如果发送超时,函数返回COMM_TX_TIMEOUT
//-------------------------------------------------------------------
extern COMM_ERR_TYPE CommSendByte( INT8U commNum, INT8U byte )
{
	INT8U temp;
	
	COMM_ERR_TYPE err = COMM_NO_ERR;
	
#define TIMEOUT_VALUE 10000	
	INT16U timeout=TIMEOUT_VALUE;
	
	temp = IE;
	
	if( commNum == UART0 )
	{
		UART0_INT_DIS();
		
		SBUF = byte;
      	while( TI==0 && (--timeout)>0);
      	TI = 0;
      	
      	if( timeout == 0 )
      	{
      		err = COMM_TX_TIMEOUT;
      	}
	}
	else if( commNum == UART1 )
	{
		UART1_INT_DIS();
		
		SBUF1 = byte;
      	while( TI1==0 && (--timeout)>0);
      	TI1 = 0;
      	
      	if( timeout == 0 )
      	{
      		err = COMM_TX_TIMEOUT;
      	}
	}
	else
	{
		err = COMM_BAD_CH;
	}
	
	IE = temp;
	
	return err;
}

//-------------------------------------------------------------------
// 串口查询方式发送字符串
//
// 参数说明:
// 		commNum	串口号
//          str         要发送的字符串
//
// 返回值:
//		如果发送成功,函数返回COMM_NO_ERR
//          如果串口编号出错,函数返回COMM_BAD_CH
//          如果发送超时,函数返回COMM_TX_TIMEOUT
//-------------------------------------------------------------------
extern COMM_ERR_TYPE CommSendString( INT8U commNum, const INT8U *str )
{
	COMM_ERR_TYPE err;
	
	while( *str != '\0' )
	{
		err = CommSendByte( commNum, *str );
		
		++str;
		
		if( err != COMM_NO_ERR )
			return err;
	}
	
	return COMM_NO_ERR;
}


#if CFG_UART_PRINTF_EN > 0
//---------------------------------------------------------------------------
// 串口打印函数
// 
// 说明:
//          本函数和ANSI C标准库stdio.h中定义的printf()函数保持兼容,本函数只是在
//    形参中多了一个“串口号”参数,其余和printf()函数完全兼容,包括形参和返回值。
//
// 开发过程:
//		2005-1-12 13:57 
//			目前这个版本的CommPrintf()函数一次还不能打印太多的东西,因为
//		它是将所有要打印的东西都打印到print_buf[]中,如果一次打印的东西太多,
//		会造成print_buf[]的溢出。
//---------------------------------------------------------------------------
extern int CommPrintf( INT8U commNum, const char *format, ... )
{
#define PRINT_BUF_SIZE 32
      static INT8U idata print_buf[ PRINT_BUF_SIZE ];
      
      int cnt;
      
      va_list args;                 
      va_start( args, format );
      cnt = vsprintf( print_buf, format, args );
      va_end( args );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -