Movatterモバイル変換


[0]ホーム

URL:


EmbeddedRelated.com
The 2026 Embedded Online Conference
   Code Snippets    Simple serial and timer ISR state machine

Simple serial and timer ISR state machine

March 23, 2013 Coded inC for theAtmel AT89

This is a replacement firmware for a K164. The K164 Kit is a simple DTMF decoder board still available or can be built with available schematics. This example is a good reference for the AT89C2051 or 8051 on how to setup interrupts and create a simple real time state machine.

/*    k164_js.c        Purpose:    New firmware for the k164 dtmf decoder board and                the AT89C2051-24PC The source code was compiled with sdcc.    URLs:        http://www.digikey.com/product-detail/en/AT89C2051-24PU/AT89C2051-24PU-ND/1118880        http://www.electronics123.com/kits-and-modules/Telephone-Call-Logger-Kit-16k.html        http://www.kitsrus.com/pdf/k164.pdf    Compile:    sdcc k164_js.c ; packihx k164_js.ihx > k164_js.hex    Simulate:   s51 k164_js.hex    Copyright (C) 2009 Nu Tech Software Solutions, Inc.    Permission is hereby granted, free of charge, to any person obtaining a copy    of this software and associated documentation files (the "Software"), to deal    in the Software without restriction, including without limitation the rights    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell    copies of the Software, and to permit persons to whom the Software is    furnished to do so.    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN    THE SOFTWARE.    AUTHOR: Sean Mathews <coder at f34r.com> 1/27/2009*/#include <at89x051.h>#define STATUS_LED  P3_5#define HOOK_LED    P3_4#define LOOP_STATUS P3_3#define STD_STATUS  P3_7#define MODE_SWITCH P1_5/* UART parameters                                            */#define CpuClk        20275200              // 20.2752 MHz clock chip on the k164 board#define Baudrate      9600                  // UART - 9600,N,8,1 baud used by current firmware#define Timer1ReloadValue (256-(2*CpuClk/32/12/Baudrate))#define F34R_MODE   0char szVERSION[] = "V1.0";/*To determine the value that must be placed in TH1 to generate a given baud rate, we may use the following equation (assuming PCON.7 is clear).      TH1 = 256 - ((Crystal / 384) / Baud) If PCON.7 is set then the baud rate is effectively doubled, thus the equation becomes:      TH1 = 256 - ((Crystal / 192) / Baud)        make this next macro work and we wont hvae to hard code the values ...  */#define InterruptRate 10000    // how oftin to hit our interrupt per second#define Timer0H           0xBE //(char)((0xFF00 & (65536 - (InterruptRate / 12 * 1000))) >> 8)#define Timer0L           0x00 //(char)(0x00FF & (65536 - (InterruptRate / 12 * 1000)))/* prototypes                                                 */void hw_init();char getchar( void );void myputchar( char c );void doevents();void myputs(char *);void itoa(int value, char* string, int radix);void uitoa(unsigned int value, char* string, int radix);void send_version(void);void send_hello(void);void send_help(void);#define UNKNOWN  0x01#define OFFHOOK  0x02#define ONHOOK   0x03#define VERSION  0x04#define EGGS     0x05#define RESET    0x06#define SEND_HELP 0x07char hook_state;char input_state;int notdone=1;#define ON       0x02#define OFF      0x03char std_state;static char state_machine_active=0;/* plug all of the other interrupt vectors                    */#ifdef SDCCvoid mydummyISR (void) interrupt 12 _naked {}#endif/* Serial interrupt to track incoming key strokes             */void serial_isr(void) interrupt 4 {        if (RI != 0)        {          RI = 0;                    if(SBUF == '?')            hook_state = UNKNOWN;          if(SBUF == 'V' || SBUF == 'v')            input_state = VERSION;          if(SBUF == 'R' || SBUF == 'r')            input_state = RESET;          if(SBUF == '!')            input_state = EGGS;          if(SBUF == 'H' || SBUF == 'h')            input_state = SEND_HELP;                  }        return;}/*------------------------------------------------------------------------- integer to string conversion Written by:   Bela Torok, 1999 in the public domain               bela.torok@kssg.ch usage: uitoa(unsigned int value, char* string, int radix) itoa(int value, char* string, int radix) value  ->  Number to be converted string ->  Result radix  ->  Base of value (e.g.: 2 for binary, 10 for decimal, 16 for hex)---------------------------------------------------------------------------*/#define NUMBER_OF_DIGITS 16   /* space for NUMBER_OF_DIGITS + '\0' */void uitoa(unsigned int value, char* string, int radix){unsigned char index, i;  index = NUMBER_OF_DIGITS;  i = 0;  do {    string[--index] = '0' + (value % radix);    if ( string[index] > '9') string[index] += 'A' - ':';   /* continue with A, B,.. */    value /= radix;  } while (value != 0);  do {    string[i++] = string[index++];  } while ( index < NUMBER_OF_DIGITS );  string[i] = 0; /* string terminator */}void itoa(int value, char* string, int radix){  if (value < 0 && radix == 10) {    *string++ = '-';    uitoa(-value, string, radix);  }  else {    uitoa(value, string, radix);  }}/* setup UART                                                 */void hw_init() {        LOOP_STATUS = 1; //set our loop status pin to an input        STD_STATUS  = 1; //set our std status pin to an input        MODE_SWITCH = 1; //set the "ECHO" switch input on the K164 board to input         EA = 0; // disable all interrupts                          PCON |= 0x80;  // SMOD = 1 double speed clock for our baud rate interrupt        TH1 = TL1 = Timer1ReloadValue;   // timer 1 mode 1 reload value 9600 baud as calculated in our macro        TMOD &= 0x0f;    /* Set timer 1 */         TMOD |= 0x20;    /* Set timer 1 as Gate=0 Timer, mode 2 */         TR1 = 1;        // turn on serial timer Timer 1        SCON = 0x40;    // init port as 8-bit UART with variable baudrate         SCON |= 0x10;   // Enabling serial reception//      SCON |= 0x02;   // Setting TI bit         ES = 1;         // Enable Serial Interrupt */        /* Timer 0 setup */        TMOD &= 0xf0;    /* Set timer 0 */         TMOD |= 0x01;    /* Set timer 0 16 bit timer  */         /* configure generic timer 0 reset value */                TH0 = Timer0H;        TL0 = Timer0L;  // reload with 35711 for 1Hz            TR0 = 1;        // turn on timer 0        ET0 = 1;        // Enable timer 0 interrupt                 RI  = 0;        TI  = 1;        EA  = 1; // enable all interrupts}/* setup FIRMWARE                                              */void fw_init() {        /* initialize our state machine to ON HOOK */        hook_state = UNKNOWN;        input_state = UNKNOWN;        std_state = UNKNOWN;        /* Turn off our LED's we just started */        HOOK_LED = 0;        STATUS_LED = 0;}/* read a character from UART                                 */char getchar( void ) {         while(!RI);        RI = 0;        return(SBUF);}/* send a character to UART port                              */void myputchar( char c ) {         while(!TI);        TI =0;        SBUF = c;}void myputs(char *sz) {   while(*sz) myputchar(*sz++);} /* Timer 0 interrupt the state machines main interrupt */void timer_isr(void) interrupt 1 {        static int suppressfirst=1;        static int x=0;        static int counter=0;        char buffer[17];        /* configure generic timer 0 reset value */        TH0 = Timer0H;        TL0 = Timer0L;                /* every 1 second do our event routine */                if(x++>50) {                x=0;                doevents();        }        /* we need to control this or we will be trying to send out serial data from two threads */        if(state_machine_active) {                if( input_state == VERSION ) {                        send_version();                        input_state = UNKNOWN;                }                if( input_state == SEND_HELP ) {                        send_help();                        input_state = UNKNOWN;                }                if( input_state == EGGS ) {                        myputs("! Jack Edin 1961-2012 rip - Logic Unlimited !\r\n");                        myputs("! Sean Mathews - NuTech.com   !\r\n");                        input_state = UNKNOWN;                }                if( input_state == RESET ) {                        notdone=0;                        input_state = UNKNOWN;                }                /* check state of the hook line it seems to be inverted */                if(!LOOP_STATUS) {                        HOOK_LED = 1; /* ON  NPN Transistor base*/                          if( hook_state != OFFHOOK ) {                                counter++;                                if(counter>10) { // 100ms                                        hook_state = OFFHOOK;                                        if(!suppressfirst) {                                           myputs("OFFHOOK\r\n");                                        } else {                                           suppressfirst=0;                                        }                                }                          }                } else {                        HOOK_LED = 0; /* OFF NPN Transistor base*/                        counter=0;                        if( hook_state != ONHOOK ) {                                hook_state = ONHOOK;                                if(!suppressfirst) {                                   myputs("ONHOOK\r\n");                                                                   } else {                                   suppressfirst=0;                                }                        }                }                /* check state of the STD pin on the MT8870CE chip      */                if(STD_STATUS) {                        if( std_state != ON ) {                                std_state = ON;                                if(MODE_SWITCH==F34R_MODE) {                                        myputs("TONE ");                                }                                switch(P1 & 0x0f) {                                        case  10:                                                buffer[0]='0';                                                buffer[1]=0;                                                break;                                        case  11:                                                buffer[0]='*';                                                buffer[1]=0;                                                break;                                        case  12:                                                buffer[0]='#';                                                buffer[1]=0;                                                break;                                        default:                                                itoa(P1 & 0x0f,buffer,10);                                                break;                                }                                myputs(buffer);                                if(MODE_SWITCH==F34R_MODE) {                                        myputs("\r\n");                                }                        }                } else {                        if( std_state != OFF ) {                                std_state = OFF;                        }                }        }} /* Event routine for periodic processing                      */void doevents() {  static char flipflop=0;  /* one second event handler. Future use...*/   /* flash the status led every 1 second */ if(MODE_SWITCH!=F34R_MODE) {       STATUS_LED = !STATUS_LED;       } else {         flipflop = !flipflop;         if(flipflop)            STATUS_LED = !STATUS_LED;    }                 }/* MAIN                                                       */void main(void) {        notdone=1;        /* first setup our states and any other startup code so           when our hardware calls our routines they are ready */        fw_init();        /* ok now setup our hardware and start the interrupts */        hw_init();        /* tell the world we are up and running */        send_hello();        /* let the state machine go */        state_machine_active=1;        /* ... */        while (notdone) { }        // disable all interrupts        EA = 0;         // jump to 0        ((void (code *)(void)) 0) ();}void send_hello() {        myputs("\r\n! K164mh Telephone DTMF Decoder ");        myputs(szVERSION);        myputs(" written for my good friend Jack Edin 1961-2012 rip!\r\n");}void send_version() {        myputs(szVERSION);        myputs("\r\n");}void send_help() { myputs("\r\n! Every line that starts with a ! is considered informational\r\n!and is not part of any call logging.\r\n"); myputs("! The state messages are ONHOOK [%1], OFFHOOK, TONE %1\r\n"); myputs("! The tones can also be on the ONHOOK line if the device is in inbound calls mode\r\n"); myputs("! K164mh commands: \r\n!    ? = Information\r\n!    V = Version\r\n!    R = Reset\r\n!    H = This info\r\n");        }

The 2026 Embedded Online Conference

Sign in

Forgot username or password?  | Create account

Blogs - Hall of Fame

So You Want To Be An Embedded Systems Developer

So You Want To Be AnEmbedded Systems Developer
Steve Branam

Introduction to Microcontrollers

Introduction toMicrocontrollers
Mike Silva

Important Programming Concepts (Even on Embedded Systems)

ImportantProgramming Concepts (Even on Embedded Systems)
Jason Sachs

How FPGAs Work and Why You'll Buy One

HowFPGAs Work and Why You'll Buy One
Yossi Krenin

MSP430 Launchpad Tutorial

MSP430 Launchpad Tutorial
Enrico Garante

Arduino Robotics

Arduino Robotics
Lonnie Honeycutt

Free PDF Downloads

C++ On Embedded Systems
Interrupt handling in an ARM processor
First Steps with Embedded Systems

Quick Links

About EmbeddedRelated.com

The Related Sites


[8]ページ先頭

©2009-2026 Movatter.jp