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

📄 softuart.c

📁 C8051FXXX的软串行端口编程技术
💻 C
📖 第 1 页 / 共 2 页
字号:
//------------------------------------------------------------------------------------
//
// Copyright 2001	Cygnal Integrated Products, Inc.
//
// FILE NAME		: softuart.c
// TARGET DEVICE	: C8051F02x
// CREATED ON		: 06/07/04
// CREATED BY		: JS
//
// Software UART program, using PCA as baud rate source.
// PCA module 0 is used as receive baud rate source and START detector.  For START
// detection, module 0 is configured in negative-edge capture mode.  For all other
// SW_UART operations, module 0 is configured as a software timer.  Module match
// interrupts are used to generate the baud rate.  Module 1 generates the transmit
// baud rate in software timer mode. 
// Code assumes an external crystal is attached between the XTAL1 and XTAL2 pins.
// The frequency of the external crystal should be defined in the SYSCLK constant.
// 
// INITIALIZATION PROCEDURE:
// 1) Define SYSCLK according to external crystal frequency.
// 2) Define desired BAUD_RATE.
// 3) Call SW_UART_INIT().
// 4) Set SREN to enable SW_UART receiver.
// 5) Set SES only if user-level interrupt support is desired.
// 6) Call SW_UART_ENABLE().
//
// TO TRANSMIT:
// 1) Poll STXBSY for zero.
// 2) Write data to TDR.
// 3) Set CCF1 to initiate transmit.
// 4) STI will be set upon transmit completion.  An IE7 interrupt is generated if 
//    user-level interrupts are enabled.
//
// TO RECEIVE:
// 1) If in polled mode, poll SRI.  If in interrupt mode, check SRI in IE7 Interrupt
//    Service Routine.
// 2) Read data from RDR.
// 
// Test code is included, for both polled and interrupt mode.  Test code assumes
// the HW_UART pins and SW_UART pins are connected externally:
// P0.0 (HW_UART TX) ->  P2.2 (SW_UART RX)
// P0.1 (HW_UART RX) ->  P2.7 (SW_UART TX)
// 
// To use the test code in polled mode, comment out the call to the INTERRUPT_TEST()
// at the bottom of the main routine, and uncomment the call to POLLED_TEST().  To 
// test the interrupt mode, comment out the POLLED_TEST() call and uncomment the
// INTERRUPT_TEST() call.
//
// The test routines configure the HW_UART to operate with Timer 1 as the baud rate
// source.  The Timer 1 preload values are auto-calculated from the SYSCLK and BAUD_RATE
// constants.
//
//-----------------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------------
#include <c8051f020.h>								// SFR declarations

//-----------------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------------

#define	BAUD_RATE		38400						// User-definable SW_UART baud rate
#define	SYSCLK			11059200					// System clock derived from 11.0592MHz XTL

#define 	TIME_COUNT		SYSCLK/BAUD_RATE/4	// Number of PCA counts for one bit-time.
															// (PCA configured to count SYSCLK/4)

#define	TH_TIME_COUNT	TIME_COUNT*3/2			// 3/2 bit-time, for use after receiving
															// a START bit.  RX should be LOW for one
															// bit-time after the edge of the START,
															// and the first bit sample starts in the
															// middle of the next bit-time.

#define	HW_TIME_COUNT	SYSCLK/BAUD_RATE/16 	// Time count for HW_UART baud rate
															// generation.  Auto-calculated from the
															// SYSCLK and BAUD_RATE constants defined
															// above.

//-----------------------------------------------------------------------------------
//Global VARIABLES
//-----------------------------------------------------------------------------------

bit	SRI;												// SW_UART Receive Complete Indicator
bit	STI;												// SW_UART Transmit Complete Indicator
bit	STXBSY;											// SW_UART TX Busy flag
bit 	SREN;												// SW_UART RX Enable
bit	SES;												// SW_UART User-level Interrupt Support Enable

sbit	SW_RX = P2^2;  								// SW_UART Receive pin
sbit	SW_TX = P2^7;  								// SW_UART Transmit pin

char 	TDR;												// SW_UART TX Data Register
char 	RDR;												// SW_UART RX Data Register (latch)

// Test Variables
char k, m;												// Test indices.
char idata SW_BUF[20];								// SW_UART test receive buffer.

bit	HW_DONE;											// HW transfer complete flag (15 characters
															// transmitted.)
bit	SW_DONE;											// SW transfer complete flag (15 characters
															// transmitted.)

//------------------------------------------------------------------------------------
// Function PROTOTYPES
//------------------------------------------------------------------------------------

void	SW_UART_INIT();								// SW_UART initialization routine
void	SW_UART_ENABLE();								// SW_UART enable routine
void	PCA_ISR();										// SW_UART interrupt service routine
void 	INTERRUPT_TEST(void);						// SW_UART test routine using interrupt mode
void 	POLLED_TEST(void);							// SW_UART test routine using polled mode
void 	USER_ISR(void);								// SW_UART test interrupt service routine
void 	HWU_INIT(void);								// HW_UART initialization and setup routine
void	HW_UART_ISR(void);							// HW_UART interrupt service routine						
//------------------------------------------------------------------------------------
// MAIN Routine
//------------------------------------------------------------------------------------
// - Disables Watchdog Timer
// - Configures external crystal; switches SYSCLK to external crystal when stable.
// - Configures crossbar and ports.
// - Initializes and enables SW_UART.
// - Calls Test Routines.
//
void MAIN (void){
//	int delay;											// Delay counter.
    unsigned int i;
//OSCXCN = 0x66;										// Enable external crystal	
	WDTCN = 0xDE;										// disable watchdog timer
	WDTCN = 0xAD;

	// Port Setup
	XBR0 = 0x0f;										// HW_UART routed to pins P0.0 and P0.1;
															// CEX0 routed to pin P0.2.
	XBR2 = 0x44; 										// Enable crossbar, pull-ups enabled.

    P1MDIN = 0x00;										// P0.0 (HW TX), and P0.3 (SW TX)
	P2MDOUT |= 0X80;														// configured for push-pull output.
    P0MDOUT |= 0X01;
  OSCXCN = 0x67;                      // start external oscillator with
                                       // 11.0592MHz crystal

   for (i=0; i < 256; i++) ;           // XTLVLD blanking interval (>1ms)

   while (!(OSCXCN & 0x80)) ;          // Wait for crystal osc. to settle

   OSCICN = 0x88;                      // select external oscillator as SYSCLK
                                       // source and enable missing clock
                                       // detector
//	POLLED_TEST();										// Call Polled mode SW_UART test routine.
	INTERRUPT_TEST();									// Call Interrupt mode SW_UART test routine.

	while(1);											// Spin forever
}


//------------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------
// INTERRUPT_TEST: SW_UART Interrupt Mode Test
// Test code to transmit and receive 15 characters to/from the HW_UART (in interrupt
// mode), with SW_UART in interrupt mode.
// - Initializes and enables the SW_UART & HW_UART
// - Clears all test variables & counters
// - Transfers 15 characters from HW to SW_UART, and 15 characters from SW to HW_UART,
//   simultaneously. 
//
void INTERRUPT_TEST(void){

	SW_UART_INIT();									// Initialize SW_UART
	SW_UART_ENABLE();									// Enable SW_UART
	SREN = 1;											// Enable SW_UART Receiver
	SES = 1;												// User-level interrupt support enabled.

	HWU_INIT();											// Configure HW_UART for testing routine.
	k=m=0;												// Clear user ISR counters.
	
	HW_DONE=0;											// Clear transfer complete indicators
	SW_DONE=0;											// 

	IE |= 0x10;											// Enable HW_UART interrupts
	STI=1;												// Indicate transmit complete to initiate
															// next transfer.
	EIE2 |= 0x20;										// Start SW_TX by enabling
	P3IF |= 0x80;									// and forcing an IE7 interrupt
	
   TI0 = 1;                                   // Initiate a HW_UART transmit
                                             // by forcing TX interrupt.

	while(!(HW_DONE&SW_DONE));						// Wait for transfers to finish.
}

//---------------------------------------------------------------------------------------
// POLLED_TEST: SW_UART Polled Mode Test
// Test code to transmit and receive 15 characters to/from the HW_UART, with SW_UART
// in polled mode.
// - Initializes and enables the SW_UART & HW_UART
// - Clears all test variables & counters
// - Sends 15 characters from the HW_UART to be received by SW_UART.
// - Sends 15 characters from the SW_UART to be received by the HW_UART.
//
void POLLED_TEST(void){

	SW_UART_INIT();									// Initialize SW_UART
	SW_UART_ENABLE();									// Enable SW_UART
	SREN = 1;											// Enable SW_UART Receiver
	SES=0;												// Disable user-level interrupt support.

	HWU_INIT();											// Configure HW_UART for testing routine.
	k=m=0;												// Clear test counter variables.
	HW_DONE=0;											// Clear transfer complete indicators
	SW_DONE=0;											//
	IE |= 0x10;											// Enable HW_UART interrupts.

   TI0 = 1;                                   // Initiate a HW_UART transmit
                                             // by forcing TX interrupt.

	// Receive 15 characters with SW_UART; transmit with HW_UART.
	while(SREN){                              // Run while SW_UART Receiver is
                                             // enabled.	
		if (SRI){										// If Receive Complete:
			SRI = 0;										// Clear receive flag.
			SW_BUF[k++] = RDR;						// Read receive buffer.
			if (k==15){									// If 15 characters have been received:
				SREN = 0;								// Disable SW_UART Receiver.
			}												// Indicate 15 characters received.
		}
	}

	// Transmit 15 characters with SW_UART; receive with HW_UART.
	while(STXBSY);										// Poll Busy flag.
   STXBSY = 1;                               // Claim SW_UART Transmitter
	TDR=m++;												// Load TX data.
	CCF1=1;												// Initiate first SW_UART TX
															// by forcing a PCA module 1 interrupt.
	while(!SW_DONE){									// SW_UART transmitting here; HW_UART receiving.

		if (STI){										// If Transmit Complete:
			STI = 0;										// Clear transmit flag.
			if (m<16){									// Transmit 15 characters.
				STXBSY = 1;                      // Claim SW_UART Transmitter.
            TDR = m++;								// Transmit, increment variable.
				CCF1 = 1;								// Force module 1 interrupt to initiate TX.
			}
         else											// If this is 15th character,
				SW_DONE=1;								// Indicate last character transmitted.
		}
	}
}

//------------------------------------------------------------------------------------------
// HWU_INIT: HW_UART Initialization Routine
// Sets up HW_UART for use in SW_UART testing.
// - HW_UART in mode 1
// - Timer 1 used as baud rate source, clocked by SYSCLK.
//
void HWU_INIT(void) {

	PCON |= 0x80;										// SMOD=1 (HW_UART uses Timer 1 overflow
															// with no divide down).

	TMOD = 0x20;										// Configure Timer 1 for use by HW_UART
	CKCON |= 0x10;										// Timer 1 derived from SYSCLK
	TH1 = -HW_TIME_COUNT;							// Timer 1 initial value
	TL1 = -HW_TIME_COUNT;							// Timer 1 reload value

	TR1 = 1;    										// Start Timer 1

	RI0=0;													// Clear HW_UART receive and transmit
	TI0=0;													// complete indicators.

	SCON0 = 0x50;										// Configure HW_UART for mode 1, receiver enabled.
}
//------------------------------------------------------------------------------------------
// SW_UART_INIT: SW_UART initialization routine
// Prepares SW_UART for use.
// - Configures PCA: Module 0 in negative capture mode; module 1 in software 
//   	timer mode; PCA time base = SYSCLK/4; PCA interrupt disabled; PCA counter
//		disabled.
// - Clears pending PCA module 0 and 1 interrupts
// - Resets TX and RX state variables
//
void	SW_UART_INIT(void){

	PCA0CPM0 = 0x10;									// Module 0 in negative capture mode; module
															// 0 interrupt disabled.

	PCA0CPM1 = 0x48; 									// Module 1 in software timer mode; module
															// 1 interrupt disabled.	

	PCA0CN = 0;											// Leave PCA disabled
	PCA0MD = 0x02;										// PCA timebase = SYSCLK/4; PCA counter
															// interrupt disabled.

⌨️ 快捷键说明

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