/*
* Read the ADC on a 16F873.
*/
#include <pic.h>
#include "adc.h"
#include "delay.h"
char adc_read(unsigned char channel)
{
char result;
ADCON1 = 0x0E; // left justified, AN0 is the only analog input
ADCON0 = (channel << 3) + 0xC1; // enable ADC, RC osc.
DelayUs(30); // delay 30usec so the channel change will stabilize
ADGO = 1;
while(ADGO); // wait for conversion complete
result = ADRESH;
return result;
}
---------------------------------------------------
/*
* Delay functions
* See delay.h for details
*
* Make sure this code is compiled with full optimization!!!
*/
#include "delay.h"
void
DelayMs(unsigned char cnt)
{
#if XTAL_FREQ <= 2MHZ
do {
DelayUs(996);
} while(--cnt);
#endif
#if XTAL_FREQ > 2MHZ
unsigned char i;
do {
i = 4;
do {
DelayUs(250);
} while(--i);
} while(--cnt);
#endif
}
----------------------------------------------------
/*
* Delay functions for HI-TECH C on the PIC
*
* Functions available:
* DelayUs(x) Delay specified number of microseconds
* DelayMs(x) Delay specified number of milliseconds
*
* Note that there are range limits: x must not exceed 255 - for xtal
* frequencies > 12MHz the range for DelayUs is even smaller.
* To use DelayUs it is only necessary to include this file; to use
* DelayMs you must include delay.c in your project.
*
*/
/* Set the crystal frequency in the CPP predefined symbols list in
HPDPIC, or on the PICC commmand line, e.g.
picc -DXTAL_FREQ=4MHZ
or
picc -DXTAL_FREQ=100KHZ
Note that this is the crystal frequency, the CPU clock is
divided by 4.
* MAKE SURE this code is compiled with full optimization!!!
*/
#ifndef XTAL_FREQ
#define XTAL_FREQ 4MHZ /* Crystal frequency in MHz */
#endif
#define MHZ *1000L /* number of kHz in a MHz */
#define KHZ *1 /* number of kHz in a kHz */
#if XTAL_FREQ >= 12MHZ
#define DelayUs(x) { unsigned char _dcnt; \
_dcnt = (x)*((XTAL_FREQ)/(12MHZ)); \
while(--_dcnt != 0) \
continue; }
#else
#define DelayUs(x) { unsigned char _dcnt; \
_dcnt = (x)/((12MHZ)/(XTAL_FREQ))|1; \
while(--_dcnt != 0) \
continue; }
#endif
extern void DelayMs(unsigned char);
----------------------------------------------------------
/***************************************************/
/* Servo Tester main.c */
/* */
/***************************************************/
#include <pic.h>
#include "adc.h"
#include "servo.h"
#include "delay.h"
bit sweep;
bit stop;
#define low(a) (a & 0x00ff)
static void interrupt isr(void)
{
// determine the interrupt source
// first the INTCON register
if(RBIF && RBIE) // Port B Change Interrupt
{
RBIF = 0;
}
if(INTF && INTE) // Port B.0 Interrupt for Idle Line Detection
{
INTF = 0;
}
if(T0IF && T0IE) // TMR0 Interrupt
{
T0IF = 0;
}
// Done with INTCON, it must be the PIR1 register
if(TMR1IF && TMR1IE) // check timer 1
{
TMR1IF = 0;
servoisr();
}
if(TMR2IF && TMR2IE) // check timer 2
{
TMR2IF = 0;
}
if(CCP1IF && CCP1IE) // check the CCP module
{
CCP1IF = 0;
servoCCPisr();
}
if(SSPIF && SSPIE)
{
SSPIF = 0;
}
if(TXIF && TXIE) // TX Character Interrupt
{
}
if(RCIF && RCIE) // RX Character Interrupt
{
}
if(ADIF && ADIE) // check the ADC
{
}
}
#define SWEEP_BUTTON 0x10
#define STOP_BUTTON 0x08
char check_stop()
{
static char bounce = 0;
char ret;
if(PORTA & STOP_BUTTON)
bounce = 0;
else
bounce ++;
if(bounce >= 3)
{
ret = 1;
bounce = 3;
}
else
ret = 0;
return ret;
}
char check_sweep()
{
static char bounce = 0;
char ret;
if(PORTA & SWEEP_BUTTON)
bounce = 0;
else
bounce ++;
if(bounce >= 3)
{
ret = 1;
bounce = 3;
}
else
ret = 0;
return ret;
}
const char table[] = {0x01,0x03,0x07,0x0f,0x01f,0x3f,0x7f,0xff};
void main()
{
char v;
int pos;
char direction;
char o_sweep;
initServo();
TRISB = 0x00;
PORTB = 0x00;
TRISA = 0x19;
TRISC = 0x00;
GIE = 1; // enable interrupts
setServo(127);
direction = 0;
pos = 0;
while(1)
{
v = check_sweep();
if(v && !o_sweep)
{
sweep = !sweep;
}
o_sweep = v;
if(check_stop())
{
stop = !stop;
}
if(stop)
{
GIE = 0;
PORTC = 0;
}
if(!stop)
{
GIE = 1;
}
v = adc_read(0);
if(sweep)
{
if(pos == 0)
direction = 1;
if(pos == 255)
direction = 0;
if(direction)
{
pos += (v/4) + 1;
if(pos > 255)
pos = 255;
}
else
{
pos -= (v/4)+1;
if(pos < 0)
pos = 0;
}
PORTB = table[low(pos)/32];
setServo( low(pos) );
}
else
{
pos = v;
PORTB = table[low(pos)/32];
setServo(low(pos));
}
DelayMs(20);
}
}
/**********************************************************/
/* Servo Tester Servo Code */
/**********************************************************/
#include <pic.h>
#include "servo.h"
char servoLow;
char servoHigh;
/* servo system uses CCP and TMR1 */
/* TMR1 Overflow is set for 20msecs */
/* set TMR1 for prescale of 1/2 */
/* CCP is set for clear on match after servo command period */
#define crystal 20000000
#define clock (crystal/8)
#define TWNTYMSEC (65535 - (clock / 50))
#define TWOUSEC (clock / 500000)
#define NONEMSEC (TWOUSEC * 475)
#define ONEMSEC (TWOUSEC * 525)
#define high(a) (a >> 8)
#define low(a) (a & 0x00ff)
#define RC2 0x04
void initServo()
{
CCP1CON = 0;
TRISC = 0;
TMR1IF = 0;
CCP1IF = 0;
TMR1H = high(TWNTYMSEC);
TMR1L = low(TWNTYMSEC);
servoLow = low(TWNTYMSEC + NONEMSEC);
servoHigh =high(TWNTYMSEC + NONEMSEC);
CCPR1L = servoLow;
CCPR1H = servoHigh;
CCP1CON = 0x0A;
CCP1IF = 0;
T1CON = 0x11;
TRISC &= ~RC2;
PORTC &= ~RC2;
CCP1IE = 1;
TMR1IE = 1;
PEIE = 1;
}
void servoisr()
// Turn on PORTC
{
PORTC |= RC2; // set PORTC.2
TMR1H = high(TWNTYMSEC);
TMR1L = low(TWNTYMSEC);
}
void servoCCPisr()
// after the high pulse, update the compare registers for the next pulse
{
PORTC &= ~RC2;
CCPR1L = servoLow;
CCPR1H = servoHigh;
}
void setServo(char pos)
/* 0 to 255 */
{
unsigned int v;
v = pos * (ONEMSEC/255);
v += TWNTYMSEC + NONEMSEC;
servoLow = low(v);
servoHigh = high(v);
}
-----------------------------------------
/***************************************************/
/* Autopilot servo.h */
/* */
/***************************************************/
void servoisr();
/* TMR1 ISR for Servo control */
void servoCCPisr();
/* CCP ISR for servo update */
void initServo();
/* initialize the system for servo drive */
void setServo(char pos);
/* set the servo position between 0 and 255 */
/* 128 will center the servo */
---------------------------------------------
/*
* adc.h
*/
/*
* Read the adc on the specified channel - return result
*/
extern char adc_read(unsigned char channel); |