View previous topic :: View next topic |
Author |
Message |
curt2go
Joined: 21 Nov 2003 Posts: 200
|
16F1823 UART Problems |
Posted: Tue Mar 27, 2012 10:47 am |
|
|
I am having problems with setting up the UART on this device. It is especially hard not being able to be in Debug mode. I am using the A1 pin to receive because I need the PWM where it is. So I cannot get the RDA interrupt to fire. I know I am getting info sent to it with the right baud rate. It is PIC to PIC communication from a 18F87K22 pic. So below is the code I have put together so far.
Compiler 4.128
Any help would be appreciated.
Code: |
#include <16F1823.h>
#device ICD=TRUE
#device adc=10 *=16
//#FUSES WDT2048 //No Watch Dog Timer
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc
//#FUSES LPT1OSC
#FUSES NOPUT //No Power Up Timer
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES PROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#FUSES BROWNOUT //No brownout reset
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWRT //Program memory not write protected
//#fuses NOXINST
//#fuses CCP2B3 //mux the ccp2 output to pin b3
//#FUSES BORV42 //Brownout reset at 4.0V
#use delay(clock=250000)
#use rs232(baud=1200,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8,errors)
#bit APFCON = 0x11D.7
#bit ANSELA = 0x18C.1
#bit TRISA_1 = 0x08C.1
#bit CREN = 0x019D.4
#bit SPEN = 0x019D.7
#bit SYNC = 0x019E.4
int rx_count = 0;
char rx_buffer[10];
char timed_getc() {
long timeout;
timeout=0;
while(!kbhit()&&(++timeout<500)) // 1/2 second
delay_us(10);
if(kbhit())
return(getc());
else {
return(0);
}
}
void check_incomming(){
long int what_pwm = 0;
//if(rx_buffer[0] == '*'){
what_pwm = (rx_buffer[1] * 1000) + (rx_buffer[2] * 100) + (rx_buffer[3] * 10) + (rx_buffer[4]);
set_pwm1_duty(90);
//}
rx_count = 0;
}
#INT_RDA
void Serial_Receive()
{
char new_char;
new_char = timed_getc();
clear_interrupt(INT_RDA);
rx_buffer[rx_count] = new_char;
//if(new_char == 0x0A)//we haev got an LF then go look......
check_incomming();
rx_count++;
}
void main(){
SETUP_CCP1(CCP_PWM);
setup_timer_2 ( T2_DIV_BY_4, 0xC4,1); // setup_timer_2 ( T2_DIV_BY_16, 0xc0, 2);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
setup_oscillator(OSC_250KHZ);
APFCON = 1; //set RX for pin A1
ANSELA = 0;
TRISA_1 = 1;
//CREN = 1;
//SPEN = 1;
//SYNC = 0;
while(1){
if(kbhit())
serial_receive();
//set_pwm1_duty(90);
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Tue Mar 27, 2012 2:37 pm |
|
|
Because you are setting APFCON yourself, and not letting the compiler do it. the compiler _will_ be generating the code for software RS232, not hardware. Hence just about nothing will work....
You need to tell the compiler that you want to use the hardware UART. Simplest change, since you are overriding the APFCON register yourself, is to get rid of the pin definitions in the #USE RS232, and just say 'UART1'. This tells the compiler to generate code to use the hardware UART, which if your other settings are right, should then start to have a chance of working.
Then, INT_RDA, _only_ triggers when a character _is_ waiting to be read. All the 'timed getc' stuff is pointless, and risks making things not work.
You don't need to clear interrupts in INT_RDA. The compiler already does this for you.
Then _get rid of the maths in the interrupt routine_. This takes much too long to have in an interrupt. At 250KHz master clock, the four 16bit multiplications on a PIC16, will take over 15000uSec. Given that your serial data rate allows characters to arrive every 8.3mSec, _you cannot do this_. You _must_ just buffer the data, and get out, doing this work in the main code. EX_SISR, shows how to buffer the serial data.
Finally, you can't call the interrupt routine from the main code. Doing this, means that interrupts _will_ be disabled for large amounts of the time.
Best Wishes |
|
|
curt2go
Joined: 21 Nov 2003 Posts: 200
|
|
Posted: Tue Mar 27, 2012 2:43 pm |
|
|
I will give the UART1 a try. I did originally try that with not setting anything manually
Code: | #use rs232(baud=1200,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8,errors)
|
but could not get it to work. Yeah I know the routines are big right now I was just trying to get something to work and the kbhit being in the main routine was just there to see if the other routines did something. It was taking a long time to get anything to work so I was just trying stuff. So I will give it a shot and get back to you. Thanks for the response. TTY |
|
|
curt2go
Joined: 21 Nov 2003 Posts: 200
|
|
Posted: Tue Mar 27, 2012 5:42 pm |
|
|
Gave this code a try.. No luck.. In this version just trying to set an LED when the interrupt fires. The LED is on all the time.. Very confused.. Any thoughts..
#include <16F1823.h>
#device ICD=TRUE
#device adc=10 *=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NODEBUG //No Debug mode for ICD
#use delay(clock=250000)
#use rs232(BAUD=1200,parity=N,UART1,bits=8,errors)
#bit APFCON = 0x11D.7
#bit ANSELA = 0x18C.1
#bit TRISA_1 = 0x08C.1
#bit CREN = 0x019D.4
#bit SPEN = 0x019D.7
#bit SYNC = 0x019E.4
#INT_RDA
void Serial_Receive() {
char gg= 0;
output_high(pin_a2);
gg = getc();
}
void main(){
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
setup_oscillator(OSC_250KHZ);
//APFCON = 1; //set RX for pin A1
//ANSELA = 0;
TRISA_1 = 1;
CREN = 1;
SPEN = 1;
SYNC = 0;
while(1){
output_low(pin_a2);
}
} |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Mar 27, 2012 5:45 pm |
|
|
I tested the following program with vs. 4.130 in hardware and it works OK.
(It doesn't work if I specifiy UART1 instead of the pin numbers).
With vs. 4.128, the compiler always generates a software UART
if I specify the pins, or if I specify UART1.
Code: |
#include <16F1823.H>
#fuses INTRC_IO, NOWDT, NOMCLR
#use delay(clock=32M)
#use rs232(baud=9600, xmit=PIN_A0, rcv=PIN_A1, errors)
#int_rda
void rda_isr(void)
{
char c;
c = getc();
putc(c);
}
//========================================
void main()
{
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(1);
} |
|
|
|
curt2go
Joined: 21 Nov 2003 Posts: 200
|
|
Posted: Tue Mar 27, 2012 5:58 pm |
|
|
I stuck in my output_high(pin_a2); in the INT and its not working. Do I need version 4.130? to use the interrupt? I used your code. SO either my board is whacked or ? was your comms pic to pic that you tested? Thanx for the help.. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Mar 27, 2012 9:37 pm |
|
|
The rs232 was between the 16F1823 and my PC. I used TeraTerm as
the terminal program. The 16F1823 was installed in a Microchip "Low Pin
Count" board. I used a Sparkfun Level Shifter to convert the TTL voltage
levels from the PIC to rs232 levels:
http://www.sparkfun.com/products/449
If you can get vs. 4.130, then it should solve your problem. |
|
|
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Tue Mar 27, 2012 9:45 pm |
|
|
Note that according to an email I got today, 4.131 of the compiler is now out.
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
|
curt2go
Joined: 21 Nov 2003 Posts: 200
|
|
Posted: Tue Mar 27, 2012 10:17 pm |
|
|
Bought the update. Mine ran out in Jan. $275 for a bug. If it works then I will be happy. I will post tomorrow the results.
I do wish when you order the updates that you can get them right away instead of waiting for CCS to manually enter stuff. But I digress. |
|
|
curt2go
Joined: 21 Nov 2003 Posts: 200
|
|
Posted: Wed Mar 28, 2012 10:59 am |
|
|
Works good with 4.131.... It was the compiler... But it works so I am very happy.. Thanx for everyones help.. |
|
|
|