??? 07/20/10 16:25 Read: times |
#177396 - Which register bank are you using? Responding to: ???'s previous message |
I use the same part (DS89C450) and have both UARTS working using interrupts, but in order to do it, I used the "using" keyword. This keyword switches the register banks used when the interrupt is services so that interrupts don't trample over each other or have to use the stack.
Here is my initialization code: void sbufs_init(void) { // General Serial Mode Setup PCON &= 0xBF; // No Frame Error Mode for SBUF0 and SBUF1 // Serial 0 Mode Setup SM0 = 0; // SBUF0 Mode 0 SM1 = 1; // SBUF0 Mode 0 SM2 = 0; // No multiprocessor communication mode REN = 1; // Recieve enable RI = 0; // RI must be clear to recieve PCON &= 0x7F; // Single Speed for sbuf0 RXD0 = 1; // Latch port high for serial functions to work correctly // Serial 1 Mode Setup SM01 = 0; // SBUF1 Mode 0 SM11 = 1; // SBUF1 Mode 0 SM21 = 0; // No multiprocessor communication mode REN1 = 0; // Recieve only enabled when expecting an incomming message WDCON = WDCON & 0x7F; //01111111B Single Speed for sbuf1 RXD1 = 1; // Latch port high for serial functions to work correctly TEN = 0; // Disable transmit for RS485 until needed // Interrupt Settings ET1 = 0; // Disable T1 interrupts since using T1 for baud generation ET2 = 0; // Disable T2 interrupts since using T2 for baud generation // SBUF1 Baud clock TMOD = TMOD & 0x0F; // reset timer1 mode bits TMOD = TMOD | 0x20; // t1 8bit auto reload timer using system clk TCON = TCON & 0x33; // reset t1 control bits and INT1 control bits TH1 = 0xFD; // 9600 for serial port 1 TR1 = 1; // Start the Baud clock // SBUF0 Baud clock T2MOD &= 0xFC; // Not driving external pin with T2 and T2 counts up T2CON = 0x30; // timer 2 is baud for sbuf0 TX and RX RCAP2H = 0xFF; // Setup 9600 baud RCAP2L = 0xDC; // Communication for S0 TR2 = 1; // Start the Baud clock // Initialize ptrs RX_IN_PTR_0 = 0; RX_OUT_PTR_0 = 0; RX_EMPTY_0 = 1; RX_IN_PTR_1 = 0; RX_OUT_PTR_1 = 0; RX_EMPTY_1 = 1; TX_IN_PTR_0 = 0; TX_OUT_PTR_0 = 0; TX_EMPTY_0 = 1; TX_IN_PTR_1 = 0; TX_OUT_PTR_1 = 0; TX_EMPTY_1 = 1; } And the ISR code: void serial0_ISR(void) interrupt 4 using 2{ if(RI) { RI = 0; // Always acknowledge the interrupt if(RX_EMPTY_0 || (((RX_IN_PTR_0 + 1) % RX_BUF_SIZE_0) != RX_OUT_PTR_0)) { // buffer full if in+1 == out RX_BUF_0[RX_IN_PTR_0]=SBUF0; RX_IN_PTR_0 = (RX_IN_PTR_0 + 1) % RX_BUF_SIZE_0; RX_EMPTY_0 = 0; // not empty any more } } else { TI = 0; // always acknowledge interrupt // put_char routine must not fill the buffer such that in ptr catches out ptr if(TX_OUT_PTR_0 != TX_IN_PTR_0) { SBUF0 = TX_BUF_0[TX_OUT_PTR_0]; TX_OUT_PTR_0 = (TX_OUT_PTR_0 + 1) % TX_BUF_SIZE_0; } else TX_EMPTY_0 = 1; // we are done when out ptr catches in ptr } } void serial1_ISR(void) interrupt 7 using 2{ if(RI1) { RI1 = 0; // Always acknowledge the interrupt if(RX_EMPTY_1 || (((RX_IN_PTR_1 + 1) % RX_BUF_SIZE_1) != RX_OUT_PTR_1)) { // buffer full if in+1 == out RX_BUF_1[RX_IN_PTR_1]=SBUF1; RX_IN_PTR_1 = (RX_IN_PTR_1 + 1) % RX_BUF_SIZE_1; RX_EMPTY_1 = 0; // not empty any more } } else { TI1 = 0; // put_char routine must not fill the buffer such that in ptr catches out ptr if(TX_OUT_PTR_1 != TX_IN_PTR_1) { REN1 = 0; // can't send and recieve at the same time TEN = 1; SBUF1 = TX_BUF_1[TX_OUT_PTR_1]; TX_OUT_PTR_1 = ++TX_OUT_PTR_1 % TX_BUF_SIZE_1; } else { TX_EMPTY_1 = 1; // we are done when out ptr catches in ptr TEN = 0; REN1 = 1; // finished talking, now we listen } } } Note that UART1 is setup for half duplex communication. Please don't copy the style of this code as it is old and I would have chosen to do things differently these days, but it does work. Take a look at Mark A. Odell's code in the code section here at 8052.com for a better structured library. http://www.8052.com/codelib/files/efdUartDriver.zip --David |