Newsgroups: comp.home.automation,comp.protocols.misc,comp.realtime,comp.robotics,comp.sys.m6809
From: noel@sectel.com (Noel Anderson)
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!news2.near.net!howland.reston.ans.net!pipex!peernews.demon.co.uk!sectel.com!noel
Subject: Re: 68HC05 Serial Interrupts (Desperate)
References:  <11349.9501271123@eestud1.elec.glasgow.ac.uk>
Followup-To: comp.home.automation
Cc: noel@sectel.com
X-Mailer: cppnews $Revision: 1.42 $
Organization: Securicor Telecoms
Lines: 150
X-Posting-Host: sectel.demon.co.uk
Date: Thu, 2 Feb 1995 09:39:17 +0000
Message-ID: <791743157snx@sectel.com>
Sender: usenet@demon.co.uk
Xref: glinda.oz.cs.cmu.edu comp.home.automation:5095 comp.protocols.misc:4894 comp.realtime:8483 comp.robotics:17554 comp.sys.m6809:3154

In article <11349.9501271123@eestud1.elec.glasgow.ac.uk>
   927191st@elec.gla.ac.UK (E and E  Undergraduate, Eng.) writes:
>
> Hello,
>   I am doing a project work on a robotic arm that is controlled by a
> Motorola 68HC05 microcontroller. I have a very serious problem however,
>
>   I want to communicate with a terminal the SCI serial port (port D)
>
> I set correctly the interrupt masks, the vector table at 1ff6-1ff7 locations
> but when a byte comes, the interrupt occurs but the program counter is not
> loaded with the vector address and the program crashes, as I find my PC
> hanging around my data and unused memory.


You didn't say which version of the 68HC05 you're using, there are some
differences in their interrupt structures.

Here is some code for the 68HC05C4/C8/C9 flavours. This code has been used
in anger so it does work.

The code was done in C using the Bytecraft C6805 C compiler, and what's below
is the lising output with both the C and the resulting assembler.

Only the receive is interrupt driven with received bytes placed in a circular
buffer, transmit is direct to port.


--->> SCI Initialisation Section
                                      /*
                                       +--------------------------------------------------------------------------+
                                       |  SCI enabled, 9600 baud selected (4MHz Clock)                            |
                                       +--------------------------------------------------------------------------+
                                      */
018E 3F 0E     CLR    $0E             sci_control1 = 0x00;
0190 A6 2C     LDA    #$2C            sci_control2 = 0x2C; /* RIE, RE, TE bits set */
0192 B7 0F     STA    $0F
0194 A6 30     LDA    #$30            sci_baud     = 0x30; /* SCP0, SCP1 bits set */
0196 B7 0D     STA    $0D


--->> SCI Receive Interrupt Handler


005F 0006                         unsigned char  comms_buf[COMMS_BUFFER_SIZE];    /* Serial comms buffer          */
0065                              unsigned int  in_pos;                           /* Where to put next recieved byte  */
0066                              unsigned int  out_pos;                          /* Where to read next byte fom buffer   */

                                  /*
                                   +--------------------------------------------------------------------------+
                                   |  Function  :  SCI Interrupt service routine                              |
                                   |               Entry forced by received character, ie rdrf bit set.       |
                                   |               Status register is checked for over-run, framing & noise   |
                                   |               errors.  If ok then character is placed in recieve buffer, |
                                   |               the buffer pointers updated and 'Data In Buffer' flag set. |
                                   |                                                                          |
                                   |  Arguments :  -                                                          |
                                   |  Returns   :  -                                                          |
                                   +--------------------------------------------------------------------------+
                                  */
                                  void SCI(void)
1FF6 01 9D                            {
019D 0B 10 18  BRCLR 5,$10,$01B8      if (sci_status.rdrf)                    /* Check it really is here due to recieved data */
                                          {
01A0 B6 10     LDA    $10                 if ( (sci_status & (1<<fe | 1<<or | 1<<nf)) == CLEAR )
01A2 A4 0E     AND    #$0E
01A4 26 12     BNE    $01B8
                                              {
01A6 B6 11     LDA    $11                     comms_buf[in_pos] = sci_data;       /* Save in buffer */
01A8 BE 65     LDX    $65
01AA E7 5F     STA    $5F,X
01AC 3C 65     INC    $65                     if (++in_pos == COMMS_BUFFER_SIZE) in_pos = 0;   /* If at array top start again */
01AE B6 65     LDA    $65
01B0 A1 06     CMP    #$06
01B2 26 02     BNE    $01B6
01B4 3F 65     CLR    $65
01B6 10 50     BSET  0,$50                    setflag(control_flag,dib);      /* Set data in buffer flag */
                                              }
                                          }
                                      /* In case somethings screwed up, read data to clear interrupt flags */
01B8 B6 11     LDA    $11             accumulator = sci_data;
01BA 80        RTI                    }



--->> SCI Send one Byte ie. Putc()
      Yes, I know there are some tight loops on a hardware bit in there,
      but there was a watchdog to restart if it got stuck.

                                  /*
                                   +--------------------------------------------------------------------------+
                                   |  Function  :  Send Byte Routine                                          |
                                   |               Outputs byte to SCI.                                       |
                                   |               Tests tc bit in SCI status register to check SCI is ready  |
                                   |               to send.                                                   |
                                   |                                                                          |
                                   |  Arguments :  Accumulator 'a'contains byte to transmit                   |
                                   |  Returns   :  Index register                                             |
                                   +--------------------------------------------------------------------------+
                                  */
                                  void send_byte( registera a)
0000                                  {
0245 0D 10 FD  BRCLR 6,$10,$0245      while (sci_status.tc == 0); /* Wait till ready */
0248 B7 11     STA    $11             sci_data = a;               /* Send it */
024F 81        RTS                    }



--->> SCI Get one Byte ie. getc() reads from serial buffer.


                                  /*
                                   +--------------------------------------------------------------------------+
                                   |  Function  :  Get Byte                                                   |
                                   |                 Gets next character from SCI recieve buffer.             |
                                   |                 If input & output pointers are the same ie buffer empty, |
                                   |                 resets dib flag (Data In Buffer).                        |
                                   |                                                                          |
                                   |    Arguments :  -                                                        |
                                   |    Returns   :  received char (in accumulator)                           |
                                   +--------------------------------------------------------------------------+
                                  */
                                  char get_byte()
                                      {
0250 BE 66     LDX    $66             index = comms_buf[out_pos];
0252 E6 5F     LDA    $5F,X
0254 97        TAX
0255 3C 66     INC    $66           if(++out_pos == COMMS_BUFFER_SIZE)  /* End of buffer, wrap around */
0257 B6 66     LDA    $66
0259 A1 06     CMP    #$06
025B 26 02     BNE    $025F
025D 3F 66     CLR    $66                 out_pos = 0;
025F B6 66     LDA    $66           if (out_pos == in_pos)              /* Emptied buffer ? */
0261 B1 65     CMP    $65
0263 26 02     BNE    $0267
0265 11 50     BCLR  0,$50                clearflag(control_flag, dib);
0267 9F        TXA                    return index;
0268 81        RTS
                                      }



This code is my own and not the property of my employers.



  /|  /  ___   ___  /      Noel Anderson
 / | / /   / /___  /      Securicor Telecoms, R&D, Westcote House,
/  |/ /___/ /___  /___   Somerford Road, Cirencester, Glos, England. GL7 1TW
Voice: +44 1285 655766    Fax: +44 1285 655595     Email: noel@sectel.com
