View previous topic :: View next topic |
Author |
Message |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
SW Uart on PCD devices |
Posted: Thu Apr 26, 2018 8:45 am |
|
|
Hello,
Any idea how to use software uart on PCD micros? This is my test program, in which only first byte is printed correct!
Code: | #include <33EP512MU810.h>
#device ICSP=1
#use delay(crystal=8MHz, clock=16MHz)
#FUSES NOWDT //No Watch Dog Timer
#FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOJTAG //JTAG disabled
#FUSES NOPROTECT //
#pin_select INT1=PIN_G12
#use rs232(baud=9600, xmit=PIN_G13, rcv=PIN_G12)
#int_ext1
void int1_swuart_isr() {
char c;
c=getc();
putc(c);
}
#zero_ram
void main(){
delay_ms(500); // wait PLL Lock.
printf("\r\n Hello from 'SW-UART' on DsPic33Ep512MU810");
ENABLE_INTERRUPTS(INT_EXT1 | H_TO_L);
for(;;){
}
} |
Best Regards! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Thu Apr 26, 2018 8:59 am |
|
|
You need to understand the limitations of software UART's.
Your code receives the character, and then sits for an entire character time transmitting. Result anything that arrives in this time, _will_ be lost.
S/W UARTs are half duplex only.
Given your chip has four hardware UARTs, I have to ask 'why'?. Use one of these. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Thu Apr 26, 2018 12:41 pm |
|
|
Hi Ttelmah,
I'm using all four HW uarts and maybe i have to have one more? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Thu Apr 26, 2018 1:30 pm |
|
|
Ouch.
Some time ago I published code here using a tick interrupt to generate a software UART. This would avoid the problem, and the same basic code could be used for both receive and transmit.
If any of your UART's needs transmit only, this is the one to use for a software implementation. A receive one can be done but is likely to cause more problems, but if you need full duplex, you are going to have to use a timer based solution not the CCS code.
Honestly much easier to add an external SPI slave UART. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Thu Apr 26, 2018 1:40 pm |
|
|
I think CCS SW UART will do the job, because it will work in half duplex. I don't know why receiver #int_ext1 doesn't work correct. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Thu Apr 26, 2018 1:47 pm |
|
|
The point is you are not using it half duplex. As soon as you receive a character you start sending it. While it is being sent another can't be received....
This is the timer based receive code.
<http://www.ccsinfo.com/forum/viewtopic.php?t=51403> |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Thu Apr 26, 2018 3:51 pm |
|
|
Yes, my example is not correct! If I change it as follow:
Code: | #include <33EP512MU810.h>
#device ICSP=1
#use delay(crystal=8MHz, clock=16MHz)
#FUSES NOWDT //No Watch Dog Timer
#FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOJTAG //JTAG disabled
#FUSES NOPROTECT //
#pin_select INT1=PIN_G12
#use rs232(baud=9600, xmit=PIN_G13, rcv=PIN_G12)
char c;
int1 fl = FALSE;
#int_ext1
void int1_swuart_isr() {
c=getc();
fl = TRUE;
}
#zero_ram
void main(){
delay_ms(500); // wait PLL Lock.
printf("\r\n Hello from 'SW-UART' on DsPic33Ep512MU810");
ENABLE_INTERRUPTS(INT_EXT1 | H_TO_L);
for(;;){
if(fl){
putc(c);
fl = FALSE;
}
}
} |
It's also doesn't work correct. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 26, 2018 3:55 pm |
|
|
What is the time delay between incoming bytes to PIN_G12 (Rx) ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Fri Apr 27, 2018 12:31 am |
|
|
Problem is that the same issue really exists. You have to understand that when a byte arrives, the code goes and sits inside the interrupt handler for the whole byte time it takes to arrive. Now a byte arrives. F1 gets set. The main code starts sending 'c', and if another byte then arrives, this transmission will _stop_, while the code goes into the interrupt and starts receiving the next byte. Result the transmitted byte will be garbage.
Software UART's can _only_ be used (with the standard CCS code), when there is no expectation to send at the same time as receiving.
What you post should work if there is at least one byte time between successive characters, but will (for instance) fail on a terminal program if you simply hit 'enter', since this normally sends a LF, followed by a CR. Result no time interval.... |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Fri Apr 27, 2018 1:18 am |
|
|
Hi TT, PCM
I understand you perfectly at the very beginning, but the problem is not that.
I'll wait to receive specific chat (etx) and after that will start transmitting procedure!
P.S with the latest example above I send only one byte which doesn't get correct.
Another strange thing is when mouse point 'char c' variable debugger show me 8 bytes (64 bits) variable.
Thanks! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Fri Apr 27, 2018 1:33 am |
|
|
OK. The obvious thing 'wrong', is that the default operating edge for the external interrupt is _positive_. The software UART needs to start on the negative edge. Now you try to set this in the enable_interrupt command, but I see no suggestion in the manual or .h file that the edge can be set in this command. If you look at the .h file, it says:
Quote: |
// Constants used in EXT_INT_EDGE() are:
#define L_TO_H 0x40
#define H_TO_L 0
|
So:
Code: |
ext_int_edge(INT_EXT1, H_TO_L);
clear_interrupt(INT_EXT1); //in case it is set by setting the edge
ENABLE_INTERRUPTS(INT_EXT1);
|
Some chips _do_ allow the edge to be set on specific interrupts. So (for instance):
enable_interrupts( INT_EXT_H2L );
but in these cases there is a specific define for the interrupt on this edge, listed in the .h file. Your chip does not have this..... |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Fri Apr 27, 2018 2:39 am |
|
|
Still no success with suggested settings:
Code: |
ext_int_edge(INT_EXT1, H_TO_L);
clear_interrupt(INT_EXT1); //in case it is set by setting the edge
ENABLE_INTERRUPTS(INT_EXT1); |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Fri Apr 27, 2018 12:24 pm |
|
|
OK. Change you #use rs232 to:
#use rs232(baud=9600, xmit=PIN_G13, rcv=PIN_G12, SAMPLE_EARLY)
It takes a long time to get into an interrupt. Your clock rate is quite slow. This removes the half bit time delay at the start of the software read routine. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Mon Apr 30, 2018 5:35 am |
|
|
Hello,
First sorry for my delayed response! Mr. TT with 'SAMPLE EARLY' option also have not success with software uart.
Best Regards! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Mon Apr 30, 2018 6:02 am |
|
|
OK. Have you actually tested that the software UART is working correctly?. No interrupt. Just read data from the software UART?. It's the old 'test one step at a time' advice. This has got to work _before_ you start trying to handle it using an interrupt. |
|
|
|