CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Problem with UART - PIC16LF1827
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Dave_25152



Joined: 11 Dec 2010
Posts: 60

View user's profile Send private message

Problem with UART - PIC16LF1827
PostPosted: Sat Jun 23, 2012 8:44 am     Reply with quote

Hello all.

I am doing a very simple program and I am having some problems with it.

What happens is that when sending information for the first time, everything is fine, but the following data, it starts giving problems.

The program:

Code:
#include "16lf1827.h"
#include <stdlib.h>
#use delay (clock=1000000)
#fuses INTRC_IO, NOLVP, NOWDT, NOMCLR, NOIESO
#use RS232(baud=4800, xmit=PIN_B2,rcv=PIN_B1,PARITY=N,BITS=8,STOP=1,stream=uart)


int1 a;
unsigned int valor[4];   //4 caracteres

#INT_RDA
void serial()
{
fgets(valor, uart);

disable_interrupts(INT_RDA);     //activated only after all the calculations
clear_interrupt(INT_RDA);

a=0;
}


void pic_init()
{

output_A(0);
output_B(0);

set_tris_a(0b00000000);
set_tris_b(0b00000010);

setup_adc(0);
setup_oscillator(OSC_1MHZ);
setup_timer_2(T2_DIV_BY_64,510,1);
setup_timer_4(T2_DIV_BY_64,510,1);
setup_ccp1(CCP_PWM|CCP_TIMER2);
setup_ccp2(CCP_PWM|CCP_TIMER4);
setup_uart(4800);
ENABLE_INTERRUPTS(global);
ENABLE_INTERRUPTS(INT_RDA);
}


void MAIN()
{

unsigned int16 servo1, servo2, num, veloc;
unsigned int tipo, i;


pic_init();

servo1=0;
servo2=0;
tipo=0;

set_pwm1_duty(servo1);
set_pwm2_duty(servo2);

a=1;

loop:

while(a);      //wait for interrupt

printf (valor);

num=atol(valor);

tipo=num/1000;

veloc=num-(tipo*1000);


printf("\n\n\r velocidade=%Ld\n\n\r", veloc);

printf("\n\n\rtipo=%d\n\n\r", tipo);


fim_loop:

for(i=0; i<=3; i++)        //colocar tudo a zero
   valor[i]=0;

a=1;

output_high(pin_A6);
delay_ms(250);
output_low(pin_A6);

enable_interrupts(INT_RDA);      //enable interrupt

goto loop;

}






Surely the problem is very simple to solve, but I'm not seeing how the resolution.




Thank you.
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Jun 23, 2012 10:12 am     Reply with quote

1) always add 'errors' to the use rs232(...) line as it'll keep the hardware UART from 'locking up'.

2) delete the disable, enable interrupt code inside the ISR. The ISR actually does this for you!

3)unless you're using fast_io(), delete the set_tris_()... lines, letting the compiler automatically handle the I/O...
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat Jun 23, 2012 10:20 am     Reply with quote

Quote:
unsigned int valor[4]; //4 caracteres

You've defined valor as a 4 character array.

So what do these lines do?
Quote:
printf (valor);
num=atol(valor);

Reduce your code to test your problem area ONLY.

Add printf lines to test intermediate values of num etc.

Do NOT use GOTO. You could define a while(1) loop instead.

Make your code more readable with indentation.

Mike
Dave_25152



Joined: 11 Dec 2010
Posts: 60

View user's profile Send private message

PostPosted: Sat Jun 23, 2012 11:30 am     Reply with quote

Thanks for the replies.

I followed your suggestions, but now I have no response from the PIC.

Code:
#include "16lf1827.h"
#include <stdlib.h>
#use delay (clock=1000000)
#fuses INTRC_IO, NOLVP, NOWDT, NOMCLR, NOIESO
#use RS232(baud=4800, xmit=PIN_B2,rcv=PIN_B1,PARITY=N,BITS=8,STOP=1,stream=uart, ERRORS)
#use fast_io(A)
#use fast_io(B)


int1 a;
unsigned int valor[4];   //4 numeros

#INT_RDA
void serial()
{
clear_interrupt(int_RDA);

fgets(valor, uart);

a=0;
}


void pic_init()
{

output_A(0);
output_B(0);

set_tris_a(0b00000000);
set_tris_b(0b00000010);

setup_adc(0);
setup_oscillator(OSC_1MHZ);
setup_timer_2(T2_DIV_BY_64,510,1);
setup_timer_4(T2_DIV_BY_64,510,1);
setup_ccp1(CCP_PWM|CCP_TIMER2);
setup_ccp2(CCP_PWM|CCP_TIMER4);
setup_uart(4800);
ENABLE_INTERRUPTS(global);
ENABLE_INTERRUPTS(INT_RDA);
}


void MAIN()
{

unsigned int16 servo1, servo2, num, veloc;
unsigned int tipo, i;


pic_init();

servo1=0;
servo2=0;
tipo=0;

set_pwm1_duty(servo1);
set_pwm2_duty(servo2);

a=1;

while(1)
{

while(a);      //espera pela interrupção

printf (valor);

num=atol(valor);

tipo=num/1000;

veloc=num-(tipo*1000);


printf("\n\n\r velocidade=%Ld\n\n\r", veloc);

printf("\n\n\rtipo=%d\n\n\r", tipo);


fim_loop:

for(i=0; i<=3; i++)        //colocar tudo a zero
   valor[i]=0;

a=1;

output_high(pin_A6);
delay_ms(150);
output_low(pin_A6);

//enable_interrupts(INT_RDA);      //habilitar interrupção

}

}



The operation should be simple.
I send something like 2255, and in response I get "tipo = 2" and "velocidade = 255".
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jun 23, 2012 12:50 pm     Reply with quote

Quote:

#use fast_io(A)
#use fast_io(B)

output_A(0);
output_B(0);

set_tris_a(0b00000000);
set_tris_b(0b00000010);

For this program, you don't need any of these lines. The compiler will
set the correct TRIS for you.



Quote:

unsigned int valor[4];

num=atol(valor);

I send something like 2255,

atol() expects valor to be a string. A string consists of ASCII characters
and a final 0x00 byte, that marks the end of a string. Your array is not
large enough to hold the 4 digits and also the 0x00 byte. Increase
the size of the valor array.


Quote:

#INT_RDA
void serial()
{
clear_interrupt(int_RDA);

fgets(valor, uart);

a=0;
}

void main()
{

while(a);

In this code, you get one RDA interrupt, and then you sit inside the
#int_RDA routine, waiting to get the string. Then you check 'a' to see
if you got it. In fact, with this program design, you don't even need
interrupts. All the code above can be replaced by the fgets() line,
if you place it in main(). Like this:
Code:

while(1)
{
fgets(valor, uart);

printf (valor);

num=atol(valor);

 



Quote:
fim_loop:

This label doesn't do anything. Remove it. If you need a comment to
tell yourself about the code, then add a comment, not a label.
Dave_25152



Joined: 11 Dec 2010
Posts: 60

View user's profile Send private message

PostPosted: Sat Jun 23, 2012 2:30 pm     Reply with quote

I'm testing a very simple program now.

But the LED flashes only 2 times .... even after I send data.

Code:
#include "16lf1827.h"
#use delay (clock=1000000)
#fuses INTRC_IO, NOLVP, NOWDT, NOMCLR, NOIESO, PUT, NOBROWNOUT
#use RS232(baud=4800, xmit=PIN_B2,rcv=PIN_B1,PARITY=N,BITS=8,stream=uart, ERRORS)


void MAIN()
{
unsigned int16 valor[4];
unsigned int i;

setup_adc(0);
setup_oscillator(OSC_1MHZ|OSC_NORMAL);

setup_uart(true);



for(i=0; i<=3; i++)       
   valor[i]=0;


delay_ms(500);

output_high(pin_A6);
delay_ms(150);
output_low(pin_A6);
delay_ms(150);

while(true)
{

output_high(pin_A6);
delay_ms(150);
output_low(pin_A6);


fgets(valor, uart);


delay_ms(100);

output_high(pin_A6);
delay_ms(150);
output_low(pin_A6);

}
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jun 23, 2012 3:17 pm     Reply with quote

You need to study the C language. I said to increase the size of the array.
That means increase it to:
Code:
int8 valor[5];
 

In your case, just to be safe, you should set it to a larger number, such
as this:
Code:
int8 valor[10];



Quote:
setup_uart(true);

Also, you are randomly inserting code that you don't understand
into the program for no reason. Remove this line. It's not needed.


The order of the top 4 lines should be like this:
Code:
#include "16lf1827.h"
#fuses INTRC_IO, NOLVP, NOWDT, NOMCLR, NOIESO, PUT, NOBROWNOUT
#use delay (clock=1000000)
#use RS232(baud=4800, xmit=PIN_B2,rcv=PIN_B1,PARITY=N,BITS=8,stream=uart, ERRORS)



Quote:
But the LED flashes only 2 times .... even after I send data.

You have to press the Enter key after you type the numbers into the
terminal window on your PC. Press 2255 and then press Enter.
The fgets() function looks for the Enter key to know when to end the
input session.
Dave_25152



Joined: 11 Dec 2010
Posts: 60

View user's profile Send private message

PostPosted: Sat Jun 23, 2012 4:32 pm     Reply with quote

Everything works fine now.

But one problem remains. All goes well the first time. When Enio data again, the "atoll" does not work.

Code:
void MAIN()
{
unsigned int16 valor[10], num;
unsigned int i;

setup_adc(0);
setup_oscillator(OSC_1MHZ|OSC_NORMAL);

setup_uart(true);



delay_ms(500);

output_high(pin_A6);
delay_ms(150);
output_low(pin_A6);
delay_ms(150);

while(true)
{

output_high(pin_A6);
delay_ms(150);
output_low(pin_A6);


fgets(valor, uart);

delay_ms(100);

num=atol(valor);

printf (valor);

printf("valor=%Ld", num);

output_high(pin_A6);
delay_ms(150);
output_low(pin_A6);

for(i=0; i<=9; i++)       
   valor[i]=0;
   
num=0;

}
}
Dave_25152



Joined: 11 Dec 2010
Posts: 60

View user's profile Send private message

PostPosted: Sat Jun 23, 2012 4:48 pm     Reply with quote



I do not understand why this is happening ....
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jun 23, 2012 4:56 pm     Reply with quote

You don't read what I post. You still have the array declared as int16.
I told you to make it be int8.
Quote:
unsigned int16 valor[10],

I feel like quitting this thread. Someone else can help.
Dave_25152



Joined: 11 Dec 2010
Posts: 60

View user's profile Send private message

PostPosted: Sat Jun 23, 2012 5:17 pm     Reply with quote

Thanks for your patience.

I changed as you told me to "int8".

The problem is not solved.
Dave_25152



Joined: 11 Dec 2010
Posts: 60

View user's profile Send private message

PostPosted: Sat Jun 23, 2012 5:53 pm     Reply with quote

I have looked everywhere and nobody had a similar problem?

It's very strange, not to convert twice.


Code:
void MAIN()
{
unsigned int16 num;
unsigned int i, valor[6];

setup_adc(0);
setup_oscillator(OSC_1MHZ|OSC_NORMAL);
setup_uart(true);



delay_ms(500);

output_high(pin_A6);
delay_ms(150);
output_low(pin_A6);
delay_ms(150);

while(true)
{

output_high(pin_A6);
delay_ms(150);
output_low(pin_A6);

delay_ms(500);

fgets(valor, uart);

delay_ms(100);

num=atol(valor);


printf (valor);

printf("valor=%Ld\n\n\n\n\n", num);

output_high(pin_A6);
delay_ms(150);
output_low(pin_A6);

for(i=0; i<=5; i++)       
   valor[i]=0;

num=0;
}
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Sun Jun 24, 2012 1:22 am     Reply with quote

There are two possible problems:

The first is time. It is not clear from your post how the data is being sent. Presumably you are typing it, or is it coming from some sort of program?.

Now, when you start, the code delays for 650mSec, before it arrives at the gets. Then waits for the string to arrive. Once it arrives, the code goes off, waits for 100mSec before doing anything else, then prints, taking perhaps 19mSec to do this - printf(valor);, is _not_ legitimate C. The correct syntax is:
printf("%s",valor);, then delays of another 150mSec, then another 650mSec, before finally returning to wait for the string. So a delay of just under 1second. If anything more than 1.9+ characters arrive in this time, these _will_ be lost, so if the transmission is automatic, or you are typing at anything more than at a crawl, the code at this point will go wrong.

Second problem, is what arrives.

Assuming this is from a PC, using a terminal program, then there is a good chance it is set to send carriage return _plus_ line feed when you hit the 'enter' key to send the value. The gets code waits for a carriage return (code 13), then returns the string. At this point, a line feed (code ten) then arrives, and when you loop round, this is still waiting to be read. The second gets, then returns:

<LF>nnnnn<\0>

and again the line feed is left waiting to be read. The string now returned begins with line feed, not a number, so atol, looks at it, and says "not a number, can't convert it".....

Change the settings in your terminal program to only send CR, not CR/LF when enter is pressed.

Best Wishes
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Jun 24, 2012 4:44 am     Reply with quote

I was thinking about helping you, and then I saw this line:
Quote:
setup_uart(true);
A few posts higher PCM Programmer told you to get rid of it and why, but it seems like you don't want to listen to good advice. If you don't understand the advice, then say so. Ignoring good advice makes us feel like we are not being taken serious. Good, but then we have better ways to spend our time.

Another suggestion was to improve your indentation. Many passionate discussions have been held about the possible styles to choose from. I don't care which style you choose, but anything is better than your current code where you have no indentation. More info on this subject: http://en.wikipedia.org/wiki/Indent_style

Last suggestion to make you a better programmer is to take care about capitalization. The C-language is sensitive to the use of lower and UPPER capital words. The CCS compiler doesn't follow the standard and doesn't care, but this results into programs that are not portable to other compilers and more difficult to read.
For example it is good practice to write all constants in capital letters to make them stand out from the variables:
true --> TRUE
pin_A1 --> PIN_A1

but:
MAIN() --> main()

Add '#case' to the start of your program to make the compiler case sensitive.
Dave_25152



Joined: 11 Dec 2010
Posts: 60

View user's profile Send private message

PostPosted: Sun Jun 24, 2012 7:17 am     Reply with quote

Thanks for the replies.

I've tried to take "setup_uart", but after the serial port no longer works.

I changed the settings on my terminal program to send only CR, but the PIC does not send any value. When I change to "CR + LF", I get data from PIC.

To send data, I'm using "uart tool" of the PICkit2.
The values ​​are sent at intervals of 10/15 seconds.

The result is the same. Works well once and then starts sending "valor = 0".


Code:

#CASE

void main()
{

unsigned int16 num;
unsigned int i, valor[8];

setup_adc(0);
setup_oscillator(OSC_1MHZ|OSC_NORMAL);
setup_uart(TRUE);                                                 //If I take this line, the uart port stops working ...


delay_ms(500);

output_high(PIN_A6);
delay_ms(150);
output_low(PIN_A6);
delay_ms(150);

   while(TRUE)
   {
   output_high(PIN_A6);
   delay_ms(150);
   output_low(PIN_A6);

   delay_ms(500);

   fgets(valor);

   delay_ms(1000);

   num=atol(valor);

   delay_ms(1000);

   printf ("%s\n\n\n", valor);

   printf("valor=%Ld\n\n\n\n\n", num);

   output_high(PIN_A6);
   delay_ms(500);
   output_low(PIN_A6);

   for(i=0; i<=7; i++)       
      valor[i]=0;

   num=0;
   }
}




I do not know what to do ...
I do not understand why everything works fine the first time and then does not work.

I've done a program like this to test: http://www.daniweb.com/software-development/cpp/threads/148373/extract-numbers-from-char

The problem is that when I write "num = valor[1]" (for example) appears in the terminal "num = 50".


Something is driving me crazy.

Thanks for your help!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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