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

pulse width input

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



Joined: 11 Apr 2010
Posts: 13

View user's profile Send private message

pulse width input
PostPosted: Tue Apr 20, 2010 8:41 am     Reply with quote

I am using PIC12f675 to make a project such that it takes input pulses of 50Hz that is 20ms and analyze the duty cycle. After analysis I need an On time and Off time (which I will get from duty cycle) that I will use for my desired outputs.

Is there any method to do such thing? A code sample will be appreciated.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 20, 2010 3:46 pm     Reply with quote

The 12F675 doesn't have a CCP module, so if you want to measure
the pulse width, you need to do it in software. The following program
takes the ASM code from the PicBasic Pro PULSIN command and puts it
in a function "wrapper" so it can be used with CCS. This code can be
used to measure the pulse width of a signal on any PIC input pin.

The program below will work with your 50 Hz signal. Pulse widths
will vary from 0 to about 20 ms. The accuracy is within 4%.

This is the test program. It should be saved as "pulsin_test.c".
Code:

#include <16F877.H>
#fuses XT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#include "pulsin.c"

//======================================
void main()
{
int16 result;
int16 pulse_width_usec;

// Measure the pulse width of the signal on pin B0.
// The pulse width is displayed in microseconds.
while(1)
  {
   result = pulsin(PIN_B0, 1);
   pulse_width_usec = result * 10;
   printf("%lu\n\r", pulse_width_usec);
   delay_ms(500);
  }

}


This is the Pulsin driver code. It should be saved as "pulsin.c".
Code:

#ifdef __PCB__
#error  Pulsin is not supported for the PCB compiler.
#endif
#ifdef __PCD__
#error  Pulsin is not supported for the PCD compiler.
#endif

#ifdef __PCM__
#define interrupt_enabled(x)  !!(*make8(x,1) & make8(x,0))
#endif
#ifdef __PCH__
#define interrupt_enabled(x)  !!(*(make8(x,1) | 0xF00) & make8(x,0))
#endif

#define BYTE_PTR(x) &(int8 *)(x)

// ASM definitions
#define W  0
#define F  1

// Status Register Bits
#define Z  2
#define C  0

#ifdef __PCM__
// Register addresses (16F)
#byte INDF   = 0x00
#byte STATUS = 0x03
#byte FSR    = 0x04
#endif

#ifdef __PCH__
// Register addresses (18F)
#byte INDF0  = 0xFEF
#byte STATUS = 0xFD8
#byte FSR0H  = 0xFEA
#byte FSR0L  = 0xFE9
#endif

//---------------------------------------
// #define PULSIN_MAX  60000

#ifdef PULSIN_MAX
  #if(PULSIN_MAX > 65535)
      #error PULSIN MAX is too High. Maximum value is 65535. 
  #endif
#endif

//---------------------------------------

#ifdef __PCM__
int16 pulsin(int8 ccs_pin, int8 state)
{
int8 io_port;
#endif

#ifdef __PCH__
int16 pulsin(int16 ccs_pin, int8 state)
{
int16 io_port;
#endif

int8 const bitmask_table[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
int8 gie_enabled = FALSE;

int8 bitmask;
int8 flip;
int16 count;

// These variables are used in the ASM code
// and must be located in the same RAM bank.
#locate io_port = 0x30  // Can be 8 or 16 bits
#locate count   = 0x32  // 16 bits
#locate state   = 0x34
#locate bitmask = 0x35
#locate flip    = 0x36


if(interrupt_enabled(GLOBAL))
  {
   disable_interrupts(GLOBAL);
   gie_enabled = TRUE;
  }

// Get the I/O Port address and the bitmask from
// the CCS pin number value.
io_port = ccs_pin >> 3;

bitmask = bitmask_table[ccs_pin & 7];

// Set TRIS = input.
#ifdef __PCM__
*(io_port | 0x80) |= bitmask;  // For 16F PICs
#endif
#ifdef __PCH__
*(io_port + 0x12) |= bitmask; // For 18F PICs
#endif


#asm   
PULSINT:
#ifdef __PCM__
         movf    io_port, W      ; Get port
         movwf   FSR
#endif

#ifdef __PCH__
         movf    io_port, W      ; Get port lsb
         movwf   FSR0L
         movf    BYTE_PTR(io_port) +1, W   ; Get port msb
         movwf   FSR0H
#endif
         movf    bitmask,w

         clrf    flip            ; Preset state tracking
         btfss   state, 0        ; State tracking preset for flip
         movwf   flip            ; Set state to bit mask
   
         call    statecnt        ; Wait for idle state
         btfsc   STATUS, Z       ; If timeout then it's over
         goto    done

         call    statecnt        ; Wait for starting edge
         btfsc   STATUS, Z       ; If timeout then it's over
         goto    done
   
         call    statecnt        ; Do the count
         goto    done

//--------------------------------------------------
statecnt:
         movf    bitmask, W      ; Flip state each time through here
         xorwf   flip, F
#ifdef PULSIN_MAX
         movlw   ((-(PULSIN_MAX)) + 1)       ; Start counter -PULSIN_MAX + 1
         movwf   count
         movlw   (((-(PULSIN_MAX)) + 1) >> 8)
         movwf   BYTE_PTR(count) + 1
#else
         movlw    1
         movwf    count
         clrf     BYTE_PTR(count) + 1
#endif

statecntloop:                    ; Takes 10 usec
#ifdef __PCM__
         movf    INDF, W         ; 1 Read Port with INDF
#endif
#ifdef __PCH__
         movf    INDF0, W        ; 1 Read Port with INDF0
#endif
         andwf   bitmask, W      ; 1 Mask it with bitmask
         xorwf   flip, W         ; 1 Mix with desired state
         btfss   STATUS, Z       ; 2 / 1
#ifdef PULSIN_MAX
         goto    statecntexit    ; 0 / 2 No longer in state
#else
         return                  ; 0 / 2 No longer in state
#endif
         incf    count, F        ; 1 Increment counter
         btfsc   STATUS, Z       ; 1 / 2
         incfsz  BYTE_PTR(count) + 1, F   ; 1 / 2
         goto    statecntloop    ; 2 / 0
         return                  ; 0 / 2 Counter overflow
#ifdef PULSIN_MAX
statecntexit:
         movlw   PULSIN_MAX      ; Normalize count
         addwf   count, F
         movlw   PULSIN_MAX >> 8
         btfsc   STATUS, C
         addlw   1
         addwf   BYTE_PTR(count) + 1, F
         bcf     STATUS, Z       ; Indicate no overflow
         return
#endif
done:

#endasm

if(gie_enabled)
  {
   enable_interrupts(GLOBAL);
  }

return(count);
}

For reference, here is the PicBasic COUNT command for CCS:
http://www.ccsinfo.com/forum/viewtopic.php?t=41877
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