CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

#int_tbe on dspic33 doesn't work

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
kmp84



Joined: 02 Feb 2010
Posts: 345

View user's profile Send private message

#int_tbe on dspic33 doesn't work
PostPosted: Wed Mar 21, 2018 5:24 am     Reply with quote

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: 345

View user's profile Send private message

PostPosted: Wed Mar 21, 2018 11:09 am     Reply with quote

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: 345

View user's profile Send private message

PostPosted: Mon Mar 26, 2018 12:53 pm     Reply with quote

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: 19195

View user's profile Send private message

PostPosted: Mon Mar 26, 2018 1:33 pm     Reply with quote

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: 345

View user's profile Send private message

PostPosted: Tue Mar 27, 2018 8:52 am     Reply with quote

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: 19195

View user's profile Send private message

PostPosted: Tue Mar 27, 2018 11:07 am     Reply with quote

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: 345

View user's profile Send private message

PostPosted: Tue Mar 27, 2018 12:42 pm     Reply with quote

I am totally confused about transmit interrupt. Confused 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: 19195

View user's profile Send private message

PostPosted: Wed Mar 28, 2018 1:15 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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