View previous topic :: View next topic |
Author |
Message |
cchappyboy
Joined: 03 Dec 2008 Posts: 45
|
PIC12F1840 INT_RDA & INT_TBE |
Posted: Sat Jan 07, 2012 11:24 am |
|
|
I use 4 MHz INTRC working under baud 9600
Code: |
#fuses INTRC_IO
#use delay(internal=4M)
#use 232(baud=9600,xmit=pin_a4,rcv=pin_a5)
#byte RCSTA=0x19D
#byte TXSTA=0x19e
#bit TXIE=0x091.4//pie1.4
#byte TXREG=0x19a
#byte RCREG=0x199
#bit SYNC=TXSTA.4
#bit SPEN=RCSTA.7//enable uart
#bit CREN=RCSTA.4//enable RX
int1 st=0;
#int_rda
void rx_isr()
{
int16 data=0;
data=RCREG;
if(data=='I')
{
st=!st
if(st) output_high(pin_a2);//LED on
if(!st) output_low(pin_a2);//LEN off
}
}
#int_tbe
void tx_isr()
{
int8 data=0;
if(txcount>0)
{
TXREG=tx[txcount--];
if(txcount==0) TXIE=0;
}
}
char tx[16];
void main()
{
int8 j=0;
char s[16]="THIS IS A TEST!";
/*
TXSTA=0x24;
SPBRGL=25;// set baud=9600
SPEN=1;//enable async serial
CREN=1;// enable rx
SYNC=0;//async
RXDTSEL=1;//pin_a5 rx
TXCKSEL=1;//pin_a4 tx
*/
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(true)
{
for(j=0;j<TX_SIZE;j++)
{
tx[j]=s[j];
//putc(tx[j]);
}
TXREG=0x20;
TXIE=1;
}
}
|
My questions are:
1. Please see code between /* */, if I don't add them on then it will only works with printf and putc() commmand. The interrupts INT_RDA and INT_TBE are all doesn't work.
2. So I add code between /* */ on. And the INT_RDA and INT_TBE worked but only sometimes.
Can somebody give me a help.
Thanks |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sat Jan 07, 2012 12:39 pm |
|
|
Look at the examples....
EX_STISR.C
The key point to understand, is that once the transmit buffer is empty, and you have no characters waiting to send, you have to turn off INT_TBE. Then when you want to send characters, store the first into the hardware register, then the rest into a transmit buffer, and enable INT_TBE.
For 99.9% of things, you do not need to fiddle directly with registers in CCS. Use the supplied functions instead, it is the whole 'point' of the compiler. There are a few (rare) occasions where direct accesses are needed, and this is not one of them.
You can't use INT_TBE, and then putc, in the main. Instead use a buffered putc, as in the example.
Best Wishes |
|
|
cchappyboy
Joined: 03 Dec 2008 Posts: 45
|
|
Posted: Mon Jan 09, 2012 10:20 am |
|
|
Hi Ttelmah, I tried EX_STISR.c
Please see below:
Code: |
#include <12F1840.h>
#fuses INTRC_IO
#use delay(internal=4M)
#use rs232(baud=9600, xmit=pin_a4,rcv=pin_a5)
#define T_BUFFER_SIZE 64
byte t_buffer[T_BUFFER_SIZE];
byte t_next_in = 0;
byte t_next_out = 0;
#int_tbe
void serial_isr() {
if(t_next_in!=t_next_out)
{
putc(t_buffer[t_next_out]);
t_next_out=(t_next_out+1) % T_BUFFER_SIZE;
}
else
disable_interrupts(int_tbe);
}
void bputc(char c) {
short restart;
int ni;
restart=t_next_in==t_next_out;
t_buffer[t_next_in]=c;
ni=(t_next_in+1) % T_BUFFER_SIZE;
while(ni==t_next_out);
t_next_in=ni;
if(restart)
enable_interrupts(int_tbe);
}
void main() {
enable_interrupts(GLOBAL);
printf(bputc,"\r\n\Running...\r\n");
do {
delay_ms(2000);
output_high(pin_a2);// LED on
printf(bputc,"This is buffered data\r\n");
} while (TRUE);
}
|
It doesn't work. The only worked part is the output_high(pin_a2).
I tried printf("This is a test!"); without printf(bputc,"\r\nRunning...\r\n"). and there is output on screen. So I guess the #int_tbe doesn't work. So I guess I need to do something extra, not only the
Code: | #use rs232(baud=9600, xmit=pin_a4, rcv=pin_a5) |
and enable_interrupts(INT_TBE), but something else? This is pic12f1840. Maybe this is the one out of the 99.9%. What do you think?
Thanks |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Jan 09, 2012 10:41 am |
|
|
Try using #pin select to tell the compiler that you want to use TX/RX on the pins, and then using UART1, rather than the pin numbers in the #use RS232.
There is a common problem on chips with multiple peripherals selected on individual pins, with the compiler not 'realising' you are using the hardware UART. When this happens INT_TBE, and RDA won't work.
Best Wishes |
|
|
cchappyboy
Joined: 03 Dec 2008 Posts: 45
|
|
Posted: Mon Jan 09, 2012 11:31 am |
|
|
Thanks Ttelmah.
It looks it 's not in this case.
I put there whatever it is
Code: |
#pin_selects tx=pin_a4
#pin_selects rx=pin_a5 |
or
Code: |
#pin_selects tx1=pin_a4
#pin_selects rx1=pin_a5 |
or
Code: |
#pin_selects u1tx=pin_a4
#pin_selects u1rx=pin_a5
|
they all show
Quote: |
*** Error 7 "TXINT.c" Line 6(12,22): Invalid Pre-Processor directive Invalid Pin ID |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Jan 09, 2012 2:34 pm |
|
|
Have you tried just using UART as opposed to the pins in the setup?.
Best Wishes |
|
|
cchappyboy
Joined: 03 Dec 2008 Posts: 45
|
|
Posted: Tue Jan 10, 2012 11:38 am |
|
|
No I didn't do that because the hardware pins set should be pin_a4 is TX and pin_a5 is RX.
I add some code to my program and now it works with #int_ and #int_tbe
Code: |
#bit RXDTSEL=APFCON.7//if =1 pin_a5 to be rx ,=0 Pin_a1
#bit TXCKSEL=APFCON.2// if =1 pin_a4 to be tx,
#bit TXEN=TXSTA.5
#bit TXIE=0x091.4//pie1.4
#bit SPEN=RCSTA.7//enable uart
#bit CREN=RCSTA.4//enable RX
#bit SYNC=TXSTA.4
|
in the main()
add on
Code: |
TXSTA=0x04;
SPBRGL=25;//set baud=9600
TXEN=1;//when async =1 enable tx
SPEN=1;//async enable
CREN=1;//when it is async =1 enable rx
SYNC=0;
RXDTSEL=1;//pin_a5 RX
TXCKSEL=1;//PIN_A4 TX
|
I don't know why but if i just rely on the command
Code: | #use rs232(baud=9600, xmit=pin_a4,rcv=pin_a5)
|
and
Code: |
enable_interrupts(INT_RDA);
enable_interrupts(INT_TBE);
enable_interrupts(GLOBAL);
|
it doesn't work.
I am not sure is that compiler's issue or something else.
And i think the #pin_selects doesn't work for this chip pic12f1840 that is only 8 pins and the pins are not selectable.
I have experience with 33fj128mc804 it does work for it by not in this case.
Anyways Thank you so much for your concern and help. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Tue Jan 10, 2012 3:01 pm |
|
|
There are issues with several of the newer chips where multiple peripherals exist on one set of pins. The compiler in a lot of cases doesn't quite get it right.
In several cases though it _will_ work correctly if you just select the UART, rather than using the pin number. It knows where the UART hardware is, and uses it. When pins are selected, because the UART is so far down the list of things on the pins, this is when it gets confused, and switches to using the software UART instead.
Best Wishes |
|
|
|