|
|
View previous topic :: View next topic |
Author |
Message |
carlosma
Joined: 24 Mar 2004 Posts: 53 Location: Portugal
|
error char with #int_ext and #int_asr |
Posted: Wed Jun 30, 2004 7:08 am |
|
|
Hello:
My program send and receive data for Modem and PC. Have a real time clock to register event and send AT command to modem.
When I receive the data from software port, have a char error like �����������������.
It liked to know if the Interrupt OK
Code: |
#include <16F877.h>
#fuses HS,NOPROTECT,NOWDT,NOLVP,PUT,NOBROWNOUT
#use delay(clock=16000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, STREAM=COM_A)
#USE RS232(BAUD=9600, XMIT=PIN_B1, RCV=PIN_B0, STREAM=COM_B)
#int_ext //interrupt for sotftware COM_B USART port
void vira()
{
dado_b=fgetc(COM_B);
dado_b=toupper(dado_b);
fputc(dado_b,COM_B);
}
#int_rda //interrupt for hardware COM_A USART port
void seirala_isr()
{
cmd=fgetc(COM_A);
cmd=toupper(cmd);
fputc(cmd, COM_A);
}
#int_timer0 //interrupt for real time clock
timer0_isr()
{
clock-=256; // 256 > dois elevado a 8
if(clock<256)
{
clock+=CLOCK_VAL;
tick=1;
seconds++;
}
}
void init_chip()
{
setup_adc_ports(No_Analogs);
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_32);
enable_interrupts(int_timer0); // Enable timer0 interrupt
enable_interrupts(INT_RDA);
enable_interrupts(int_ext);
enable_interrupts(GLOBAL);
}
//...
void main()
{
static boolean led2;
init_ext_eeprom();
init_chip();
fprintf(COM_A,"\r\nRead or Write: ");
while(1)
{
if (tick) // real time clock 1 second
{
tick=0;
update_clock();
led2 = !led2; // led flash 1 second
output_bit (pin_c0,led2);
}
if(dado_b=='A')
fprintf(COM_A,"Tunga........->");
if(cmd=='R')
{
//...
read_eeprom_string(s, ROM_SMTP, ROM_SMTP_SIZE);
fprintf(COM_B,"AT#ESMTP=\"%s\"\r\n",s);
//...
}
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Jun 30, 2004 10:14 am |
|
|
Code: | #int_ext //interrupt for sotftware COM_B USART port
void vira()
{
dado_b=fgetc(COM_B);
dado_b=toupper(dado_b);
fputc(dado_b,COM_B);
} |
This is not going to work for two reasons:
1) Don't put an fputc under software control in your interrupt routine! It will take as long as sending the whole character, resulting in the loss of an character on your receive pin.
2) The int_ext interrupt will be triggered on the first edge of the received start bit. Then your call to fgetc() will also wait for detection of a start bit... There are no 2 start bits and you are out of sync resulting in the garbage data you showed.
Conclusion: The CCS routines for software emulation of an UART are not compatible with interrupts. It is difficult, but possible, to create an interrupt based software UART. Search this forum for examples. |
|
|
Ttelmah Guest
|
|
Posted: Wed Jun 30, 2004 10:58 am |
|
|
Two comments.
You need to program the external interrupt to be on the falling edge.
Secondly (and more probably the problem), you may well find it impossible to do what you want at this baud rate, with everything else going on. At 9600bps, the 'bit time', is just 104uSec. Your processor clock gives 4 million instructions per second. Unfortunately, the behaviour will depend on the sequence of events, but if (for instance), your code is allready in the 'timer' interrupt, when the edge occurs on the software RS232, it'll take perhaps as much as 100 instructions, to execute this routine, then enter the software handler, which itself takes perhaps another 30 instructions. The software handler can be used in an interrupt like this, _but_ the routine will assume that the 'edge' of the start bit has occured at the momnt the fgetc is called (it looks for levels, not 'edges'). Hence the sample timing in the data, could be as much as 50u to 60uSec 'late' in the example given. In fact this is only a guess, and is probably an underestimate. I'd not expect this to work reliably, with any other interrupt in use, at baud rates above perhaps 1200bps...
I'm afraid you need to rethink your hardware to make this work properly.
Best Wishes |
|
|
carlosma
Joined: 24 Mar 2004 Posts: 53 Location: Portugal
|
|
Posted: Wed Jun 30, 2004 1:43 pm |
|
|
hello
now the system works, because I added the line:
Code: |
ext_int_edge( H_TO_L ); // Sets up EXT
|
Carlos |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Jun 30, 2004 4:15 pm |
|
|
Congatulations! You have proven my second point to be wrong.
Still, the other remarks (from me and Ttelmah) are still standing and I hope you give them a serious thought... |
|
|
carlosma
Joined: 24 Mar 2004 Posts: 53 Location: Portugal
|
|
Posted: Thu Jul 01, 2004 2:36 am |
|
|
Thanks for all
both the PORTS, COM_A and COM_B function when sending or receive char, but I think that I go to have problems when to try to send strings.
To reduce the problems I go to lower baud rate.
Carlos |
|
|
Ttelmah Guest
|
|
Posted: Thu Jul 01, 2004 7:27 am |
|
|
carlosma wrote: | Thanks for all
both the PORTS, COM_A and COM_B function when sending or receive char, but I think that I go to have problems when to try to send strings.
To reduce the problems I go to lower baud rate.
Carlos |
It is much more likely to be reliable on the software receive, in the long run. However there is then another 'caveat'. Unfortunately, while it is receiving the character inside the ISR, all the other interrupts are effectively disabled if you run the soft uart at 1200, and data arrives on the 9600bps 'hardware' link while you are in the ISR, if more tha a couple of characters arrive, you will trigger a com overrun on the hardware link, and lose data. So long as none of your interrupt routines are going to get any longer, stick at 9600bps, use the #priority statement to set the software receive isr to have the highest priority, followed by the hardware serial receive, and do some testing.
Best Wishes |
|
|
carlosma
Joined: 24 Mar 2004 Posts: 53 Location: Portugal
|
|
Posted: Thu Jul 08, 2004 12:26 pm |
|
|
After some alterations, I continue with problems in both Interrupts, because I can't read the data incoming by Modem GSM on EXT_INT.
When I test with hyperterminal all the system work fine but not with modem.
Only wanted to read the "RING" or "OK"
now my code:
Code: |
#use delay(clock=16000000)
#use rs232(baud=1200, xmit=PIN_C6, rcv=PIN_C7, STREAM=COM_B) //hardware
#USE RS232(BAUD=9600, XMIT=PIN_B1, RCV=PIN_B0, STREAM=COM_A)
//...
#int_rda
void vira()
{
char c;
c=fgetc(COM_B);
if ((c>=' ')&&(c<='~'))
{
buffer1[len] = c;
len++;
}
if(c==0x0A ||c==0x0D) // I gues End Of String
{
bit_com_b=1; // All OK
}
if(len >= BUFFER_SIZE)
{
//bit_set(ModemFlag,RecErr); // Something wrong !!
disable_interrupts(INT_RDA); // Get out & ovoid reentrance
len=0;
}
fputc(c, COM_A);//just for test arrive char
}
#int_ext
void seirala_isr()
{
cmd=fgetc(COM_A);
cmd=toupper(cmd);
fputc(cmd, COM_A);
}
//..
// now, read and compare with String "RING" or "OK"
read_eeprom_string(s, ROM_ackmodem, ROM_askmodem_SIZE);
if (strncmp (buffer1, s, 5)==0)
{
fprintf(COM_A,"\r\nComutado\r\n");
disable_interrupts(INT_RDA);//disable interrupt port b
fprintf(COM_B,"AT+CMGR=1\n");
delay_us( 1000 );
enable_interrupts(INT_RDA);
len=0;
bit_com_b=0;
|
Thank you |
|
|
|
|
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
|