home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / microcrn / issue_49.arc / 6805DEMO.ARC / EXAMPLE.ASM
Assembly Source File  |  1989-07-11  |  13KB  |  364 lines

  1. *  Micro Cornucopia Magazine Issue #49
  2. *  6805 Controller Example Project Code
  3. *
  4. *  EXAMPLE.ASM
  5. *
  6. *  Sample program showing design of control program, to be run from
  7. *  the EPROM of an MC68HC705 MCU.  The program monitors one channel
  8. *  of A/D, using an MC145041 Serial A/D converter chip.  LEDs are
  9. *  sequenced as needed, depending on the value of the A/D channel.
  10. *
  11. *  The A/D chip connects to the MCU through the Serial Peripheral
  12. *  Interface (SPI).  The chip select line for the A/D is bit 3 of MCU
  13. *  Port C; a low on this line selects the A/D chip.
  14. *
  15. *  Three status LEDs connect to bits 0-2 of MCU port C.  LED1 (port C,
  16. *  bit 0) stays on at all times, to show the program is actually running.
  17. *  LED2 (port C, bit 1) stays on at all times, provided the A/D value
  18. *  stays below $40.  If the value rises to between $40 and $7F, LED2
  19. *  blinks once per second.  If the value rises above $7F, LED2 goes out.
  20. *  LED3 (port C, bit 2) only comes on if the A/D value reaches $80.
  21. *  If the value lies between $80 and $BF, LED3 stays on.  If the value
  22. *  rises above $BF, LED3 blinks once per second.
  23. *
  24. *  The code for routine TIME and much of the code in MAIN comes directly
  25. *  from the example development project in the M68HC05 Microcontroller
  26. *  Applications Guide.  Refer to pages 4-24 for the original listing.
  27. *  The same program is provided by Motorola as Freeware and as source
  28. *  code on the program disc that accompanies the Applications Guide.
  29. *  I would give credit to the original programmer, if I knew who he/she
  30. *  was.
  31. *
  32.  
  33.  
  34. *
  35. *  Register equates
  36. *
  37.  
  38. PORTA    EQU     $00       Port A data register
  39. PORTB    EQU     $01       Port B data register
  40. PORTC    EQU     $02       Port C data register
  41. PORTD    EQU     $03       Port D data register
  42. DDRA     EQU     $04       Data direction, Port A
  43. DDRB     EQU     $05       Data direction, Port B
  44. DDRC     EQU     $06       Data direction, Port C
  45. SPCR     EQU     $0A       SPIE,SPE,-,MSTR;CPOL,CPHA,SPR1,SPR0
  46. SPSR     EQU     $0B       SPIF,WCOL,-,MODF;-,-,-,-
  47. SPDR     EQU     $0C       SPI Data
  48. BAUD     EQU     $0D       -,-,SCP1,SCP0;-,SCR2,SCR1,SCR0
  49. SCCR1    EQU     $0E       R8,T8,-,M;WAKE,-,-,-
  50. SCCR2    EQU     $0F       TIE,TCIE,RIE,ILIE;TE,RE,RWU,SBK
  51. SCSR     EQU     $10       TDRE,TC,RDRF,IDLE;OR,NF,FE,-
  52. SCDR     EQU     $11       SCI Data
  53. RDR      EQU     $11       SCI Receive Data (same as SCDR)
  54. TDR      EQU     $11       SCI Transmit Data (same as SCDR)
  55. TCR      EQU     $12       ICIE,OCIE,TOIE,0;0,0,IEGE,OLVL
  56. TSR      EQU     $13       ICF,OCF,TOF,0; 0,0,0,0
  57. ICAP     EQU     $14       Input Capture Reg (Hi-$14, Lo-$15)
  58. OCMP     EQU     $16       Output Compare Reg (Hi-$16, Lo-$17)
  59. TCNT     EQU     $18       Timer Count Reg (Hi-$18, Lo-$19)
  60. ALTCNT   EQU     $1A       Alternate Count Reg (Hi-$1A, Lo-$1B)
  61.  
  62. *
  63. *  Following equates are timer values to produce a 50 msec delay
  64. *  using the MCU timing registers.  Use ONLY one pair of values,
  65. *  depending on the MCU timing crystal for the target system.
  66. *
  67.  
  68. TMRCNTL  EQU     $D4       FOR 2.0 MHZ CLOCK
  69. TMRCNTH  EQU     $30
  70.  
  71. *  TMRCNTL  EQU     $6A        FOR 1.0 MHZ CLOCK
  72. *  TMRCNTH  EQU     $18
  73.  
  74.  
  75.  
  76.          ORG     $50       START OF VARIABLES IN RAM
  77.  
  78. TEMPA    RMB     1         TEMP STORAGE FOR ACC
  79. TEMPX    RMB     1         TEMP STORAGE FOR XR
  80.  
  81. TIC      RMB     1         50 MSEC TICS; 0-19, 20 TICS = 1 SEC
  82. SEC      RMB     1         CURRENT TIME IN SECONDS
  83. MIN      RMB     1         CURRENT TIME IN MINUTES
  84. HR       RMB     1         CURRENT TIME IN HOURS
  85. AMPM     RMB     1         CURRENT TIME (0 = AM, 1 = PM)
  86. DAY      RMB     1         CURRENT DAY (1 = SUN...7 = SAT)
  87.  
  88.  
  89. LED1     RMB     1         CONTROL BYTE FOR LED1 (0 = DARK)
  90. LED2     RMB     1         CONTROL BYTE FOR LED2 (0 = DARK)
  91. LED3     RMB     1         CONTROL BYTE FOR LED3 (0 = DARK)
  92.  
  93.  
  94.          ORG     $0100     START OF PROGRAM IN ROM
  95.  
  96. INIT     RSP               INITIALIZE THE STACK POINTER
  97.  
  98. *
  99. *  Set timer and SPI characteristics.
  100. *
  101.  
  102.          LDA     #$50      SPI: MCU IS MASTER, 2 USEC CLOCK
  103.          STA     SPCR      WRITE TO SPI CONTROL REG
  104.          CLRA              TIMER: NO INTERRUPTS OR PINS USED
  105.          STA     TCR       WRITE TO TIMER CONTROL REG
  106.  
  107. *
  108. *  Set up port C, bits 0-2 for output as LED controllers.
  109. *  Clear LED control bytes (turns LEDs off later).
  110. *
  111. *  Set up port C, bit 3 for output as A/D chip select.
  112. *
  113.  
  114.          LDA     #$0F      BITS 0-3 = OUTPUT, ALL OTHERS = INPUT
  115.          STA     DDRC      SETUP PORT C
  116.          CLR     LED1      SHOW ALL LEDS AS OFF
  117.          CLR     LED2
  118.          CLR     LED3
  119.  
  120. *
  121. *  Initialize clock to show 12:00 AM Sunday.
  122. *
  123.  
  124.          CLR     TIC       ZERO THE TIC COUNTER
  125.          CLR     SEC       SET SECONDS TO 0
  126.          LDA     #12       SET HOUR TO NOON
  127.          STA     HR
  128.          CLR     MIN       SET MINUTES TO 0
  129.          CLR     AMPM      SET TO MORNING
  130.          LDA     #1        SET DAY TO SUNDAY
  131.          STA     DAY
  132.  
  133. *
  134. *              ----- END OF INITIALIZATION -----
  135. *
  136.  
  137.  
  138.  
  139. *
  140. *  MAIN
  141. *
  142. *  This loop gets executed once each 50 msec, based on the
  143. *  MCU's internal timer.  The compare register is loaded
  144. *  with a target value.  When the timer hits that value,
  145. *  bit 6 of the Output Compare Register (OCR) gets set,
  146. *  marking the end of a 50 msec interval.
  147. *
  148. *  At each interval, the timer is reloaded, the time/day clock
  149. *  is updated, and the chain of subroutines at the bottom of
  150. *  the loop is executed.  So long as the chain takes no more
  151. *  than 50 msec to complete, the MCU will stay on-time.
  152. *
  153.  
  154. MAIN     EQU     *
  155.          BRCLR   6,TSR,MAIN    LOOP HERE UNTIL TIME OUT
  156.          LDA     OCMP+1        LOW BYTE OF OCR
  157.          ADD     #TMRCNTL      CALCULATE NEW TIMER TARGET
  158.          STA     TEMPA
  159.          LDA     OCMP          DO BOTH HALVES OF 16-BIT VALUE
  160.          ADC     #TMRCNTH
  161.          STA     OCMP
  162.          LDA     TEMPA
  163.          STA     OCMP+1        TIMER TARGET RELOADED
  164.  
  165.          LDA     TIC           GET TIC COUNTER
  166.          INCA                  BUMP IT
  167.          STA     TIC           AND SAVE NEW VALUE
  168.          CMP     #20           DONE ONE SECOND YET?
  169.          BLO     ARNC1         IF NOT, DON'T CLEAR TIC
  170.          CLR     TIC           YES, START A NEW SECOND
  171. ARNC1    EQU     *
  172.  
  173. *
  174. *  End of the timing loop; following chain of subroutine calls
  175. *  must complete within 50 msecs.
  176. *
  177.  
  178.          JSR     TIME          UPDATE TIME-OF-DAY CLOCK
  179.          JSR     PROCESS       READ A/D, SET LED CONTROL BYTES
  180.          JSR     LEDS          PROCESS PENDING LED COMMANDS
  181.          BRA     MAIN          DO IT ALL AGAIN
  182.  
  183. *
  184. *  TIME
  185. *
  186. *  Update the time-of-day clock.
  187. *
  188.  
  189. TIME     EQU     *
  190.          TST     TIC       Check for TIC=zero
  191.          BNE     XTIME     If not; just exit
  192.          INC     SEC       SEC=SEC+1
  193.          LDA     #60
  194.          CMP     SEC       Did SEC -> 60 ?
  195.          BNE     XTIME     If not; just exit
  196.          CLR     SEC       Seconds rollover
  197.          INC     MIN       MIN=MIN+1
  198.          CMP     MIN       A still 60; MIN=60 ?
  199.          BNE     XTIME     If not; just exit
  200.          CLR     MIN       Minutes rollover
  201.          INC     HR        HR=HR+1
  202.          LDA     HR        For comparisons
  203.          CMP     #13       HR=13 ?
  204.          BNE     ARNS1     If not; skip
  205.          LDA     #1
  206.          STA     HR        Set HR=1
  207.          BRA     XTIME     Exit
  208. ARNS1    CMP     #12       HR=12 ?
  209.          BNE     XTIME     If not; just exit
  210.          LDA     AMPM
  211.          EOR     #%00000001  Invert AM/PM bit
  212.          STA     AMPM      0=AM, 1=PM
  213.          BNE     XTIME     If not AM now; just exit
  214.          INC     DAY       DAY=DAY+1
  215.          LDA     DAY
  216.          CMP     #8        Day rollover ?
  217.          BNE     XTIME     If not; just exit
  218.          LDA     #1
  219.          STA     DAY       Set Day to 1 (SUN)
  220. XTIME    RTS
  221.  
  222.  
  223.  
  224. *
  225. *  LEDS -- Process any pending LED commands, based on the LED
  226. *  control bytes.
  227. *
  228. *  Each LED control byte determines whether an LED is turned on
  229. *  or off.  If the byte is 0, that LED is always turned off by this
  230. *  routine.  If the byte is not 0, the corresponding LED is always
  231. *  turned on and the control byte is decremented.
  232. *
  233. *  If this routine is called each slice (20 times per second), the
  234. *  longest period of time an LED can remain lit without intervention
  235. *  is 255 * 50 msec = 12750 msec or 12.75 seconds.
  236. *
  237.  
  238. LEDS     TST     LED1      NEED TO TURN ON LED1?
  239.          BEQ     LED1N     BRANCH IF TIME TO TURN OFF
  240.          BCLR    0,PORTC   TURN ON LED1 (ACTIVE LOW)
  241.          DEC     LED1      COUNT THIS 50 MSEC
  242.          BRA     LED2T     GO TEST LED2
  243. LED1N    BSET    0,PORTC   TURN OFF LED1
  244.  
  245. LED2T    TST     LED2      DO IT AGAIN FOR LED2
  246.          BEQ     LED2N
  247.          BCLR    1,PORTC   USE BIT 1 FOR LED2
  248.          DEC     LED2
  249.          BRA     LED3T
  250. LED2N    BSET    1,PORTC
  251.  
  252. LED3T    TST     LED3      SAME AGAIN FOR LED3
  253.          BEQ     LED3N
  254.          BCLR    2,PORTC   USE BIT 2 FOR LED3
  255.          DEC     LED3
  256.          BRA     LEDSX
  257. LED3N    BSET    2,PORTC
  258. LEDSX    RTS
  259.  
  260.  
  261. *
  262. *  PROCESS -- Change LED control bytes as needed to reflect current
  263. *  status of A/D input.
  264. *
  265. *  If TIC holds a 0 (first 50 msec slice of each second), read channel
  266. *  0 of the A/D and trash the returned value.
  267. *
  268. *  If TIC holds a 1 (second 50 msec slice of each second), read
  269. *  channel 0 of the A/D and process the LED states, depending on the
  270. *  following:
  271. *
  272. *  Value range                    Action taken
  273. *  -----------    --------------------------------------------
  274. *
  275. *   $00 - $3F     Turn LED2 on for one second, turn LED3 off.
  276. *   $40 - $7F     Turn LED2 on for .5 seconds, turn LED3 off.
  277. *   $80 - $BF     Turn LED2 off, turn LED3 on for one second.
  278. *   $C0 - $FF     Turn LED2 off, turn LED3 on for .5 seconds.
  279. *
  280. *  All other values of TIC are ignored by this routine.  Note
  281. *  that LED1 is always on.
  282. *
  283.  
  284. PROCESS
  285.          LDA     #$FF      GET LONGEST ON-TIME
  286.          STA     LED1      ALWAYS LEAVE LED1 ON
  287.          LDA     TIC       GET CURRENT TIC VALUE
  288.          BNE     PROCS1    BRANCH IF NOT FIRST TIC
  289.          BSR     A2D       LOAD UP CHANNEL 0 VALUE
  290.          BRA     PROCSX    AND LEAVE
  291.  
  292. PROCS1   CMP     #1        IS THIS THE SECOND TIC?
  293.          BNE     PROCSX    BRANCH IF NOT
  294.          CLRA              LOAD UP CHANNEL 0 AGAIN
  295.          BSR     A2D       AND READ THAT CHANNEL
  296.  
  297.          CMP     #$40      IS VALUE IN GOOD RANGE?
  298.          BHS     PROCS2    BRANCH IF NOT
  299.          CLR     LED3      TURN OFF LED3
  300.          LDA     #20       TURN ON LED2 FOR 1 SECOND
  301.          STA     LED2
  302.          BRA     PROCSX    AND LEAVE
  303.  
  304. PROCS2   CMP     #$80      IS VALUE IN FAIR RANGE?
  305.          BHS     PROCS3    BRANCH IF NOT
  306.          CLR     LED3      TURN OFF LED3
  307.          LDA     #10       TURN ON LED2 FOR .5 SECONDS
  308.          STA     LED2
  309.          BRA     PROCSX    AND LEAVE
  310.  
  311. PROCS3   CMP     #$C0      IS VALUE IN POOR RANGE?
  312.          BHS     PROCS4    BRANCH IF NOT
  313.          CLR     LED2      TURN OFF LED2
  314.          LDA     #20       TURN ON LED3 FOR 1 SECOND
  315.          STA     LED3
  316.          BRA     PROCSX    AND LEAVE
  317.  
  318. PROCS4   CLR     LED2      MUST BE BAD, SHUT OFF LED2
  319.          LDA     #10       TURN ON LED3 FOR .5 SECONDS
  320.          STA     LED3
  321.  
  322. PROCSX   RTS
  323.  
  324.  
  325. *
  326. *  A2D -- Read selected channel of serial A/D (MC145041).
  327. *
  328. *  Enter with A/D channel number in ACC.  Returns analog value
  329. *  in ACC.  Assumes chip select line to A/D chip is driven by
  330. *  port C, bit 3 (active low).
  331. *
  332. *  Note that the value returned by A2D corresponds to the most
  333. *  recent previous channel number transmitted, not the current
  334. *  channel number!  Therefore, unless you know for a fact that
  335. *  the last channel number you sent was the one you want to read
  336. *  now, you had better call this routine twice, using the same
  337. *  channel number.
  338. *
  339.  
  340. A2D
  341.          TST     SPSR      CLEAR SPIF
  342.          BCLR    3,PORTC   PULL CHIP SELECT LINE LOW
  343.          ASLA              MOVE CHANNEL NUMBER TO HIGH NYBBLE
  344.          ASLA
  345.          ASLA
  346.          ASLA
  347.          STA     SPDR      SEND CHANNEL TO SPI
  348.  
  349. SPIFLP   BRCLR   7,SPSR,SPIFLP    WAIT UNTIL COMPLETE
  350.          BSET    3,PORTC   RELEASE CHIP SELECT
  351.          LDA     SPDR      GET VALUE RETURNED
  352.          RTS
  353.  
  354.  
  355.  
  356. *
  357. *  Set up the RESET vector.  This is required for code that will
  358. *  be moved into the MCU's EPROM for later execution.
  359. *
  360.  
  361.          ORG     $1FFE     RESET VECTOR
  362.  
  363.          FDB     INIT      POINT TO START OF PROGRAM
  364.