|
|
View previous topic :: View next topic |
Author |
Message |
Torello
Joined: 29 Sep 2006 Posts: 123
|
#INT_TBE on a 18F26Q83 |
Posted: Fri Jan 03, 2025 9:42 am |
|
|
Hi,
I start writing a DMX controller and I'm running into a problem when doing the actual byte writes in an ISR.
In the code below, the ISR is never executed, i can see that on my oscilloscope. As the code executes "enable_interrupts(global)" I think it jumps to a wrong ISRvector where it finds nothing.
The Pic then restarts after a second due to the WDT.
So do I need to code more ISR setup/initialisation?
Code: | #include <test.h>
int8 TxBuf[60];
int8 TxIdx,TxLen;
#int_tbe
void Tbe_handler() {
bScope0=1;
if (interrupt_active(INT_TBE2)) {
U2TXB = TxBuf[TxIdx++]; //load TXB, increment index
if (TxIdx==TxLen) disable_interrupts(INT_TBE2); //T: last load of TXB; disable interrupt
}
bScope0=0;
}
void main(){
int8 Tic100ms=0;
int8 i=0;
int16 i160;
int16 RstCause;
setup_oscillator(OSC_HFINTRC_64MHZ);
setup_wdt( WDT_1S);
//------ setup IO
output_drive(pScope0); output_low(pScope0);
output_drive(RS_Tx);
output_drive(DMX_Tx);
//------ Modify the #use RS232(stream=DMX...) to really become DMX
U2CON0&=0b11000000; //clear bits TxEn/RxEn/mode others untouched
U2CON0|=0b00101010; //TxEn=1 and Mode=DMX
U2CON2&=0b11111011; //TxPol=0 other untouched
//----- Setup Timer0 raise Tmr0IF every 100ms
setup_timer_0(T0_INTERNAL|T0_DIV_1024|T0_OUTPS_11|T0_8_BIT); TMR0H=142;
delay_ms(20);
fprintf(Debug, "Program start, cause: ");
RstCause=restart_cause();
Switch (RstCause) {
case RESTART_NONE:
break;
case NORMAL_POWER_UP:
fprintf(Debug, "Normal PowerUp\n");
break;
case WDT_TIMEOUT:
fprintf(Debug, "WDT-Timeout\n");
break;
case WDT_WINDOW_VIOLATION:
fprintf(Debug, "WDT_window violation\n");
break;
case RESET_INSTRUCTION:
fprintf(Debug, "RST instruction\n");
break;
case MCLR_FROM_RUN:
fprintf(Debug, "MCLR from Run\n");
break;
case BROWNOUT_RESTART:
fprintf(Debug, "BrownOut\n");
break;
default:
fprintf(Debug, "other %Lx\n",RstCause);
}
//----- Main Loop, Task schedular
while(true) {
restart_wdt();
if (Tmr0IF) {
Tmr0IF=0;
Tic100ms++; if (Tic100ms>=10) Tic100ms=0;
switch (Tic100ms) {
case 1:
//bScope0=1; delay_ms(10); bScope0=0;
break;
case 2:
if (!U2TXIE && U2TXTMIF ) { //interrupt not enabled -AND-! the transmit register is also empty
//bScope0=1;
TxBuf[0]=0; //load buffer
TxBuf[1]=0xAA;
TxBuf[2]=0x55;
TxIdx=0; TxLen=3; //reset index count, load number of bytes to send
U2P1H=0; U2P1l=TxLen-2; //set bytes "amount" for autobreak (=number of DATA bytes minus 1 EXcluding the StartCode)
enable_interrupts(INT_TBE2); //this will fire the ISR as the transmit register is empty
enable_interrupts(global);
//bScope0=0;
}
/*below 3 byte DMX send works as should
U2P1H=0; U2P1l=1; // 1U2P1= total bytes to send - 2 !! (Startcode + n-bytes; startcode=universum number)
U2TXB=0x00;
While(!U2TXIF); //wait till byte has been send
U2TXB=0xAA;
While(!U2TXIF);
U2TXB=0x55;
While(!U2TXIF);
*/
break;
Case 3:
for(i160=0x49E; i160<=0x04AD; i160++) { //show me all the PIE content
fprintf(Debug,"Adr: %Lx, byte: %x\n",i160, (*i160));
}
fprintf(Debug,"-----\n");
break;
}
}
}
}
|
Code: | #ifndef test_H
#define test_H
#include <18F26Q83.h>
#device ADC=12
#use fast_io(B)
#use fast_io(C)
#FUSES WDTCLK_LFINTRC,NOEXTOSC, RSTOSC_HFINTRC_1MHZ, PUT_64MS, NOLVP, Nobrownout, NoPPS1Way
#use delay(internal=64000000)
//#define An0 PIN_A0
//#define An1 PIN_A1
//#define An2 PIN_A2
//#define An3 PIN_A3
//#define An4 PIN_A4
//#define An5 PIN_A5
//#define An6 PIN_A6
//#define An7 PIN_A7
#define nop(x) Delay_cycles(x)
#define pScope0 PIN_B0
#bit bScope0=getenv("SFR:PORTB").0
#define pFree_B1 PIN_B1
#define pFree_B2 PIN_B2
#define pFree_B3 PIN_B3
#define pFree_B4 PIN_B4
#define pFree_B5 PIN_B5
#define RS_Tx PIN_B6
#define RS_Rx PIN_B7
#define pFree_C0 PIN_C0
#define pFree_C1 PIN_C1
#define pFree_C2 PIN_C2
#define pFree_C3 PIN_C3
#define DMX_Tx PIN_C4
#define DMX_Rx PIN_C5
#define pFree_C6 PIN_C6
#define pFree_C7 PIN_C7
#define Mclr PIN_E3
//--- ADC-----------------------------------
#bit ADCBUSY = getenv("SFR:ADCON0").0 //busy bit is called "GO"
//--- IO -----------------------------------
#byte PortA = getenv("SFR:PORTA")
#byte PortB = getenv("SFR:PORTB")
#byte PortC = getenv("SFR:PORTC")
//--- Timer -----------------------------------
#define T0_OUTPS_01 0x0000 //Postscale 1:1
#define T0_OUTPS_02 0x0100
#define T0_OUTPS_03 0x0200
#define T0_OUTPS_04 0x0300
#define T0_OUTPS_05 0x0400
#define T0_OUTPS_06 0x0500
#define T0_OUTPS_07 0x0600
#define T0_OUTPS_08 0x0700
#define T0_OUTPS_09 0x0800
#define T0_OUTPS_10 0x0900
#define T0_OUTPS_11 0x0A00
#define T0_OUTPS_12 0x0B00
#define T0_OUTPS_13 0x0C00
#define T0_OUTPS_14 0x0D00
#define T0_OUTPS_15 0x0E00
#define T0_OUTPS_16 0x0F00 //PostScale 1:16
#byte TMR0L=0x318
#byte TMR0H=0x319
#byte T0CON0=0x31A
#byte T0CON1=0x31B
#bit TMR0IF = getenv("BIT:TMR0IF") //PIR3.7
#bit TMR0EN = getenv("BIT:T0CON0.T0EN")
#bit TMR0ASYNC = T0CON1.4
//--- NCO -----------------------------------
#bit NCO1EN = getenv("SFR:NCO1CON").7 //Enable bit of the NCO0
//--- RS232 ---------------------------------
#PIN_SELECT U1RX=RS_Rx //must be on port B or C !
#PIN_SELECT U1TX=RS_Tx //must be on port B or C !
#use RS232(stream=debug, UART1, Baud=38400, ERRORS)
//--- UART / DMX ----------------------------
#PIN_SELECT U2RX=DMX_Rx
#PIN_SELECT U2TX=DMX_Tx
#byte U2CON0=getenv("SFR:U2CON0") //(oa. TxEn/RxEn/Mode)
#byte U2CON1=getenv("SFR:U2CON1")
#byte U2CON2=getenv("SFR:U2CON2") //(oa. RxPol/TxPol
#byte U2P1H=getenv("SFR:U2P1H")
#byte U2P1L=getenv("SFR:U2P1L")
#byte U2TXB=getenv("SFR:U2TXB") //transmit byte register
#bit U2TXEn=getenv("BIT:U2CON0.U2TXEN")
#bit U2TXIF=getenv("BIT:PIR8.U2TXIF") //'1' transmit reg empty
#bit U2RXIF=getenv("BIT:PIR8.U2RXIF") //'1' byte received
#bit U2TXIE=getenv("BIT:PIE8.U2TXIE") //'1' enable TXIF interrupt
#bit U2RXIE=getenv("BIT:PIE8.U2RXIE") //'1' enable RXIF interrupt
#bit U2TXTMIF=getenv("BIT:U2ERRIR.U2TXMTIF") //'1' transmit -SHIFT- reg empty flag, '0' transmit is busy
#bit U2TXTMIE=getenv("BIT:U2ERRIE.U2TXMTIE") //'1' enable above as interrupt
#use RS232(stream=DMX, UART2, Baud=250000,BITS=8,PARITY=N,STOP=2, ERRORS)
//---- I2C ----------------------------------
#bit FME=getenv("BIT:FME") //'0'= (postscale5, only 10x or 2c PU-currents) '1'= (postscale4, 20, 10, 5x PU-currents)
#bit WPUC3=getenv("BIT:WPUC3") //'1'=weak pull-up enabled
#bit WPUC4=getenv("BIT:WPUC4")
#byte WPUC=getenv("SFR:WPUC")
#byte RC4I2C=getenv("SFR:RC4I2C")
#byte RC3I2C=getenv("SFR:RC3I2C")
#byte I2C1BAUD = getenv("SFR:I2C1BAUD")
//#pin_select SCL1OUT = pSCL
//#pin_select SCL1IN = pSCL
//#pin_select SDA1OUT = pSDA
//#pin_select SDA1IN = pSDA
//#use i2c(Master, stream=MCP9808_Stream, I2C1, CLOCK_SOURCE=HFINTOSC, CLOCK_DIVISOR=4)
Typedef union { // This union typedef can be used for easy acces
int8 B[2]; // of bytes in integers
long int W;
} btwd;
Typedef union { // This union typedef can be used for easy acces
signed int8 B[2]; // of bytes in integers
signed int16 W;
} sbtwd;
Typedef union { // This union typedef can be used for easy acces
int8 B[4]; // of bytes and words in a long int
int16 W[2];
int32 L;
} bwl;
Typedef Union {
int8 byt;
int1 bit[8];
int1 b7,b6,b5,b4,b3,b2,b1,b0;
} bytbit;
#endif |
_________________ Regards, Edwin. PCWHD v5.114 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19589
|
|
Posted: Fri Jan 03, 2025 10:35 am |
|
|
INT_TBE2
INT_TBE
Not the same thing.......
You are adding a handler for UART1 TBE, but then enabling UART2 TBE
interrupt,
Also a comment, a signed int16, only has a sign on the high byte. Using two
signed int8's to access it is a problem..... |
|
|
Torello
Joined: 29 Sep 2006 Posts: 123
|
|
Posted: Sat Jan 04, 2025 6:58 am |
|
|
Thanx, so obvoius And this works.
I first tried #INT_TBE1 as I thought that #INT_TBE would be for UART1 and thus #INT_TBE1 for UART2.
But #INT_TBE1 does not compile and raises an error "Invalid Pre-Processor directive". Then I didn't try TBE2 anymore, because I read something about this Pic using just one "main" TBE interrupt and with the interrupt_active(INT_TBE2) command you need to test which TBE number it actally is. And then I got stuck.
But it still confuses me that #INT_TBE1 does not compile and seems to be missing in the 18F26Q83.h header file.
Any thoughts why?
And now with #INT_TBE2 I guess I can leave out the testing on TBE2..
Yes, you are right about the union! _________________ Regards, Edwin. PCWHD v5.114 |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9269 Location: Greensville,Ontario
|
|
Posted: Sat Jan 04, 2025 7:08 am |
|
|
possibly......
in the beginning,
there was but ONE UART in a PIC, so 'TBE' was chosen
later, when there were TWO UARTS. 'TBE2' was added...
'TBE1' SHOULD be added into the header as it would be 'logical'
Now I'm curious if PICs with 4 UARTS have 'TBE1' ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19589
|
|
Posted: Sat Jan 04, 2025 7:38 am |
|
|
With the compiler, there is a text file. ints.txt. Contains the names of
all the interrupts and what they do.
There is TBE, TBE1, TBE2, TBE3 & TBE4.
The chips with more than one UART accept the numeric forms for all of
the UARTs.
The key point tis that TBE, is not a 'global' TBE flag, it only applies to the
first UART.
Microchip did the same. Sp originally there was TBE, but when they added
the multiple UARTs, you got TBE1, TBE2 etc.. CCS allow TBE to still be used
for the first UART for reverse compatibility. |
|
|
Torello
Joined: 29 Sep 2006 Posts: 123
|
|
Posted: Sat Jan 04, 2025 9:33 am |
|
|
Ah, reading you last reply just now
I was already experimenting with my code and found out the same.
TBE = TBE1.
In code below I also can see that Uart1 has priority over Uart2.
Running on 64Mhz the latency is 1.8us. The ISR self is just below 1us
The first service of TBE2 is after 2 services of TBE1. That makes sense as the transmit-, and buffer register are both empty when starting the sendtrain.
Thanx for the extensive help!
Code: |
#include <test.h>
int8 TxBuf[60];
int8 TxIdx,TxLen;
int8 Hlo[6]={'H','a','l','l','o','\n'};
int8 Hidx=0;
#int_tbe2
void Tbe2_handler() {
bScope0=1;
U2TXB = TxBuf[TxIdx++]; //load TXB, increment index
if (TxIdx==TxLen) disable_interrupts(INT_TBE2); //T: last load of TXB; disable interrupt
bScope0=0;
}
#int_tbe
void Tbe1_handler() {
bScope1=1;
U1TXB = Hlo[Hidx++];
if (Hidx==6) { Hidx=0; disable_interrupts(INT_TBE);}
bScope1=0;
}
void main(){
int8 Tic100ms=0;
int8 i=0;
int16 i160;
int16 RstCause;
setup_oscillator(OSC_HFINTRC_64MHZ);
setup_wdt( WDT_1S);
//------ setup IO
output_drive(pScope0); output_low(pScope0);
output_drive(pScope1); output_low(pScope1);
output_drive(RS_Tx);
output_drive(DMX_Tx);
//------ Modify the #use RS232(stream=DMX...) to really become DMX
U2CON0&=0b11000000; //clear bits TxEn/RxEn/mode others untouched
U2CON0|=0b00101010; //TxEn=1 and Mode=DMX
U2CON2&=0b11111011; //TxPol=0 other untouched
//----- Setup Timer0 raise Tmr0IF every 100ms
setup_timer_0(T0_INTERNAL|T0_DIV_1024|T0_OUTPS_11|T0_8_BIT); TMR0H=142;
delay_ms(20);
fprintf(Debug, "Program start, cause: ");
RstCause=restart_cause();
Switch (RstCause) {
case RESTART_NONE:
break;
case NORMAL_POWER_UP:
fprintf(Debug, "Normal PowerUp\n");
break;
case WDT_TIMEOUT:
fprintf(Debug, "WDT-Timeout\n");
break;
case WDT_WINDOW_VIOLATION:
fprintf(Debug, "WDT_window violation\n");
break;
case RESET_INSTRUCTION:
fprintf(Debug, "RST instruction\n");
break;
case MCLR_FROM_RUN:
fprintf(Debug, "MCLR from Run\n");
break;
case BROWNOUT_RESTART:
fprintf(Debug, "BrownOut\n");
break;
default:
fprintf(Debug, "other %Lx\n",RstCause);
}
//----- Main Loop, Task schedular
while(true) {
restart_wdt();
if (Tmr0IF) {
Tmr0IF=0;
Tic100ms++; if (Tic100ms>=10) Tic100ms=0;
switch (Tic100ms) {
case 1:
//bScope0=1; delay_ms(10); bScope0=0;
break;
case 2:
if (!U2TXIE && U2TXTMIF ) { //interrupt not enabled -AND-! the transmit register is also empty
TxBuf[0]=0; //load buffer
TxBuf[1]=0xAA;
TxBuf[2]=0x55;
TxIdx=0; TxLen=3; //reset index count, load number of bytes to send
U2P1H=0; U2P1l=TxLen-2; //set bytes "amount" for autobreak (=number of DATA bytes minus 1 EXcluding the StartCode)
disable_interrupts(global);
enable_interrupts(INT_TBE2); //this will enable the TBE2 ISR as the transmit register is empty
enable_interrupts(INT_TBE); //this will enable the TBE (=Uart1) ISR and 1 send of "Hallo"
bScope0=1;
delay_us(10); //scope-bit 'mark' bigger than ISR time..
bScope0=0; //to measure i'rupt latency
enable_interrupts(global); //both interrupts now get fired....
}
break;
Case 3:
break;
}
}
}
}
|
_________________ Regards, Edwin. PCWHD v5.114 |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|