Here is the file ``main.c.''
#include "ports.h" #include "./sio.h" #define OC3 0x20 #define OC4 0x10 #define RDRF 0x20 #define TDRE 0x80 #define TC 0x40 void A2Dinit(void); unsigned int A2Dread(void); unsigned int insci(void); long int high; long int low; int main() { /* start at zero */ char msg[25]; short int pos; unsigned int pot,hi; high = 2000; low = 40000 - high; /* * Interrupts are disabled to set up output compare interrupt * for the clock. */ asm(" SEI "); /* disable interrupts */ TFLG1 = OC3; /* Clear TOC3 register */ TMSK1 |= OC3; /* Enable interrupt TOC3 */ TCTL1 |= 0x30; TOC3 = TCNT + 50; asm(" CLI "); /* enable interrupts */ serial_init(); A2Dinit(); /* * Interrupts are now re-enabled. */ while(1) { pos = 0; pot = A2Dread(); high = 2000+((long)pot*2000)/255; low = 40000 - high; hi = high; msg[pos++] = pot/100 + '0'; pot = pot-pot/100*100; msg[pos++] = (pot)/10 + '0'; pot = pot-pot/10*10; msg[pos++] = pot + '0'; msg[pos++] = ' '; msg[pos++] = hi/1000 + '0'; hi = hi - hi/1000*1000; msg[pos++] = hi/100 + '0'; hi = hi - hi/100*100; msg[pos++] = hi/10 + '0'; hi = hi - hi/10*10; msg[pos++] = hi + '0'; msg[pos++] = '\r'; msg[pos++] = 0x00; serial_print(msg); } } /* * Output compare 3 interrupt service routine. * Just increments time, which counts milliseconds. */ void TOC3isr(void) __attribute__((interrupt)); void TOC3isr(void) { if(TCTL1&0x10) { TOC3 = TOC3 + high; TCTL1 &= 0xEF; } else { TOC3 = TOC3 + low; TCTL1 |= 0x10; } TFLG1 = 0x20; } void cyclewait(unsigned short cycles) { TOC4 = TCNT + cycles; TFLG1 = OC4; while((TFLG1 & OC4)==0); } /* void SCIinit(void) */ /* { */ /* BAUD = 0x30; */ /* SCCR1 = 0x00; */ /* SCCR2 = 0x0C; */ /* } */ unsigned int insci(void) { while((SCSR & RDRF) == 0); return(SCDR); } void A2Dinit(void) { /* continuous scan, channel PE0 */ OPTION |= 0x80; OPTION &= ~0x40; ADCTL = 0x20; } unsigned int A2Dread(void) { while(!(ADCTL |= 0x80)); return (unsigned int)ADR1; }
Here is ``ports.h.''
/* m68hc11/ports_def.h -- Definition of 68HC11 ports Copyright 1999, 2000 Free Software Foundation, Inc. Written by Stephane Carrez (stcarrez@worldnet.fr) This file is part of GDB, GAS, and the GNU binutils. GDB, GAS, and the GNU binutils are free software; you can redistribute them and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. GDB, GAS, and the GNU binutils are distributed in the hope that they will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _M68HC11_PORTS_DEF_H #define _M68HC11_PORTS_DEF_H #define _IO_BASE 0x1000 #define _P(off) *(unsigned char volatile *)(_IO_BASE + off) #define _LP(off) *(unsigned short volatile *)(_IO_BASE + off) /* Flags for the definition of the 68HC11 & 68HC12 CCR. */ #define S_BIT 0x80 /* Stop disable */ #define X_BIT 0x40 /* X-interrupt mask */ #define H_BIT 0x20 /* Half carry flag */ #define I_BIT 0x10 /* I-interrupt mask */ #define N_BIT 0x08 /* Negative */ #define Z_BIT 0x04 /* Zero */ #define V_BIT 0x02 /* Overflow */ #define C_BIT 0x01 /* Carry */ /* 68HC11 register address offsets (range 0..0x3F or 0..64). The absolute address of the I/O register depends on the setting of the INIT register. At init time, the I/O registers are mapped at 0x1000. Address of registers is then: 0x1000 + xxx */ #define PORTA _P(0x00) /* Port A register */ #define _RES1 _P(0x01) /* Unused/Reserved */ #define PIOC _P(0x02) /* Parallel I/O Control register */ #define PORTC _P(0x03) /* Port C register */ #define PORTB _P(0x04) /* Port B register */ #define PORTCL _P(0x05) /* Alternate latched port C */ #define _RES6 _P(0x06) /* Unused/Reserved */ #define DDRC _P(0x07) /* Data direction register for port C */ #define PORTD _P(0x08) /* Port D register */ #define DDRD _P(0x09) /* Data direction register for port D */ #define PORTE _P(0x0A) /* Port E input register */ #define CFORC _P(0x0B) /* Compare Force Register */ #define OC1M _P(0x0C) /* OC1 Action Mask register */ #define OC1D _P(0x0D) /* OC1 Action Data register */ #define TCNT _LP(0x0E) /* Timer Counter Register */ #define TCNT_H _P(0x0E) /* " " " High part */ #define TCNT_L _P(0x0F) /* " " " Low part */ #define TIC1 _LP(0x10) /* Input capture 1 register */ #define TIC1_H _P(0x10) /* " " " High part */ #define TIC1_L _P(0x11) /* " " " Low part */ #define TIC2 _LP(0x12) /* Input capture 2 register */ #define TIC2_H _P(0x12) /* " " " High part */ #define TIC2_L _P(0x13) /* " " " Low part */ #define TIC3 _LP(0x14) /* Input capture 3 register */ #define TIC3_H _P(0x14) /* " " " High part */ #define TIC3_L _P(0x15) /* " " " Low part */ #define TOC1 _LP(0x16) /* Output Compare 1 register */ #define TOC1_H _P(0x16) /* " " " High part */ #define TOC1_L _P(0x17) /* " " " Low part */ #define TOC2 _LP(0x18) /* Output Compare 2 register */ #define TOC2_H _P(0x18) /* " " " High part */ #define TOC2_L _P(0x19) /* " " " Low part */ #define TOC3 _LP(0x1A) /* Output Compare 3 register */ #define TOC3_H _P(0x1A) /* " " " High part */ #define TOC3_L _P(0x1B) /* " " " Low part */ #define TOC4 _LP(0x1C) /* Output Compare 4 register */ #define TOC4_H _P(0x1C) /* " " " High part */ #define TOC4_L _P(0x1D) /* " " " Low part */ #define TOC5 _LP(0x1E) /* Output Compare 5 register */ #define TOC5_H _P(0x1E) /* " " " High part */ #define TOC5_L _P(0x1F) /* " " " Low part */ #define TCTL1 _P(0x20) /* Timer Control register 1 */ #define TCTL2 _P(0x21) /* Timer Control register 2 */ #define TMSK1 _P(0x22) /* Timer Interrupt Mask Register 1 */ #define TFLG1 _P(0x23) /* Timer Interrupt Flag Register 1 */ #define TMSK2 _P(0x24) /* Timer Interrupt Mask Register 2 */ #define TFLG2 _P(0x25) /* Timer Interrupt Flag Register 2 */ #define PACTL _P(0x26) /* Pulse Accumulator Control Register */ #define PACNT _P(0x27) /* Pulse Accumulator Count Register */ #define SPCR _P(0x28) /* SPI Control register */ #define SPSR _P(0x29) /* SPI Status register */ #define SPDR _P(0x2A) /* SPI Data register */ #define BAUD _P(0x2B) /* SCI Baud register */ #define SCCR1 _P(0x2C) /* SCI Control register 1 */ #define SCCR2 _P(0x2D) /* SCI Control register 2 */ #define SCSR _P(0x2E) /* SCI Status register */ #define SCDR _P(0x2F) /* SCI Data (Read => RDR, Write => TDR) */ #define ADCTL _P(0x30) /* A/D Control register */ #define ADR1 _P(0x31) /* A/D, Analog Result register 1 */ #define ADR2 _P(0x32) /* A/D, Analog Result register 2 */ #define ADR3 _P(0x33) /* A/D, Analog Result register 3 */ #define ADR4 _P(0x34) /* A/D, Analog Result register 4 */ #define _RES35 _P(0x35) #define _RES36 _P(0x36) #define _RES37 _P(0x37) #define _RES38 _P(0x38) #define OPTION _P(0x39) /* System Configuration Options */ #define COPRST _P(0x3A) /* Arm/Reset COP Timer Circuitry */ #define PPROG _P(0x3B) /* EEPROM Programming Control Register */ #define HPRIO _P(0x3C) /* Highest priority I-Bit int and misc */ #define INIT _P(0x3D) /* Ram and I/O mapping register */ #define TEST1 _P(0x3E) /* Factory test control register */ #define CONFIG _P(0x3F) /* COP, ROM and EEPROM enables */ /* Flags of the CONFIG register (in EEPROM). */ #define NOSEC 0x08 /* Security mode disable */ #define NOCOP 0x04 /* COP system disable */ #define ROMON 0x02 /* Enable on-chip rom */ #define EEON 0x01 /* Enable on-chip eeprom */ /* Flags of the PPROG register. */ #define BYTE 0x10 /* Byte mode */ #define ROW 0x08 /* Row mode */ #define ERASE 0x04 /* Erase mode select (1 = erase, 0 = read) */ #define EELAT 0x02 /* EEPROM Latch Control */ #define EEPGM 0x01 /* EEPROM Programming Voltage Enable */ /* Flags of the PIOC register. */ #define STAF 0x80 /* Strobe A Interrupt Status Flag */ #define STAI 0x40 /* Strobe A Interrupt Enable Mask */ #define CWOM 0x20 /* Port C Wire OR mode */ #define HNDS 0x10 /* Handshake mode */ #define OIN 0x08 /* Output or Input handshaking */ #define PLS 0x04 /* Pulse/Interlocked Handshake Operation */ #define EGA 0x02 /* Active Edge for Strobe A */ #define INVB 0x01 /* Invert Strobe B */ /* Flags of the SCCR1 register. */ #define R8 0x80 /* Receive Data bit 8 */ #define T8 0x40 /* Transmit data bit 8 */ #define _SCCR1_5 0x20 /* Unused */ #define M 0x10 /* SCI Character length */ #define WAKE 0x08 /* Wake up method select (0=idle, 1=addr mark) */ /* Flags of the SCCR2 register. */ #define TIE 0x80 /* Transmit Interrupt enable */ #define TCIE 0x40 /* Transmit Complete Interrupt Enable */ #define RIE 0x20 /* Receive Interrupt Enable */ #define ILIE 0x10 /* Idle Line Interrupt Enable */ #define TE 0x08 /* Transmit Enable */ #define RE 0x04 /* Receive Enable */ #define RWU 0x02 /* Receiver Wake Up */ #define SBK 0x01 /* Send Break */ /* Flags of the SCSR register. */ #define TDRE 0x80 /* Transmit Data Register Empty */ #define TC 0x40 /* Transmit Complete */ #define RDRF 0x20 /* Receive Data Register Full */ #define IDLE 0x10 /* Idle Line Detect */ #define OR 0x08 /* Overrun Error */ #define NF 0x04 /* Noise Flag */ #define FE 0x02 /* Framing Error */ #define _SCSR_0 0x01 /* Unused */ /* Flags of the BAUD register. */ #define TCLR 0x80 /* Clear Baud Rate (TEST mode) */ #define _BAUD_6 0x40 /* Not used */ #define SCP1 0x20 /* SCI Baud rate prescaler select */ #define SCP0 0x10 #define RCKB 0x08 /* Baud Rate Clock Check (TEST mode) */ #define SCR2 0x04 /* SCI Baud rate select */ #define SCR1 0x02 #define SCR0 0x01 #define BAUD_DIV_1 (0) #define BAUD_DIV_3 (SCP0) #define BAUD_DIV_4 (SCP1) #define BAUD_DIV_13 (SCP1|SCP0) /* Flags of the SPCR register. */ #define SPIE 0x80 /* Serial Peripheral Interrupt Enable */ #define SPE 0x40 /* Serial Peripheral System Enable */ #define DWOM 0x20 /* Port D Wire-OR mode option */ #define MSTR 0x10 /* Master Mode Select */ #define CPOL 0x08 /* Clock Polarity */ #define CPHA 0x04 /* Clock Phase */ #define SPR1 0x02 /* SPI Clock Rate Select */ #define SPR0 0x01 /* Flags of the SPSR register. */ #define SPIF 0x80 /* SPI Transfer Complete flag */ #define WCOL 0x40 /* Write Collision */ #define MODF 0x20 /* Mode Fault */ /* Flags of the ADCTL register. */ #define CCF 0x80 /* Conversions Complete Flag */ #define SCAN 0x20 /* Continuous Scan Control */ #define MULT 0x10 /* Multiple Channel/Single Channel Control */ #define CD 0x08 /* Channel Select D */ #define CC 0x04 /* C */ #define CB 0x02 /* B */ #define CA 0x01 /* A */ /* Flags of the CFORC register. */ #define FOC1 0x80 /* Force Output Compare 1 */ #define FOC2 0x40 /* 2 */ #define FOC3 0x20 /* 3 */ #define FOC4 0x10 /* 4 */ #define FOC5 0x08 /* 5 */ /* Flags of the OC1M register. */ #define OC1M7 0x80 /* Output Compare 7 */ #define OC1M6 0x40 /* 6 */ #define OC1M5 0x40 /* 5 */ #define OC1M4 0x40 /* 4 */ #define OC1M3 0x08 /* 3 */ /* Flags of the OC1D register. */ #define OC1D7 0x80 #define OC1D6 0x40 #define OC1D5 0x20 #define OC1D4 0x10 #define OC1D3 0x08 /* Flags of the TCTL1 register. */ #define OM2 0x80 /* Output Mode 2 */ #define OL2 0x40 /* Output Level 2 */ #define OM3 0x20 #define OL3 0x10 #define OM4 0x08 #define OL4 0x04 #define OM5 0x02 #define OL5 0x01 /* Flags of the TCTL2 register. */ #define EDG1B 0x20 /* Input Edge Capture Control 1 */ #define EDG1A 0x10 #define EDG2B 0x08 /* Input 2 */ #define EDG2A 0x04 #define EDG3B 0x02 /* Input 3 */ #define EDG3A 0x01 /* Flags of the TMSK1 register. */ #define OC1I 0x80 /* Output Compare 1 Interrupt */ #define OC2I 0x40 /* 2 */ #define OC3I 0x20 /* 3 */ #define OC4I 0x10 /* 4 */ #define OC5I 0x08 /* 5 */ #define IC1I 0x04 /* Input Capture 1 Interrupt */ #define IC2I 0x02 /* 2 */ #define IC3I 0x01 /* 3 */ /* Flags of the TFLG1 register. */ #define OC1F 0x80 /* Output Compare 1 Flag */ #define OC2F 0x40 /* 2 */ #define OC3F 0x20 /* 3 */ #define OC4F 0x10 /* 4 */ #define OC5F 0x08 /* 5 */ #define IC1F 0x04 /* Input Capture 1 Flag */ #define IC2F 0x02 /* 2 */ #define IC3F 0x01 /* 3 */ /* Flags of Timer Interrupt Mask Register 2 (TMSK2). */ #define TOI 0x80 /* Timer Overflow Interrupt Enable */ #define RTII 0x40 /* RTI Interrupt Enable */ #define PAOVI 0x20 /* Pulse Accumulator Overflow Interrupt En. */ #define PAII 0x10 /* Pulse Accumulator Interrupt Enable */ #define PR1 0x02 /* Timer prescaler */ #define PR0 0x01 /* Timer prescaler */ #define TPR_1 0x00 /* " " prescale div 1 */ #define TPR_4 0x01 /* " " prescale div 4 */ #define TPR_8 0x02 /* " " prescale div 8 */ #define TPR_16 0x03 /* " " prescale div 16 */ /* Flags of Timer Interrupt Flag Register 2 (TFLG2). */ #define TOF 0x80 /* Timer overflow bit */ #define RTIF 0x40 /* Read time interrupt flag */ #define PAOVF 0x20 /* Pulse accumulator overflow Interrupt flag */ #define PAIF 0x10 /* Pulse accumulator Input Edge " " " */ /* Flags of Pulse Accumulator Control Register (PACTL). */ #define DDRA7 0x80 /* Data direction for port A bit 7 */ #define PAEN 0x40 /* Pulse accumulator system enable */ #define PAMOD 0x20 /* Pulse accumulator mode */ #define PEDGE 0x10 /* Pulse accumulator edge control */ #define RTR1 0x02 /* RTI Interrupt rates select */ #define RTR0 0x01 /* " " " " */ /* Flags of the Options register. */ #define ADPU 0x80 /* A/D Powerup */ #define CSEL 0x40 /* A/D/EE Charge pump clock source select */ #define IRQE 0x20 /* IRQ Edge/Level sensitive */ #define DLY 0x10 /* Stop exit turn on delay */ #define CME 0x08 /* Clock Monitor enable */ #define CR1 0x02 /* COP timer rate select */ #define CR0 0x01 /* COP timer rate select */ /* Flags of the HPRIO register. */ #define RBOOT 0x80 /* Read Bootstrap ROM */ #define SMOD 0x40 /* Special Mode */ #define MDA 0x20 /* Mode Select A */ #define IRV 0x10 /* Internal Read Visibility */ #define PSEL3 0x08 /* Priority Select */ #define PSEL2 0x04 #define PSEL1 0x02 #define PSEL0 0x01 #define IO_SIZE (0x40) /* The I/O registers are represented by a volatile array. Address if fixed at link time. */ #endif /* _M68HC11_PORTS_DEF_H */
Here is the file ``sio.h.''
/* asm-m68hc11/sio.h -- Utility methods to read/write the SIO Copyright 1999, 2000, 2001 Free Software Foundation, Inc. Written by Stephane Carrez (stcarrez@worldnet.fr) This file is part of GDB, GAS, and the GNU binutils. GDB, GAS, and the GNU binutils are free software; you can redistribute them and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. GDB, GAS, and the GNU binutils are distributed in the hope that they will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*! Initialize the SCI. This function configures the SCI to send at \c M6811_DEF_BAUD baud rate. It must be called before any other serial operation unless the program is started from another one (such as a monitor or in bootstrap mode). @see serial_print, M6811_DEF_BAUD */ extern inline void serial_init (void) { // BAUD = M6811_DEF_BAUD; BAUD = 0x33; /* Setup character format 1 start, 8-bits, 1 stop. */ SCCR1 = 0; /* Enable reciever and transmitter. */ SCCR2 = 0x0C; } /*! Test for pending character on the reception. Return != 0 if there is something to read on the serial line. @return 1 if there is something to read on the serial line. */ extern inline unsigned char serial_receive_pending (void) { return SCSR & RDRF; } /*! Wait until the SIO has finished to send the character. This function waits for the transmission of the current character. While waiting, the COP is reset using \c cop_optional_reset. @see cop_optional_reset, serial_init, serial_send */ extern inline void serial_flush (void) { while (!(SCSR & TDRE)); // cop_optional_reset (); } /*! Send the character on the serial line. This function sends the character \a c on the serial line. Before sending, it calls \c serial_flush to make sure the transmitter is ready. Once the function returns, the character is in the SCI queue and it may not be sent completely over the serial line. @param c character to send on the serial line. @see serial_init, serial_flush */ extern inline void serial_send (char c) { serial_flush (); SCDR = c; SCCR2 |= TE; } /*! Wait for a character on the serial line and return it. This function waits for a character to be received by the SCI. While waiting, it calls \c cop_optional_reset to probe the COP regularly. @return the character received from the SCI. @see serial_init, cop_optional_reset */ extern inline unsigned char serial_recv (void) { while (!(SCSR & RDRF)); // cop_optional_reset (); return SCDR; }
Here is ``sio.c''
/* Serial line operations Copyright (C) 1999, 2000 Free Software Foundation, Inc. Written by Stephane Carrez (stcarrez@worldnet.fr) This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. In addition to the permissions in the GNU General Public License, the Free Software Foundation gives you unlimited permission to link the compiled version of this file with other programs, and to distribute those programs without any restriction coming from the use of this file. (The General Public License restrictions do apply in other respects; for example, they cover modification of the file, and distribution when not linked into another program.) This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ports.h" #include "./sio.h" void serial_print (const char *msg) { while (*msg != 0) serial_send (*msg++); } void serial_getline (char *buf) { char c; do { c = serial_recv (); *buf++ = c; } while (c != '\n' && c != '\r'); *buf = 0; }
Finally, here is the Makefile
# Timer Makefile # Copyright (C) 1999, 2000 Free Software Foundation, Inc. # Written by Stephane Carrez (stcarrez@worldnet.fr) # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # In addition to the permissions in the GNU General Public License, the # Free Software Foundation gives you unlimited permission to link the # compiled version of this file with other programs, and to distribute # those programs without any restriction coming from the use of this # file. (The General Public License restrictions do apply in other # respects; for example, they cover modification of the file, and # distribution when not linked into another program.) # # This file is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; see the file COPYING. If not, write to # the Free Software Foundation, 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # SRCDIR=. BASEDIR=$(SRCDIR)/.. CP=/bin/cp TTY=/dev/ttyS0 STTY=/bin/stty include $(BASEDIR)/config/make.defs CSRCS=main.c sio.c SSRCS=vectors.s OBJS=main.o vectors.o sio.o ASFLAGS = -I../include/ CCFLAGS += -I../include/ all:: main.elf main.s19 main.b main.s main.elf: $(OBJS) $(CC) -v $(LDFLAGS) -o $@ $(OBJS) $(LIBS) main.s: main.c $(CC) $(CCFLAGS) -S main.c $(AS) $(ASFLAGS) -ahlns=main.lst main.s install: sync $(STTY) raw -F $(TTY) $(STTY) 1200 -F $(TTY) $(CP) XLOAD.BIN $(TTY) $(CP) main.s19 $(TTY)