View previous topic :: View next topic |
Author |
Message |
jaikumar
Joined: 15 Dec 2006 Posts: 109
|
PIC16F1779 UART PROBLEM - Garbage when sending data |
Posted: Sat Jul 29, 2023 7:58 am |
|
|
Hi,
I am working on a simple UART code with RX interrupt. I am getting garbage when sending read data back. Here is my code. any help would be great.
ccs version 5.115
main.h file
Code: |
#include <16F1779.h>
#device ADC=10
#use delay(xtal=8000000)
#fuses XT NOMCLR NOBROWNOUT NOWDT NOLVP
#use pwm(CCP1,OUTPUT=PIN_B5,TIMER=2,FREQUENCY=20000,DUTY=0)
#define RX_PIN PIN_C7
#define TX_PIN PIN_C6
#pin_select U1RX = RX_PIN
#pin_select U1TX = TX_PIN
#use rs232(UART1,baud=9600,parity=N,xmit=TX_PIN,rcv=RX_PIN,bits=8,DISABLE_INTS)
|
main.c file
Code: |
#include <main.h>
#define RELOAD (int16)33600 //50ms pulse
#define BUFFER_SIZE 16
/*
PIN_B5 PWM
PIN_B4 DRIVER DIR
TIMER1 PIN_C0
*/
typedef enum{
idle,
RxReceived
}stateControl;
volatile int8 delay50ms = 0;
stateControl currentState;
byte RxBuffer[BUFFER_SIZE];
byte RxDataCount = 0;
byte i = 0;
#INT_TIMER1
void timer1_isr(void)
{
clear_interrupt(INT_TIMER1);
set_timer1(RELOAD);
delay50ms = 1;
}
#INT_RDA
void rda_int(void)
{
RxBuffer[RxDataCount++]=getc();
}
void main()
{
setup_wdt(WDT_OFF);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4); //104 ms overflow
clear_interrupt(INT_TIMER1);
set_timer1(RELOAD); // Preload value
enable_interrupts(INT_TIMER1); // Enable Timer1 interrupt
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
output_low(PIN_B2);
output_low(PIN_B4);
RxDataCount = 0;
currentState = idle;
while(TRUE)
{
switch (currentState)
{
case idle: if (RXDataCount > 14)
{
currentState = RxReceived;
}
break;
case RxReceived:
disable_interrupts(GLOBAL);
for (i=0; i<16; i++)
{
putc(RxBuffer[i]);
}
RXDataCount = 0;
currentState = idle;
enable_interrupts(GLOBAL);
break;
}
}
}
|
Last edited by jaikumar on Sat Jul 29, 2023 8:01 am; edited 1 time in total |
|
|
jaikumar
Joined: 15 Dec 2006 Posts: 109
|
|
Posted: Sat Jul 29, 2023 7:59 am |
|
|
This is the data sent:
31 32 33 34 35 36 37 38 39 30 31 32 33 34 35
data received back in terminal
71 7E 74 8F 77 79 71 7E 74 0F |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Sat Jul 29, 2023 9:16 am |
|
|
On this:
#use rs232(UART1,baud=9600,parity=N,xmit=TX_PIN,rcv=RX_PIN,bits=8,DISABLE_INTS)
Change to:
use rs232(UART1,baud=9600,parity=N,bits=8)
Also you don't need to clear interrupt in the timer interrupt, the compiler
does this for you.
XT is wrong for an 8MHz crystal. Wants to be HS. However why not use the
PLL?. Run at 32Mhz from the 8MHz crystal.
Describe (or post a link to a picture of the circuit), how the actual
serial connections are made. |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 478 Location: Montenegro
|
|
Posted: Sat Jul 29, 2023 9:24 am |
|
|
Can you confirm that your RX buffer contains correct characters before sending them out? |
|
|
jaikumar
Joined: 15 Dec 2006 Posts: 109
|
|
Posted: Sat Jul 29, 2023 11:24 pm |
|
|
The actual problem was the crystal in the board. It is marked 8Mhz but it
produces about 10.21 or something like that Mhz. Used the internal oscillator and everything is fine.
I would like to thank everybody for helping me. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Sun Jul 30, 2023 8:47 am |
|
|
Did you correct the fact that you were driving it incorrectly?... |
|
|
jaikumar
Joined: 15 Dec 2006 Posts: 109
|
|
Posted: Sun Jul 30, 2023 10:33 am |
|
|
Yes Ttelmah, I did change the fuse to HS and made the alteration that you said regarding the UART. But the software was asking for PIN setting(PPS). and once that was chosen it is working now. Once again thanks for your help. Regards. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Mon Jul 31, 2023 5:28 am |
|
|
That's an unusual failure for a crystal. Normally they will only lock onto
undertones or harmonics. I remember one poster here a while ago, had a
crystal that he thought was a particular frequency, but when he checked
the ID code on the case, was actually completely different.
The only time I've seen odd frequencies like that was when I had a batch
where the hermetic sealing had failed, and after washing the boards all
gave really odd values.
Sounds like it may just be a faulty unit. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1345
|
|
Posted: Mon Jul 31, 2023 7:45 am |
|
|
Ttelmah wrote: |
#use rs232(UART1,baud=9600,parity=N,xmit=TX_PIN,rcv=RX_PIN,bits=8,DISABLE_INTS)
Change to:
use rs232(UART1,baud=9600,parity=N,bits=8)
|
I would further recommend:
Code: |
use rs232(UART1,baud=9600,parity=N,bits=8,ERRORS)
|
For the OP's benefit, the reason you remove the xmit= and rcv= parts is that the combination of the #pin_select's and the UART1 in the #use rs232() tell it the pins. You generally only use xmit= and rcv= for software UARTs.
The DISABLE_INTS option is for software UARTS as well. Since you are using a hardware UART, you don't need those options. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Mon Jul 31, 2023 9:51 am |
|
|
Well said.
Just to further explain. The PIC UART has the behaviour that on the
RX side, if data is not reliably read when it becomes available if the
internal FIFO becomes full (normally on the second or third character
depending on the chip), OERR gets set, and receive hangs. Adding
'ERRORS' adds a tiny extra test to getc, so if the UART is in this state,
the compiler will flag this, and clear the error.
Basically you should always have ERRORS unless you add your own
error handling. |
|
|
jaikumar
Joined: 15 Dec 2006 Posts: 109
|
|
Posted: Mon Jul 31, 2023 11:45 am |
|
|
Understood.
Regards. |
|
|
|