|
|
View previous topic :: View next topic |
Author |
Message |
kmp84
Joined: 02 Feb 2010 Posts: 354
|
#int_tbe on dspic33 doesn't work |
Posted: Wed Mar 21, 2018 5:24 am |
|
|
Hello,
I'm confused about dsPic UART transmit interrupt. I have used with these settings:
Code: |
#pin_select U1RX=PIN_E6 // Rx
#pin_select U1TX=PIN_E5 // Tx
#use rs232(UART1,baud=9600,errors,stream=com1)
#bit U1TXIF = getenv("BIT:U1TXIF")
#int_tbe
void TxISR(){
while(TxIndex < MaxTxBytes){
fputc(TxBuff[TxIndex++], com1);
}
. . . . . . .
U1TXIF = 1; // Enable tx isr. |
It stopped working after I added CCS TCP/IP library. #int_rda is OK!
Compiler ver.5.075.
Any Idea?
Best Regards! |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 354
|
|
Posted: Wed Mar 21, 2018 11:09 am |
|
|
Hello,
Тhe problem is solved! I just moved Code: |
#bit U1TXIF = getenv("BIT:U1TXIF") |
at the top of the compilation unit.
Best Regards! |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 354
|
|
Posted: Mon Mar 26, 2018 12:53 pm |
|
|
Hello,
I face a new problem with #int_tbe on dsPic33EP512 and modbus_slave rtu mode. When I enable transmit interrupt on UART1 Code: | U1TXIF = 1; // Enable tx isr. | , the modbus data on UART2 is garbage! What can be the problem?
Also whether the example above is the right way to using transmit interrupt for PCD devices? I saw this from the ccs example "ex_stisr.c". Whether I need to use interrupts priority?
Best Regards! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Mon Mar 26, 2018 1:33 pm |
|
|
No.
Your approach is fundamentally flawed.
Problem is that if you ask it to send more bytes than there is space for in the hardware buffer, the code will sit waiting in the INT_TBE handler. This can then result in other interrupts being starved of time.
You say you have based it on ex_stisr, but look again. Ex_stisr, uses a circular buffer and only sends the characters the hardware can accept. This is what you need to do, and then get out of the interrupt straight away.
Also understand that when int_tbe in the example has nothing to send, it disables the interrupt. Only re-enabling when new data is sent. This is essential. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 354
|
|
Posted: Tue Mar 27, 2018 8:52 am |
|
|
Hi Ttelmah,
1. I have changed transmit interrupt with your help as follow:
Code: |
#pin_select U1RX=PIN_E6 // Rx
#pin_select U1TX=PIN_E5 // Tx
#define EN_PIN_485 PIN_C1 // RE/DE Half Duplex RS485 Control Pin!
#use rs232(UART1, baud=9600, enable=EN_PIN_485, bits=9, long_data, errors, stream=com1) // Uart1 in 9 bit mode getc,putc accept 16bit data
static unsigned int8 TxBuff[TX_BUFF_SIZE];
static unsigned int8 MaxTxBytes;
static unsigned int8 TxIndex;
//===========================================
#bit U1TXIF = getenv("BIT:U1TXIF")
//===========================================
#int_tbe
void TxISR(void){
if(TxIndex < MaxTxBytes){
if(TxIndex != 0)
fputc(TxBuff[TxIndex++], com1);
else
fputc((unsigned int16)0x100|TxBuff[TxIndex++], com1); // if First byte set 9'th bit (Address byte)
}
}
//=============================================
void SendCmd(int8 CMDR, int8 Id){
int16 CRC = 0;
TxBuff[0] = Id; // Scale Address
TxBuff[1] = PC_FRAME_TYPE_01h; // Fame Type
TxBuff[2] = 0x01; // Source Address "SA";
TxBuff[3] = 0x00; // MSB Frame Len (Fixed);
TxBuff[4] = 0x08; // LSB Frame Len (Fixed);
TxBuff[5] = CMDR; // Current CMD;
CRC = CalcCrc(TxBuff, 6u); // Calc 16 bit CRC sum;
TxBuff[6] = make8(CRC, 1); // Get MSB of CRC;
TxBuff[7] = make8(CRC, 0); // Get LSB of CRC;
TxIndex = 0; // Clr. TxIndex;
MaxTxBytes = 8u; // Set Tx Packet Len;
U1TXIF = 1; // Enable Tx_ISR()!
}
|
It is OK?
2. Another problem is CCS "ex_modbus_slave.c". In several places this example is used delay_us(xxx), which significantly reduce program speed!
I tried to change
Code: |
while(true){
while(!modbus_kbhit());
delay_us(50);
.....................
}
| with
Code: |
void TaskModBusRTU(void){
if(modbus_kbhit()){
........................
}
} |
but have no success! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Tue Mar 27, 2018 11:07 am |
|
|
OK. It now becomes obvious what you are trying to do.
Don't. It's pointless....
First thing is that to work like this you would have to be configuring the TX_ISR to only interrupt when the whole 8 byte buffer is empty. Are you setting it up this way?. If not it'll be interrupting when there is space in the buffer. Not what you need.
Then if the TX buffer is empty, you can just load eight bytes into this. No need for an ISR at all. Having the ISR is a waste of time and space.
Then you have the problem of leaving the interrupt enabled. if you wanted to work this way, you would still have to disable the interrupt when you have nothing to send.
The interrupt flag is not the interrupt enable.
The delay doesn't reduce program speed. Characters can only arrive at 520uSec intervals (assuming 19200bps). |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 354
|
|
Posted: Tue Mar 27, 2018 12:42 pm |
|
|
I am totally confused about transmit interrupt. I thought that after prepares the tx packet and allowing tx interruption the cpu is ready for next "task"?
If this is not, I have just do like this:
Code: |
void SendCmd(int8 CMDR, int8 Id){
int8 i;
int16 CRC = 0;
TxBuff[0] = Id; // Scale Address
TxBuff[1] = PC_FRAME_TYPE_01h; // Fame Type
TxBuff[2] = 0x01; // Source Address "SA";
TxBuff[3] = 0x00; // MSB Frame Len (Fixed);
TxBuff[4] = 0x08; // LSB Frame Len (Fixed);
TxBuff[5] = CMDR; // Current CMD;
CRC = CalcCrc(TxBuff, 6u); // Calc 16 bit CRC sum;
TxBuff[6] = make8(CRC, 1); // Get MSB of CRC;
TxBuff[7] = make8(CRC, 0); // Get LSB of CRC;
for(i=0;i<8;i++){
if(i!= 0)
fputc(TxBuff[i], com1);
else
fputc((unsigned int16)0x100|TxBuff[i], com1); // if First byte set 9'th bit (Address byte)
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Wed Mar 28, 2018 1:15 am |
|
|
There is no such thing really as tasks. There is only one processor core and any 'threading' is down to your code.
However think about it.
You load a buffer with data.
Then trigger the interrupt.
The processor at this point stops what it is doing, and goes to the interrupt handler, taking the extra time to save all the registers as it does.
It then fills up the UART buffer, and writes all the registers back.
It then returns to the next instruction.
So using an interrupt to do this, just adds the extra time to call the interrupt handler, save the registers, restore the registers and return, to the act of loading data into the TX registers.....
Now where the interrupt would be worthwhile, is if instead of using the hardware buffer and just 8 bytes of data, you want to send large sequences of data. In this case you need something like the circular buffer shown in the example. Then when you want to send data you just load it to this buffer, and let it be sent as space becomes available in the hardware buffer. In this case, sending data that may take several seconds, is done 'on demand' by the hardware. Even better, on DS chips like this, you could put this data into a buffer accessible by DMA, and program this to send (say) 128 characters automatically reloading the UART buffer as needed. |
|
|
|
|
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
|