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 support@ccsinfo.com

#int rda and set_pwm1_duty()

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ericchee



Joined: 03 Dec 2008
Posts: 12

View user's profile Send private message

#int rda and set_pwm1_duty()
PostPosted: Wed Dec 03, 2008 2:09 am     Reply with quote

I have used the ex_sisr.c codes and I have no problem to send string from pc to PIC. I have no problem displaying the string back on the pc by sending back from PIC to pc. What I actually want is to send a three digit number but since I am sending data through the serial port, it needs to be in a string. These 3 digit numbers needed to be inputted into pwm so I have changed the string to int. But it's not working. Any help will be appreciated!

Code:

#include <16F877A.h>
#include <string.h>
#use delay(clock=20000000)
#fuses hs, noprotect, nowdt,nolvp

#byte PORTB=6
#byte PORTC=7
#define door PIN_B2
#define window PIN_B1
#define bumper PIN_B3
#define INTS_PER_SECOND 76     // (20000000/(4*256*256))

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define ChannelA PIN_A0
#define ChannelB PIN_A1
#define DIRECTION PIN_D3
#define REDLED PIN_B4
#define GREENLED PIN_B6
#define YELLOWLED PIN_B3
#include <input.c>
//#define  STRING_SIZE    51
#include <stdlib.h>
#define STRING_SIZE 40

#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
#define bkbhit (next_in!=next_out)

byte bgetc()
{
   byte c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}

#int_rda
void serial_received()
{
int asdf;
char input_str[STRING_SIZE];
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
   next_in=t;           // Buffer full !!

   strcpy (input_str , bgetc());  // i type 100 from pc and copy to input_str
     printf("\n\rYou typed: %s \n\r\n\r", input_str);  //100 display at pc
     output_high(REDLED);
     asdf = atoi(input_str);  // convert string to int
     set_pwm1_duty(asdf);
     output_high(YELLOWLED);
}

void main()
{
BYTE time;
BYTE time1;
BYTE abc;
BYTE string;

output_low(GREENLED);
output_low(REDLED);
output_low(YELLOWLED);

setup_timer_2(T2_DIV_BY_4, 127, 1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(128);

setup_counters( RTCC_EXT_H_TO_L, RTCC_DIV_1 );
set_rtcc(0);

setup_timer_1 ( T1_EXTERNAL | T1_DIV_BY_1 );
set_timer1(0);

enable_interrupts(INT_RTCC);
enable_interrupts(INT_TIMER1);
EXT_INT_EDGE(L_TO_H);
ENABLE_INTERRUPTS(INT_EXT);
ENABLE_INTERRUPTS(INT_RDA);
enable_interrupts(GLOBAL);
set_tris_b(0b00110001);
portb=0;
}
ericchee



Joined: 03 Dec 2008
Posts: 12

View user's profile Send private message

PostPosted: Wed Dec 03, 2008 2:34 am     Reply with quote

I just read 'receive ASCII string and convert to int' by coderchick. I think my problem exactly the same with hers. Also I have tried get_string() but still not working. Actually I don't quite understand how get_string works. Can anyone explain its operation? tq
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Dec 03, 2008 2:09 pm     Reply with quote

Do you need to use interrupts ? I suggest that you write a version of
your program that doesn't use interrupts.

In a while() loop, in main(), call the get_string() function. Use the atoi()
or atol() function to convert the input number into a integer. Then use
the integer to set the pwm duty cycle. This is easy to do, without using
interrupts.

Remove all unnecessary code from your program. Remove the counter
and timer1, and LED stuff. Remove the #int_rda code. Remove the
enabling of interrupts. You should be able to make a really stripped down
program that uses get_string() and pwm.
ericchee



Joined: 03 Dec 2008
Posts: 12

View user's profile Send private message

PostPosted: Sun Dec 28, 2008 4:16 am     Reply with quote

counter, timer, #int_rda and led is for other function in my program. my computer is sending string to PIC. is that possible just using your suggested method to read the string without using interrupt?
dyeatman



Joined: 06 Sep 2003
Posts: 1923
Location: Norman, OK

View user's profile Send private message

PostPosted: Sun Dec 28, 2008 7:57 am     Reply with quote

Much of your code is missing so we do not know what you are doing. You
don't even show the main program while(1) loop.

One thing is for sure. It definitely will not work with you trying to do all that
"stuff" inside the ISR. Get the character, put it in the buffer and get out as
quickly as possible. Use BGETC() to process the input buffer from the main
while(1) loop. It's been said numerous times in this forum that an
interrupt routine MUST be as short and fast as possible.

As PCM said earlier, use the interrupt only if you must. Since the character
input will be slow you may be better off testing KBHIT() in the main loop and
getting the character when it is available iin the UART buffer. An interrupt is
likely going to interfere with any time critical processes you have going on.

You are enabling interrupts that have no matching ISR routine and also
doing port setups AFTER enabling the interrupts. Both of these are
an invitation for disaster. I can only assume you have the ISRs
somewhere. Enabling interrupts should always be the LAST thing you
do before entering the main loop. Otherwise it may jump straight to
an interrupt before finishng the setup.
ericchee



Joined: 03 Dec 2008
Posts: 12

View user's profile Send private message

PostPosted: Fri Jan 02, 2009 3:24 am     Reply with quote

Okay. I have my things reorganize but still not working.
what i am trying to do here is to read data from two timers and send the data to pc. pc will proceses the data and will send back response to PIC. The data from pc which is in a form of string will be used to set the pwm.
dyeatman, i do not understand by "enabling interrupts that have no matching ISR routine". i do not understand how the program to read the input by disabling the int_rda. anyway i will give it a try and i'll tell you the result



Code:

#include <16F877A.h>
#include <string.h>
#use delay(clock=20000000)
#fuses hs, noprotect, nowdt,nolvp
#byte PORTB=6
#byte PORTC=7
#define door PIN_B2
#define window PIN_B1
#define bumper PIN_B3
#define INTS_PER_SECOND 76     // (20000000/(4*256*256))
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define ChannelA PIN_A0
#define ChannelB PIN_A1
#define DIRECTION PIN_D3
#define REDLED PIN_B4
#define GREENLED PIN_B6
#define YELLOWLED PIN_B3
#include <input.c>
#include <stdlib.h>
#define STRING_SIZE 40

#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;

#define bkbhit (next_in!=next_out)

byte bgetc()
{
   byte c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}

#int_rda
void serial_received()
{
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
}

#int_ext
void interrupt()
{
BYTE  time3;

set_tris_b(0b00000001);
output_high(bumper);
time3 = get_timer0();
time3 += -1;
set_timer0(time3);
//DISABLE_INTERRUPTS(INT_EXT);
}

#int_rtcc                          // This function is called every time
void clock_isr()
{                 // the RTCC (timer0) overflows (255->0).
BYTE seconds;      // A running seconds counter
BYTE int_count;    // Number of interrupts left before a second has elapsed

                                  // For this program this is apx 76 times
    if(--int_count==0) {           // per second.
      ++seconds;
      int_count=INTS_PER_SECOND;
    }

}

void main()
{
BYTE abc;
BYTE string;
int PwM;
char input_str[STRING_SIZE];

set_tris_b(0b00110001);
portb=0;

setup_timer_2(T2_DIV_BY_4, 127, 1);
setup_ccp1(CCP_PWM);

setup_counters( RTCC_EXT_H_TO_L, RTCC_DIV_1 );
set_rtcc(0);

setup_timer_1 ( T1_EXTERNAL | T1_DIV_BY_1 );
set_timer1(0);

enable_interrupts(INT_RTCC);
enable_interrupts(INT_TIMER1);
EXT_INT_EDGE(L_TO_H);
ENABLE_INTERRUPTS(INT_EXT);
ENABLE_INTERRUPTS(INT_RDA);
enable_interrupts(GLOBAL);


do
{

printf("%2x",get_rtcc()); //send data to computer
printf("%2x\n\r",get_timer1()); //send data to computer

while(bkbhit)
{
PwM==atoi(bgetc());
set_pwm1_duty(PwM);
}

}while(TRUE);
}



Cheers,
Ttelmah
Guest







PostPosted: Fri Jan 02, 2009 3:44 am     Reply with quote

Repeat after me fifteen times:
"I must _never_ enable an interrupt without a handler present".
You are enabling INT_TIMER1, without a handler.

Best Wishes
ericchee



Joined: 03 Dec 2008
Posts: 12

View user's profile Send private message

PostPosted: Fri Jan 02, 2009 4:41 am     Reply with quote

oh, i should add #INT_TIMER1 routine into to my code.
ericchee



Joined: 03 Dec 2008
Posts: 12

View user's profile Send private message

PostPosted: Mon Jan 05, 2009 9:12 pm     Reply with quote

I got it now. Here's the code:

Code:
#include <16F877A.h>
#include <string.h>
#use delay(clock=20000000)
#fuses hs, noprotect, nowdt,nolvp
#byte PORTB=6
#byte PORTC=7
#define door PIN_B2
#define window PIN_B1
#define bumper PIN_B3
#define INTS_PER_SECOND 76     // (20000000/(4*256*256))
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define ChannelA PIN_A0
#define ChannelB PIN_A1
#define DIRECTION PIN_D3
#define REDLED PIN_B4
#define GREENLED PIN_B6
#define YELLOWLED PIN_B3
#include <input.c>
#include <stdlib.h>
#define STRING_SIZE 40

#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;

#define bkbhit (next_in!=next_out)
char cmd_str[20];

byte bgetc()
{
   byte c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}

void get_cmd_str(char * s, int max) {
   int len;
   char c;

   max--;
   len = 0;

   do {
      c = bgetc();
      if(c > 0x00) {
         if(len < max) {
            s[len++] = c;
         }
      }
   }
   while(bkbhit);
   s[len]= 0x00;
}

#int_rda
void serial_received()
{
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
}

#int_ext
void interrupt()
{
BYTE  time3;

set_tris_b(0b00000001);
output_high(bumper);
time3 = get_timer0();
time3 += -1;
set_timer0(time3);
//DISABLE_INTERRUPTS(INT_EXT);
}

#int_rtcc
void timer0_isr()
{
BYTE tmr1;

tmr1 = get_timer1();
tmr1 = tmr1 - 255 + 1;
set_timer1(tmr1);

}

#int_timer1
void timer1_isr()
{
BYTE tmr0;

tmr0 = get_rtcc();
tmr0 = tmr0 - 255 + 1;
set_timer0(tmr0);
}

void main()
{
int PwM;

set_tris_b(0b00110001);
portb=0;

output_low(GREENLED);
output_low(REDLED);
output_low(YELLOWLED);

setup_timer_2(T2_DIV_BY_4, 127, 1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(0);

setup_counters( RTCC_EXT_H_TO_L, RTCC_DIV_1 );
set_rtcc(0);

setup_timer_1 ( T1_EXTERNAL | T1_DIV_BY_1 );
set_timer1(0);

enable_interrupts(INT_RTCC);
enable_interrupts(INT_TIMER1);
EXT_INT_EDGE(L_TO_H);
ENABLE_INTERRUPTS(INT_EXT);
ENABLE_INTERRUPTS(INT_RDA);
enable_interrupts(GLOBAL);

main_program:
do
{
if(bkbhit)
{
      delay_ms(50);              //Delay allows full string to arrive
      get_cmd_str(cmd_str, 10);
      output_high(YELLOWLED);
}

PwM=atoi(cmd_str);
set_pwm1_duty(PwM);
printf("---------------->%d\n\r",PwM);

}while(TRUE);

goto main_program;

}

ericchee



Joined: 03 Dec 2008
Posts: 12

View user's profile Send private message

PostPosted: Mon Jan 19, 2009 11:48 am     Reply with quote

hey guys,

i encounter a problem. here is the new code added.
Code:

PwM=atoi(cmd_str);
if(PwM >= 129)
{
printf("---------------->%d 1 \n\r",PwM);
PwM -= 129;
set_pwm1_duty(PwM);
output_high(DIRECTION);
}
if(PwM <= 128)
{
printf("---------------->%d 2 \n\r",PwM);
set_pwm1_duty(PwM);
output_low(DIRECTION);
}
[quote]

Whatever number i send, i get low output for DIRECTION. The upper 'if' code seems not working. Can anyone point out what mistake i have made? tq[/quote]
ckielstra



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

View user's profile Send private message

PostPosted: Mon Jan 19, 2009 12:22 pm     Reply with quote

Another classic one...

The upper code is working, but before you 'can blink an eye', the lower code is reached where the 'if-statement' now is also true and is executed as well.
(an int8 - 129 is always <= 128).

Change the second if-statement to an else-if.
ericchee



Joined: 03 Dec 2008
Posts: 12

View user's profile Send private message

PostPosted: Wed Jan 21, 2009 7:51 am     Reply with quote

You have just saved my day. This problem have been spinning my head for few days. Thank you very much.

Regards,
Eric
ericchee



Joined: 03 Dec 2008
Posts: 12

View user's profile Send private message

PostPosted: Fri Feb 27, 2009 6:51 pm     Reply with quote

hi,

May i know the formula to find speed of 9600 baud rate. I have been using 76800 baud rate before and it works but lately my project is not working. after changing back to 9600, it works.

Code:

if(bkbhit)
{
      delay_ms(50);              //Delay allows full string to arrive
      get_cmd_str(cmd_str, 10);
      output_high(YELLOWLED);
}


What is the minimum delay i can put? I encounter data loss when when i used 10. Is there anything to do with baud rate? Is there anything document regarding the speed of each code. tq

rgds,

eric
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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