⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 control.c

📁 熟悉verilog,帮助初学者尽快掌握verilog
💻 C
📖 第 1 页 / 共 3 页
字号:
/*********************************************************************
*
*   Project:  (if you don't mind... I'll withhold the actual
*              application.. Maybe you can guess..)
*
*               This is a working piece of firmware used
*               in an industrial application.  Your application
*               will be different, of course.  This example may
*               help in a few ways though:
*                  1.  I use the CCS compiler, and I use several
*                      of that compilers nice extensions, such
*                      as writing to the serial port, delays,
*                      bit manipulation, etc.  I found the
*                      CCS compiler to be more than adequete
*                      for these PIC control applications.
*                  2.  The PIC communicates to an A/D chip, the
*                      MAXIM 192.  You can copy this function.
*                  3.  Perhaps, this program help you size your
*                      application - I show the % memory
*                      utilization of the 16C63 I used.
*                  4.  I suppose you might get embedded
*                      programming ideas...  I am a fan
*                      of round-robin, state-machine programming..
*                      Really, this is a simple program but
*                      the bread-n-butter of embedded control:
*                      monitor some sensors, look at switches,
*                      light some LEDs, apply a bunch of rules..
*
*
*
*   Description:
*      Runs on a PIC16C63, compiled with the CCS PCM compiler.
*      Uses the overflow interrupt from timer1 as a timebase.
*      Various debug messages are output on the serial port
*      at 4800,8N and can be viewed with typical terminal
*      program.  Program uses a simple round-robin loop to
*      monitor and handle all events and actions.  Code written
*      with 4MHz crystal in mind.
*
*      PIC16C63 is programmed with PICSTART Plus programmer through
*      through the MPLAB program.  Programmer options include:
*      Device = 16C63, Oscillator = XT, Watchdog = OFF, Brownout = ON,
*      Code Protect = OFF, Power Up Timer = OFF.
*      Normal procedure is to:
*         1) Compile with PCM in a DOS window,
*         2) In MPLAB, enable programmer and select above options,
*         3) Select File | Import and choose the .HEX file
*         4) Select Picstart Plus | Program/Verify and program part.
*
*      The A/D chip used to sample analog values is the MAXIM MAX192.
*
*
*   Author:     Tom Coonan
*   File:       trash.c
*   Updated:    12/14/96
*   Version:    1.1
*   Revisions:
*      12/10/96:  - Added Self Test.
*      12/14/96:  - Changed DIR_RLY polarity.
*                 - Changed CHARGE_MIN constant value from 839 to 800.
*                 - Added rule to charging that turns charger on
*                   when motor is running.
*                 - Added bMotorOn flag to help with new charger rule.
*
*
*   Misc. Programming Notes:
*      1)  I use a prefix notation for variables based on their type:
*
*             b   -   boolean, will be declared as byte (8 bits)
*             by  -   byte (8 bits)
*             n   -   integer, declared as long ints (16 bits)
*
*          Most simple counters and state variables fit into 8 bits
*          and are therefore declared as byte.  Only a few variables
*          need the longer 16-bit length.  Note what the lengths of
*          types are for this compiler!
*
*      2)  Chip resources used: 56% program rom, 29% data ram
*
*******************************************************************/

/*

    I/O Map

Note:  Currently, 'fix_io' statements are used, so we do not
       have to use TRIS statements.  This is OK since pins
       are used as either inputs or outputs, but never change
       mode.

Pin Equate	 I/O     TRIS Bits
-----------------------------------
A7  N/C          INPUT    1   TRIS Word = F0
A6  N/C          INPUT    1
A5  EXTENDED     INPUT    1
A4  CYCLE_SW     INPUT    1
A3  MOTOR_RLY    OUTPUT   0
A2  RECYCLE_RLY  OUTPUT   0
A1  DIR_RLY      OUTPUT   0
A0  CHARGE_RLY   OUTPUT   0

B7  CHARGE_LED   OUTPUT   0  TRIS Word = 03
B6  SPA_LED      OUTPUT   0
B5  SERVICE_LED  OUTPUT   0
B4  CYCLE1_LED   OUTPUT   0
B3  CYCLE2_LED   OUTPUT   0
B2  CYCLE3_LED   OUTPUT   0
B1  RETRACTED    INPUT    1
B0  RECYCLE_SW   INPUT    1

C7  SERIAL_RX    INPUT    1  TRIS Word = AC
C6  SERIAL_TX    OUTPUT   0
C5  TESTJ1_7To8  INPUT    1  <--- Used to trigger Self Test
C4  ADC_CLK      OUTPUT   0
C3  ADC_DOUT     INPUT    1
C2  ADC_SSTRB    INPUT    1 
C1  ADC_DIN      OUTPUT   0
C0  ADC_CS       OUTPUT   0

*/

#include <16c63.h>

#fuses   XT,NOPROTECT,NOWDT

/* Allows the 'delay_' functions to work correctly with our 4MHz crystal. */
#use delay(clock=4000000)

/* Tell compiler our I/O.  We never change any one pin's input/output. */
#use fixed_io(a_outputs=PIN_A3,PIN_A2,PIN_A1,PIN_A0)
#use fixed_io(b_outputs=PIN_B7,PIN_B6,PIN_B5,PIN_B4,PIN_B3,PIN_B2)
#use fixed_io(c_outputs=PIN_C6,PIN_C4,PIN_C1,PIN_C0)

/* Used for debug purposes. */
#use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7)

// Bit equates for sensors INPUTs
#define RETRACTED   PIN_B1
#define EXTENDED    PIN_A5

// Bit equates for Relays OUTPUTs
#define CHARGE_RLY  PIN_A0
#define DIR_RLY     PIN_A1
#define MOTOR_RLY   PIN_A3
#define RECYCLE_RLY PIN_A2

// Bit equates for LED OUTPUTs
#define CHARGE_LED  PIN_B7
#define SPA_LED     PIN_B6
#define SERVICE_LED PIN_B5

// Bit equates for Switch INPUTs
#define RECYCLE_SW  PIN_B0
#define CYCLE_SW    PIN_A4
#define CYCLE1_LED  PIN_B4
#define CYCLE2_LED  PIN_B3
#define CYCLE3_LED  PIN_B2

// Bit equates for A/D chip I/O
#define ADC_CS      PIN_C0
#define ADC_CLK     PIN_C4
#define ADC_DIN     PIN_C1
#define ADC_DOUT    PIN_C3
#define ADC_SSTRB   PIN_C2


#define FALSE 0
#define TRUE  1

/*  Voltage Equations

  Due to the limited nature of PIC arithmetic, the
  program logic uses the raw A/D sample values and
  does not use any floating point math.  Only a few
  key variables are involved, therefore, all
  thresholds are precomputed below and placed in
  defines.

 1) The A/D input accepts a 0.000V to 4.096V input
    which maps to a 10 bit unsigned binary ranging
	 from 0x000 to 0x3FF (or, 0 to 1023).

    The following equation relates the A/D voltage
    input to the expected binary:

       sample = 1024*(vin/4.096)

    where sample is the value of the A/D number
    ultimately used in the program from the A/D
    (e.g. the value in nBatteryVoltage).

 2) The Battery voltage is divided through a
    resistor network resulting in:

       vin = vbattery*0.2582

    Therefore, the final equation is:

    sample = 1024*(vbattery*0.2582/4.096)

 3) Here is a table of voltages and samples:

    Variable         Voltage    Sample
    CHARGE_MAX       14.2       916
	 CHARGE_MIN       13.0       839
    BATTERY_PROTECT  9.5        613
    SPA_VOLTAGE      13.6       878

*/

/* What the values SHOULD be */
#define CHARGE_MAX        916
#define CHARGE_MIN        800
#define BATTERY_PROTECT   613
#define SPA_VOLTAGE       878


// Specify some hysterysis around the SPA voltage.
//
// Note:  The A/D resolution is 16.0 Volts / 1024 = 15.6 mV
#define SPA_HYSTERYSIS     7

#define MAX_PENDING_CYCLES 3

/* Called on power up. */
void LampTest (void);

/* A/D driver */
long int nADSample;  /* global where sample is assembled */
void GetAD (byte byChannel);

long int  nBatteryVoltage; /* 16-bit integer, need for 10-bit A/D sample */

long int  nAvgBatteryVoltage;

long int  nBatteryVoltage_last1;
long int  nBatteryVoltage_last2;
long int  nBatteryVoltage_last3;

/* States and flags */
byte bCharging;
byte bEverCharged;  /* Need to know if charger has ever been on */
byte byPendingCycles;
byte bMotorPaused;  /* if battery volts drop below protect, pause */
byte bMotorOn;
byte bEnoughMotorJuice;

/* Service Soon flag.  This gets set whenever a forward motor action
		       or a reverse motor action times out, or if
		       the battery voltage ever drops below a battery
		       protection voltage.
*/
byte bServiceSoon;

/* Flag is set if a forward or reverse timout has *ever* occured. */
byte bTimeoutOccured;

/* Flag is set if a battery protect voltage was ever reached. */
byte bBatteryProtect;

/* Flag is set if battery voltage has ever risen about battery protect.
   This will help elliminate the service soon light coming on prematurely. */
byte bBatteryEverOK;

/* Maximum number of cycles that can be queued up. Set after reading strap */
byte byMaxCycles;

/* Primary state machine variable for the "cycle" procedure */
byte byCycleState;

/* Cycle State Machine states for variable nCycleState */
#define STATE_CYCLE_INITIAL            0
#define STATE_CYCLE_INITIAL_WAITJUICE  1
#define STATE_CYCLE_IDLE               2
#define STATE_CYCLE_CHECKJUICE         3
#define STATE_CYCLE_WAITJUICE          4
#define STATE_CYCLE_FORWARD            5
#define STATE_CYCLE_REVERSE1           6
#define STATE_CYCLE_REVERSE2           7
#define STATE_CYCLE_DONE               8

/* Number of consequitive samples of switch needed to assert switch */
#define CYCLE_SWITCH_REQUIRED_SAMPLES 50

/* Cycle switch state machine variables */
byte byCycleSwitchState;
byte bySample_CycleSwitch;
#define STATE_CYCLE_SWITCH_IDLE            0
#define STATE_CYCLE_SWITCH_SAMPLE          1
#define STATE_CYCLE_SWITCH_WAIT_RELEASE    2

/* Timer Tick Counters (used with delay define constants) */
byte     byTicks_Charger_Hysterysis;  /* Charger can change once per second.  */

/* The delays for forward and reverse are long, so need long ints. */
long int nTicks_Reverse;             /* Reverse direction timeout (long one) */
long int nTicks_Forward;             /* Forward direction timeout (long one) */
long int nTicks_Paused;              /* Bookmark, when we pause motor        */

byte     byTicks_CycleSwitch;         /* Debounce for cycle switch            */
byte     byTicks_Delay;               /* A miscellanious delay                */
byte     byTicks_Display;             /* Last time display (e.g. RS232)       */

byte     byTicks_Initial_Charge; /* Brief time that Initial Charge rule applies */

/**** Delays ****/
/*
   Our timing is based on the overflow of the timer1.  First, here's how
   we detirmine how long a "tick" is:

   4MHz crystal, divided by 4 (e.g. PIC always does this) is 1MHz.
   Timer 1 is a 16 bit counter.  The Timer1 will be programmed to
   use a DIVIDE BY 4 prescaler (see the setup_timer_1 function call).
   Therefore, the number of interrupts per second is:

      4,000,000 / 4 / 4 / 2^16 = 3.814... Hz

   Or, 1 tick is 262ms, or roughly 1/4 second

   Note: Look at the interrupt service routine to see how tick counters
	 are done.  Basically, they are little background down counters.

*/

/* Cycle switch debounce (sort of like debounce.. see the state machine) */
#define TICKS_CYCLESWITCH      2

/* Initial charging rule is only in effect briefly after power up. */
#define TICKS_INITIAL_CHARGE    4

/* Forward direction timeout (90 seconds) */
#define TICKS_FORWARD          360

/* Reverse direction timeout (90 seconds) */
#define TICKS_REVERSE          360

/* Lamptest time duration */
#define TICKS_LAMPTEST         2

/* Minimum time between any change in charger state */
#define TICKS_CHARGER_HYST     4

/* Delay after cycle is done before direction solenoid released */
#define TICKS_CYCLE_DONEDELAY  1

/* Time period after forward-reverse changeover when sensors ignored. */
#define TICKS_IGNORE_SENSORS   4

/* Sense if the Self Test is being requested.  This is done through
   the RC5 input.  If the switch on it is closed, this port
   will read 0 which means YES run the self-test. */
int SelfTestRequested (void);

/* The self test used during manufacturing. */
void SelfTest (void);
void SelfTestFail (void);  /* Called if fail.. will blink LEDs forever. */

/* Update the nBatteryVoltage variable by sampling voltage with A/D */
void GetBatteryVoltage(void);

/* Start Motor */
void StartMotor (void);

/* Stop Motor */
void StopMotor (void);

/* Forward (direction solenoid energized) */
void Forward (void);

/* Reverse  (direction solenoid de-energized) */
void Reverse (void);

/* Return true if the retracted sensor is active */
int SenseRetracted (void);

/* Return true if the extended over pressure sensor is active */
int SenseExtended (void);

/* Sense if the multicycle option is enabled.  This is done through
   the A/D port 1. */
int MultiCyclesEnabled (void);

/* Sense if the initial retract option is enabled.  This is done through
   the A/D port 4. */
int InitialRetractsEnabled (void);

/* Main program and main loop */
main ()
{
   /* Note:  all printf calls are sent out RS232 port at 4800 baud. */
   printf ("TRASH COMPACTOR V0.0\r");

   /* Initially turn all relays off. */
   output_low (CHARGE_RLY);
   output_low (DIR_RLY);
   output_low (MOTOR_RLY);
   output_low (RECYCLE_RLY);

   /* Initialize interface to the A/D chip. */
   output_low  (ADC_CLK);
   output_high (ADC_CS);

   /* Initialize variables */
   byTicks_Charger_Hysterysis = 0;
	nTicks_Reverse = 0;
   nTicks_Forward = 0;
   nTicks_Paused  = 0;
   byTicks_CycleSwitch = 0;
   byTicks_Delay = 0;
   byTicks_Display = 0;

   byTicks_Initial_Charge = 0;
   bEverCharged = FALSE;

   byPendingCycles = 0;
   byCycleSwitchState = 0;
   byCycleState = 0;

   bServiceSoon = FALSE;
   bCharging = FALSE;
   bMotorPaused = FALSE;
   bEnoughMotorJuice = FALSE;
   bTimeoutOccured = FALSE;
   bBatteryProtect = FALSE;
	bBatteryEverOK = FALSE;
   bMotorOn = FALSE;

   /* Testing! */
   printf ("Sensors: ");
   if (input(EXTENDED))  printf ("1");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -