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

📄 softuart.c

📁 C8051FXXX的软串行端口编程技术
💻 C
📖 第 1 页 / 共 2 页
字号:

	CCF0 = 0;											// Clear pending PCA module 0 and
	CCF1 = 0;											// module 1 capture/compare interrupts.

	SRI = 0;												// Clear Receive complete flag.
	STI = 0;												// Clear Transmit complete flag.

   SW_TX = 1;											// TX line initially high.	
	STXBSY = 0;											// Clear SW_UART Busy flag

}

//------------------------------------------------------------------------------------------
// SW_UART_ENABLE: SW_UART Enable Routine
// Enables SW_UART for use.
// - Enables PCA module 0 interrupts
// - Enables PCA module 1 interrupts
// - Starts PCA counter.
//
void	SW_UART_ENABLE(void){
	
	PCA0CPM0 |= 0x01;									// Enable module 0 (receive) interrupts.
	PCA0CPM1 |= 0x01;									// Enable module 1 (transmit) interrupts.

	CR = 1;												// Start PCA counter.
	EIE1 |= 0x08;										// Enable PCA interrupts
	EA = 1;												// Globally enable interrupts

}

//------------------------------------------------------------------------------------
// Interrupt Service Routines
//------------------------------------------------------------------------------------
//
// PCA_ISR: PCA Interrupt Service Routine.
// This ISR is triggered by both transmit and receive functions, for each bit that
// is transmitted or received. 
// - Checks module 0 interrupt flag (CCF0); if set, services receive state.
// - Checks module 1 interrupt flag (CCF1); if set, services transmit state.
//
void	PCA_ISR(void) interrupt 9 {

	static char 	SUTXST = 0;						// SW_UART TX state variable
	static char 	SURXST = 0;						// SW_UART RX state variable
	static unsigned char 	RXSHIFT;				// SW_UART RX Shift Register
	
	unsigned int	PCA_TEMP;						// Temporary storage variable for
															// manipulating PCA module high & low bytes.	

	// Check receive interrupt flag first; service if CCF0 is set.
	if (CCF0){
		CCF0 = 0;										// Clear interrupt flag.
		switch (SURXST){
			
			// State 0: START bit received.
			// In this state, a negative edge on SW_TX has caused the interrupt,
			// meaning a START has been detected and the PCA0CP0 registers have 
			// captured the value of PCA0.
			// - Check for receive enable and good START bit
			// - Switch PCA module 0 to software timer mode
			// - Add 3/2 bit time to module 0 capture registers to sample LSB.
			// - Increment RX state variable.
			case 0:
				if (SREN & ~SW_RX){					// Check for receive enable and a good
															// START bit.  
																
					PCA_TEMP = (PCA0CPH0 << 8);	// Read module 0 contents into
					PCA_TEMP |= PCA0CPL0;			// PCA_TEMP.

					PCA_TEMP += TH_TIME_COUNT;		// Add 3/2 bit times to PCA_TEMP

					PCA0CPL0 = PCA_TEMP;				// Restore PCA0CPL0 and PCA0CPH0
					PCA0CPH0 = (PCA_TEMP >> 8);	// with the updated value

					PCA0CPM0 = 0x49;					// Change module 0 to software
															// timer mode, interrupts enabled.

					SURXST++;							// Update RX state variable.
				}
				break;
			
			// States 1-8: Bit Received
			// - Sample SW_RX pin
			// - Shift new bit into RXSHIFT
			// - Add 1 bit time to module 0 capture registers
			// - Increment RX state variable
			case 1:
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
					
				RXSHIFT = RXSHIFT >> 1;				// Shift right 1 bit
				if (SW_RX)								// If SW_RX=1, 
					RXSHIFT |= 0x80;					// shift '1' into RXSHIFT msb
				
				PCA_TEMP = (PCA0CPH0 << 8);		// Read module 0 contents into
				PCA_TEMP |= PCA0CPL0;				// PCA_TEMP.

				PCA_TEMP += TIME_COUNT;				// Add 1 bit time to PCA_TEMP

				PCA0CPL0 = PCA_TEMP;					// Restore PCA0CPL0 and PCA0CPH0
				PCA0CPH0 = (PCA_TEMP >> 8);		// with the updated value
				
				SURXST++;								// Update RX state variable.
				break;

			// State 9: 8-bits received, Capture STOP bit.
			// - Move RXSHIFT into RDR.
			// - Set SRI (indicate receive complete).
			// - Prepare module 0 for next transfer.
			// - Reset RX state variable.
			// - Trigger IE7 if user-level interrupt support is enabled.
			case 9:

				RDR = RXSHIFT;							// Move received data to receive register.
				SRI = 1;									// Set receive complete indicator.

				PCA0CPM0 = 0x11;						// Switch module 0 to negative capture
															// mode; interrupt enabled for START
															// detection.

				SURXST = 0;								// Reset RX state variable.

				if (SES){								// If user-level interrupt support enabled
					EIE2 |= 0x20;						// Enable IE7.
					P3IF |= 0x80;					// Trigger IE7.
				}
				break;
				
			}
		}
		
		// Check Transmit interrupt; service if CCF1 is set.
		else if (CCF1){ 
			CCF1 = 0;									// Clear interrupt flag
			switch (SUTXST){
				
				// State 0: Transmit Initiated.
				// Here, the user has loaded a byte to transmit into TDR, and set the
				// module 1 interrupt to initiate the transfer.
				// - Transmit START bit (drop SW_TX)
				// - Read PCA0, add one bit time, & store in module 1 capture registers
				//   for first bit.
				// - Increment TX state variable.
				case 0:

					SW_TX = 0;							// Drop TX pin as START bit.
					
					PCA_TEMP = PCA0L;					// Read PCA counter value into
					PCA_TEMP |= (PCA0H << 8);		// PCA_TEMP.

					PCA_TEMP += TIME_COUNT;			// Add 1 bit time.

					PCA0CPL1 = PCA_TEMP;				// Store updated match value into
					PCA0CPH1 = (PCA_TEMP >> 8);	// module 1 capture/compare registers.

					PCA0CPM1 |= 0x48;					// Enable module 1 software timer.

					SUTXST++;							// Update TX state variable.				
					break;

				// States 1-9: Transmit Bit.
				// - Output LSB of TDR onto TX
				// - Shift TDR 1 bit right.
				// - Shift a '1' into MSB of TDR for STOP bit in State 9.
				// - Add 1 bit time to module 1 capture register
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
				case 8:
				case 9:
					
					SW_TX = (TDR & 0x01);			// Output LSB of TDR onto SW_TX pin.
					TDR >>= 1;							// Shift TDR right 1 bit.
					TDR |= 0x80;						// Shift '1' into MSB of TDR for
															// STOP bit in State 9.

					PCA_TEMP = (PCA0CPH1 << 8);	// Read module 1 contents into
					PCA_TEMP |= PCA0CPL1;			// PCA_TEMP.

					PCA_TEMP += TIME_COUNT;			// Add 1 bit time to PCA_TEMP
	
					PCA0CPL1 = PCA_TEMP;				// Restore PCA0CPL1 and PCA0CPH1
					PCA0CPH1 = (PCA_TEMP >> 8);	// with the updated value	

					SUTXST++;                     // Update TX state variable.
					break;
					
				// State 10: Last bit has been transmitted.  Transmit STOP bit
				// and end transfer.  
				// - Transmit STOP bit
				// - Set TX Complete indicator, clear Busy flag
				// - Reset TX state
				// - Prepare module 1 for next transfer.
				// - Trigger IE7 interrupt if user-level interrupts enabled.
				case 10:

					STI = 1;								// Indicate TX complete.
					SUTXST = 0;							// Reset TX state.
					SW_TX = 1;							// SW_TX should remain high.

					PCA0CPM1 = 0x01;					// Disable module 1 software timer; leave
															// interrupt enabled for next transmit.					
					
					if (SES){							// If user-level interrupt support enabled:
						EIE2 |= 0x20;					// Enable IE7.
						P3IF |= 0x80;				// Trigger IE7.
					}
					STXBSY = 0;							// SW_UART TX free.	
					break;
				}
		}
}

//----------------------------------------------------------------------------------------
// USER_ISR: User SW_UART Interrupt Service Routine (IE7 ISR)
// If interrupt-mode test code is enabled, this ISR
// transmits 15 characters and receives 15 characters. This routine is triggered each
// time a SW_UART transmit or receive is completed.
// - Checks receive complete indicator, and services.
// - Checks transmit complete indicator, and services.
// - Checks for transmits or receives that completed during the ISR; if so, triggers the
//   interrupt again.
//
void USER_ISR(void) interrupt 19 {				// IE7 Interrupt Service Routine

	P3IF &= ~(0x80);								// Clear IE7 interrupt flag
	
	if (SRI){											// If Receive Complete:
		SRI = 0;											// Clear receive flag.
		SW_BUF[k++] = RDR;							// Read receive buffer.
		if (k==16){										// If 15 characters have been received:
			SREN=0;										// Disable SW_UART Receiver.
			}												// Indicate 15 characters received.
		}

	else if (STI){										// If Transmit Complete:
		STI = 0;											// Clear transmit flag.

		if (m<15){                             // If less than 15 characters transmitted:
			STXBSY = 1;                         // Claim SW_UART Transmitter.
         TDR = m++;									// Increment variable, transmit.
         CCF1 = 1;									// Force module 1 interrupt to initiate TX
      }										         
      else 			
         SW_DONE=1;									// Indicate last character transmitted.
	}

	if (STI|SRI)										// If SRI or STI is set, re-trigger
		P3IF |= 0x80;								// interrupt to service.
}

//--------------------------------------------------------------------------------------
// HW_UART_ISR: Hardware UART Interrupt Service Routine
// Transmits characters from 1 to 15, and receives 15 characters.	
// - Checks receive interrupt, and services.
// - Checks transmit interrupt, and services.
//	
void	HW_UART_ISR(void) interrupt 4 {

	static char i=0;									// Transmit data variable.
	static char j=0;									// Receive data index.
	static idata char HW_BUF[20];					// Receive data buffer.
	
	if (RI0){												// If Receive Complete:
		
		RI0=0;												// Clear receive flag
		HW_BUF[j++] = SBUF0;							// Read receive buffer		
		if (j==15)										// If 15 characters received:
			REN0=0;										// Disable HW_UART receiver.
	}

	else if (TI0){										// If Transmit Complete:

		TI0 = 0;											// Clear transmit flag
		if (i<15)										// If characters left to transmit:
			
			SBUF0=i++;
			
											// Increment variable, transmit.
		else												// If 15 characters transmitted,
			HW_DONE=1;									// Indicate HW TX finished.			

	}
}

// End of File

⌨️ 快捷键说明

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