View previous topic :: View next topic |
Author |
Message |
lucadjr
Joined: 08 Apr 2014 Posts: 3
|
16f877a problem rs232 and delay_ functions |
Posted: Tue Apr 08, 2014 5:01 pm |
|
|
Hi all!!
I'm sorry to write on forum for a so stupid answer for almost of all but i can't get out..
I can't have a very simple working routine with a putc() and a delay_ms(500) together in the same while1...
Code: |
#include <RS232doppio.h>
//#include <stdlib.h>
#define LCD_ENABLE_PIN PIN_D3
#define LCD_RS_PIN PIN_D2
#define LCD_RW_PIN PIN_D1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#define codifica PIN_C0
#include <lcd.c>
#use rs232 (baud=9600, xmit=pin_c6, rcv=pin_c7, parity=N, stop=1, bits=8)
char rxMESS;
char txMESS;
#int_rda
void rda_isr()
{
rxMESS=getc();//delay_ms(10)
}
void main(){
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
lcd_init();
delay_ms(100);
txMESS=0;
while(1)
{
putc(txMESS);
if (input(codifica)==0){
txMESS++;
}
else{
txMESS--;
}
output_high(PIN_B3);
lcd_putc("\f");
lcd_putc("SINISTRA ricevo ");
printf(lcd_putc,"%d", rxMESS);
lcd_putc("\n invio ");
printf(lcd_putc,"%d", txMESS);
output_low(PIN_B3);
delay_ms(500);
}
}
|
This work perfectly in double pic comunication on Proteus but nothing arrive to hyperterminal.
Everything is ok if i put // to all my delay_ms in the code
Anyone have answer or I'm just in a stupid mystake??? |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Apr 08, 2014 5:07 pm |
|
|
Work on the KISS principal.
Get rid of Proteus/ISIS.
Use real hardware.
Test one thing at a time.
Learn to use the code button.
Post short, complete, compilable code we can copy & paste to test.
Mike |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9291 Location: Greensville,Ontario
|
|
Posted: Tue Apr 08, 2014 7:38 pm |
|
|
What Mike says plus...
always add 'errors' to to the use rs232(...options...), as it prevents the UART from 'locking up' after 3 characters...
always add a delay)ms(500); BEFORE the lcd_init(); function. This allows the LCD hardawre to 'get organized' before the PIC tries to access it.
also have a look at the examples that CCS supplies to see how to code.
hth
jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 08, 2014 8:13 pm |
|
|
Quote: | #int_rda
void rda_isr()
{
rxMESS=getc();//delay_ms(10)
}
|
The problem is the same issue we get at least once a week on this forum.
He has a delay_ms() statement in his #int_rda and in his main().
The compiler is disabling interrupts during all delay_ms() statements in
main(), because the delay_ms() routine is not re-entrant in CCS.
The best solution is to just remove the delay_ms() from the #int_rda
routine. There's no reason to ever have a delay statement inside your
#int_rda routine. |
|
|
lucadjr
Joined: 08 Apr 2014 Posts: 3
|
rs232 problem |
Posted: Wed Apr 09, 2014 2:50 am |
|
|
Thx all for interest and quick answer!
I'm looking for a similar problem in internet since a week and didnt find, seems to be im the only one who want to have putc and delay funcions in while(1) together.
Quote: | Work on the KISS principal.
Get rid of Proteus/ISIS.
Use real hardware.
Test one thing at a time.
Learn to use the code button.
Post short, complete, compilable code we can copy & paste to test. |
I cant write more stupid than this, this is just a test for implement rs232 in a bigger project and i cant use real hardware now :(
hope the code now is "compatible" to copy and paste, sorry im newbie of this forum.
This is more simple code to explain better what is my problem
Code: |
#include <RS232doppio.h>
#include <lcd.c>
#define LCD_ENABLE_PIN PIN_D3
#define LCD_RS_PIN PIN_D2
#define LCD_RW_PIN PIN_D1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#define codifica PIN_C0
#use rs232 (baud=9600, xmit=pin_c6, rcv=pin_c7, parity=N, stop=1, bits=8, ERRORS)
char rxMESS;
char txMESS;
#int_rda
void rda_isr()
{
rxMESS=getc();
}
void main(){
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
delay_ms(500);
lcd_init();
delay_ms(500);
txMESS=0;
while(1)
{
putc(txMESS);
txMESS++;
output_high(PIN_B3);
lcd_putc("\f");
lcd_putc("receive");
printf(lcd_putc,"%d", rxMESS);
lcd_putc("\n send ");
printf(lcd_putc,"%d", txMESS);
output_low(PIN_B3);
delay_ms(500);
}
}
|
my problem is the last delay_ms(500) in the while (1) routine, when it is hyperterminal dont receive tx from pic, when its not everything work well.
On 2 pic comunication no problem with or without delay. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Apr 09, 2014 10:18 am |
|
|
I said COMPILABLE not COMPATIBLE.
I want to be able to copy & paste your code, than run it as is.
Your code is not complete is any sense.
You do not tell us which PIC or compiler version you are using.
I do not have Proteus/ISIS, so test on REAL hardware only.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19615
|
|
Posted: Wed Apr 09, 2014 11:32 am |
|
|
There is a key thing to understand.
9600bps serial characters can potentially arrive at around 1000 characters per second.
Even if you are typing them, and 'think' you are only sending single characters, you can easily be sending multiple characters at a time (just hit enter - immediate CR+LF in most configurations.).
The serial ISR, must do just one job. Receive a character. Save it. Exit ASAP.
Delays break number 3 (in a 10mSec delay, 9 more characters could have arrived - immediate hardware overflow.....). Worse though is that because the PIC does not have a software stack, code must not be 're-entrant' (can't be called inside itself). So if you put a delay in the ISR, and then another in the main code, the compiler _has_ to ensure the ISR cannot be called from inside the delay in main.
There is no reason to delay in the ISR. If you want to delay the response, then do this outside in the main code. Re-write the ISR, so it uses a larger buffer (to deal with multiple characters arriving one after the other.
Look at the thread about 'RTC frequency of 1Hz'. Look at the suggestions for how to delay output, without using an actual delay in the main loop. Realise that this would apply to you as well. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Apr 09, 2014 3:07 pm |
|
|
Code: | #include <lcd.c>
#define LCD_ENABLE_PIN PIN_D3
#define LCD_RS_PIN PIN_D2
#define LCD_RW_PIN PIN_D1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7 | Why did you change this from your first program???
The LCD data pin defines must be located before the #include !!! |
|
|
lucadjr
Joined: 08 Apr 2014 Posts: 3
|
|
Posted: Thu Apr 10, 2014 8:40 am |
|
|
Quote: | I said COMPILABLE not COMPATIBLE.
I want to be able to copy & paste your code, than run it as is.
Your code is not complete is any sense.
You do not tell us which PIC or compiler version you are using.
I do not have Proteus/ISIS, so test on REAL hardware only.
Mike |
Sorry Mike! I'm using CCS C 5.008 and the only thing i didn't write is the RS232.h file here below
Code: | #include <16F877A.h>
#device ADC=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(crystal=20000000,restart_wdt) |
Quote: | ...........Look at the thread about 'RTC frequency of 1Hz'. Look at the suggestions for how to delay output, without using an actual delay in the main loop. Realise that this would apply to you as well. |
Thx very much Ttelmah! i understood the example and Timer is a thing i will test but i prefer to use not in this case.
REALLY THERE IS NO WAY TO DO SOMETHING LIKE:
Code: | while(1) {
putc(txMess);
delay_ms(123);
} |
???????????
Quote: | Why did you change this from your first program???
The LCD data pin defines must be located before the #include !!! Rolling Eyes |
I changed just to make a more understandable, i didn't test it and i don't know it will work.
Again thx very much all for help!! i studied this things at school many years ago and its very difficult now to do it without a teacher that kick me when I'm wrong... xD |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1362
|
|
Posted: Thu Apr 10, 2014 10:33 am |
|
|
I have a spare hardware board with an LCD, but it is a different model LCD and the PIC is a PIC24 chip.
I tossed in your program changing my FUSES, #use delay, pin assignments, and the program ran fine. I saw no problems with the output. Every character that I typed went through without an issue and was displayed.
Something to note:
Your pic's receiver buffer is only 2 chars deep. If it receives more than that during the delay, you'll miss chars
This means your problem is likely:
Proteus issue
Some code other than the test program you posted
LCD initialization (my LCD has a different initialize than yours) |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19615
|
|
Posted: Fri Apr 11, 2014 8:23 am |
|
|
Yes.
There is no problem at all in doing:
Code: |
while(1) {
putc(txMess);
delay_ms(123);
}
|
So long as you don't delay in the INT_RDA, and rewrite the interrupt handler to use a reasonable sized buffer.
Key difference with Jeremiah's chip, is larger hardware buffers.
Use ex_sisr.c as an example of how to handle INT_RDA. If you want to delay after a character is received (only reason to have a delay in INT_RDA), then use:
Code: |
char c;
//Inside the main loop
if (bkbhit())
{
c=bgetc(); //get the character from the buffer
delay_ms(xxx); //delay if you want
//do what you want with the character.
}
|
|
|
|
|