Zurück (C) Christof Ermer, Regensburg
Gratis Counter 03.01.2012

!!  Veraltet !

Vollständiges C Projekt mit  Frequenzsynthese für Schrittmotor Betrieb
Communikation und Befehle über serielle Schnittstelle
Im Format z.B:    Mo,100<CR>  = Motor ON, 100Hz
Nur als Prinzip. also anpassen an Hardware usw....
16MHz Quarz
Software als ZIP für WINAVR   Stepmot.zip

main.c

//------------------------------------------------------------------------------
// Programmed by Christof Ermer
//------------------------------------------------------------------------------

//SYSINFO
#define DATUM        "22.09.2011"
#define FUNKTION    "AVR16_Com_LCD_L298_V1.0"
#define HARDWARE    "AVR16_Com_LCD_L298_V1-0"
#define UHRZEIT    "12:00"
#define AUTOR        "Christof Ermer"
#define BAUDRATE    "BAUD 9600 8N1"

#define IHAVENOBRAIN    "I have no brain."   
#define USEYOURS        "Use your own"

/*  HISTORY
In Interupts...alle Vars deklarieren mit
volatile uint32_t Tickscounter..
*/

#include <avr\io.h>
#include <ctype.h>
#include <inttypes.h>
#include <avr\pgmspace.h> // <--#include <progmem.h>

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <avr\interrupt.h>  // obsolete #include <avr\signal.h>

//ACHTUNG STELLT OBSOLETE Procedure in header wieder her
#include <util\delay.h>    //_delay_loop_1 _delay_loop_2 delay_ms
#include <avr\wdt.h>

#include "main.h"        //with Hardware assigns
#include "uart.h"
#include "stepmot.h"



uint16_t ADC_10Bit(uint8_t ucChan);
//int32_t Round(double fIn);


#ifdef TIMER_TICK_USED
void StartTickTimer(void);    //0.1 Seconds  interrupt
#endif


#ifdef UART_USE_ENABLED
void UART_TXRX_Check(void);
void ResetRxBuff(void);
void PrintCR(void);
void PrintStrCR(const char* pStr);
void Print_PStrCR(PGM_P pmStr);
void CheckOrder(char* pcStr);
void LongToNumStr(int32_t lVal);
void PrintLongCR(int32_t lVal);
void FloatToNumStr(double fVal);
#endif



//CONSTANT ARRAYs IN .TEXT = ROM ARREA   .DATA IST SRAM !! .BSS SRAM
//const char MCA_DELIMTERSTR[] PROGMEM = { ',',0 };

// GLOBALE VARIABLEN
//MSG
const char MCA_DELIMITER[] PROGMEM    = ",";
const char MCA_ISTGLEICH[] PROGMEM    = "=";
//const char MCA_VALUE[] PROGMEM    = "Value";

//gu8SineVal[iNN] = round( 127.5 * sin(2*M_PI* iNN/256.0) + 1 );
// f(x)= Amplitude * sin ( 2* M_PI * NN/X_AUFLOESUNG ) + OFFSET
/*
//f(x) = a * sin (2*Pi*x - b) + o
a ist die Amplitude
b ist die Phasenverschiebung
o ist der "Offset"-Wert
für x setzt du halt n/d ein. (n € N)
d ist die Schrittanzahl pro Periode
*/
/*
ODER
iNN)= 0..255
F(x) = 128 + 127* sin( iNN/2562*M_PI* )
*/

#ifdef UART_USE_ENABLED
static char* gpcRxPars;
static char gcaRxStr[RX_STRMAX + 1]; //+1 for the 0
static char gcaNumStr[NUMMAX + 1]; //+1 for the 0
static char gcaStr[STRMAX + 1]; //+1 for the 0
static COMMAND_TYPE gsCmd;
#endif

//static uint8_t gcaSegmentStr[SEGMENTSTRMAX + 1]; //+1 for the 0
uint32_t gu32_Ticks; //  T2 timeCounter, only NN_Counter for Keypressings
#ifdef USE_ERROR_FLAG
uint8_t gbErrorFlag;
#endif



#ifdef TIMER_TICK_USED
// ****************************************************************
//volatile  SIGNAL(TIMER2_OVF_vect) //oder SIGNAL--INTERRUPT(SIG_OVERFLOW2) = mit SEI am Anfang
SIGNAL( TIMER2_OVF_vect ) //oder SIGNAL--INTERRUPT(SIG_OVERFLOW2) = mit SEI am Anfang
// *******************************************************************
{
gu32_Ticks++;
UART_TXRX_Check();    //IMMER VORNAHANDEN !! IN ALLEN LOOPS DIE ZEIT BRAUCHEN
};
#endif

   

// *************************************
void StartTickTimer(void)    //0.1 Seconds  interrupt
//Normal MODE OC2 Disconnect Prescale 64
// *************************************
{
//TIMSK &=  ~((_BV(TOIE2) |  (_BV(OCIE2));
TIMSK &= ~( TIMSK_TOIE2_FLAG | TIMSK_OCIE2_FLAG );
gu32_Ticks = 0;
OCR2 = 0;
TCNT2 = 0;  //Timer MAX = TOP Compare
//TIMER STARTS with Presscale Select = 64
TCCR2 = TCCR2_CLK_256;    // 0000 0100//Timer Counter CTRL -- NORMAL MODE=NO OCR2
TIMSK |= TIMSK_TOIE2_FLAG;
};


#ifdef  USE_TOGGLE_FLAG
// ****************************************************************
void ToggleTEST_BIT(uint8_t ucCnt)
// ****************************************************************
{ // #include <util\delay.h>  muss da sein
uint8_t ucNN;
for(ucNN=0; ucNN < ucCnt; ucNN++)
    {
    SET_TESTBIT_MAC;
    _delay_us(1);
    CLR_TESTBIT_MAC;
    _delay_us(1);
    };
};
#endif



#ifdef UART_USE_ENABLED
// *******************************************************************
void ResetRxBuff(void)
// *******************************************************************
{
gpcRxPars = gcaRxStr; // Set parse pointer back;
*gpcRxPars = 0;    //clear Rx
};
#endif

#ifdef UART_USE_ENABLED
// *******************************************************************
void UART_TXRX_Check(void)
/*   
* Get received character from ringbuffer
* uart_getc() returns in the lower byte the received character and
* in the higher byte (bit_MSK) the last receive error
* UART_NO_DATA is returned when no data is available.
*/
// *******************************************************************
{
uint16_t uiRxUart;
uiRxUart = uart_getc();//!FETCH ALLWAYS BYTE FROM RX RINGBUFF INTERRUPT!
if( !(uiRxUart & UART_NO_DATA) )  //0x0100
    {
//   * new data available from UART
//  * check for Frame or Overrun error
#ifdef UART_ERRORMSG
    if( uiRxUart & (UART_FRAME_ERROR | UART_OVERRUN_ERROR | UART_BUFFER_OVERFLOW) )
        {
        ResetRxBuff();
        uart_init( UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU) );// !! Init UART interface
// Framing Error detected, i.e no stop bit detected
        Print_PStrCR(  PSTR("UartErr") );
        };
#endif
//NOW SELCT ACTION FROM ORDER
//Check CR
    if(gpcRxPars < (gcaRxStr + RX_STRMAX))    //ENDANSCHLAG ERREICHT ?
        {
        switch( (unsigned  char)uiRxUart  )
            {
            case 32: // SPACE weg
                {
                break;
                };                              
            case 10: // LF weg
                {
                break;
                };                              
            case 13: // order!! from Terminal
                {
                CheckOrder(gcaRxStr);//gcaRxStr = accumulated str
                ResetRxBuff();
                break;
                };                              
            default: //Accumulate
                {
      // Accumulate String only to gcaRxStr with uiAAA Parser
                *gpcRxPars++ = (unsigned  char)(uiRxUart & 0x0FF);//Append rxByte
                *gpcRxPars = 0; //ZERO carry
                };
            };//switch
        }// if (pcRxPars < (gcaRxStr + RXSTRMAX))
    else  // To much data Rx, than clear simple all
        {
     //overflow of RX clears all
        ResetRxBuff();    // Clear Rx Parspointer in Buff an terminate RxStr with 0
        };//if(gpcRxPars < (gcaRxStr + RXSTRMAX))
// ENDE DER RX EMPFANGSAUSWERTUNG
    };
};
#endif


#ifdef UART_USE_ENABLED   //MAKLEFILE ANPASSEN
// *******************************************************************
void PrintCR(void)
// *******************************************************************
{
uart_putc( ASC_CR );
};


// *******************************************************************
void PrintStrCR(const char* pStr)
// *******************************************************************
{
uart_puts(pStr);
PrintCR();
};


// *******************************************************************
void Print_PStrCR(PGM_P pmStr)
// *******************************************************************
{
uart_puts_p(pmStr);
PrintCR();
};

// **********************************************
void LongToNumStr(int32_t lVal)
// **********************************************
{
//sprintf(gcaNumStr,"%ld", lVal);  //Ulong = %ld
ltoa(lVal, gcaNumStr, 10 );
};

// *******************************************************************
void PrintLongCR(int32_t lVal)
// *******************************************************************
{
LongToNumStr(lVal); PrintStrCR(gcaNumStr);
};

// **********************************************
void FloatToNumStr(double fVal)
// *************
{
dtostrf(fVal, FLOAT_PRAEDIGITS_MAX, FLOAT_DIGITS_MAX, gcaNumStr ); //[-]d.ddd
};

// *******************************************************************
void PrintFloatCR(double fVal)
// *******************************************************************
{
FloatToNumStr(fVal); PrintStrCR(gcaNumStr);
};
#endif

/*
int32_t Round(double fIn)
// **********************************************
{
return (int32_t)floor(fIn + 0.5);
};
*/

#ifdef ADC_USED_ENABLED
//****************************************************************
uint16_t ADC_10Bit(uint8_t ucChan)
//****************************************************************
{
//unsigned int sreg;
//sreg = SREG;
//cli();
//Wegen möglichem zugriffffehler auf Port A
DDRA = DDRA & ~(1<<ucChan);   //port A Chanel Bit Input 
PORTA = PINA & ~(1<<ucChan); //Wegen Pullup
  // Activate ADC with Prescaler 16 --> 1Mhz/16 = 62.5kHz
ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) |_BV(ADPS0); 
 // Select pin ADC0 using MUX
ADMUX = (ucChan & ADC_MUX_MASK);
   
    //Start conversion
ADCSRA |= _BV(ADSC);

//SREG = sreg;
    // wait until converstion completed
while (ADCSRA & _BV(ADSC) )
    {
    wdt_reset();
    };      
return ADC;// get converted value
};
#endif


// *******************************************************************
void CheckOrder(char *pcStrOrder) //von gcaRxStr
// *******************************************************************
{ //INPUT ERWARTET INDER FOR "BEFEHL,WERT" BSP: "SFR,1000"
//uint16_t uiCnt =0;
char * pStrTok; // für strtok_r
char * pucCh = &pcStrOrder[ strlen(pcStrOrder) ]; // Stelle POINTER auf \0 Ende  // kein unsigned char*

strcpy(gcaStr, pcStrOrder);
strcpy_P(gcaNumStr, MCA_DELIMITER); //HILFSWEISE gcaNumStr für ","

if( (pStrTok = strtok_r( pcStrOrder, gcaNumStr  , &pucCh)) != NULL)//Trenne CMD, von ID, -"$$$1,CMD
    {   
    strcpy(gsCmd.ucaCmd, pStrTok);
    }
else
    {
    *gsCmd.ucaCmd = 0;
    };
gsCmd.ucaCmd[ COMAMNDSIZEMAX ] = 0; //Sicherheitsterminierung COMAMNDSIZEMAX=10


//strcpy(gcaStr, pcStrOrder);

gsCmd.fCmdVal_1 = gsCmd.fCmdVal_2 = 0;
if( (pStrTok = strtok_r( NULL,  gcaNumStr, &pucCh)) != NULL)
    {
    gsCmd.fCmdVal_1 = atof(pStrTok);// Und dann TO Float   
    };
   
if( (pStrTok = strtok_r( NULL,  gcaNumStr, &pucCh)) != NULL)
    {
    gsCmd.fCmdVal_2 = atof(pStrTok);// Und dann TO Float   
    };

//========================================================================================

if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("PING") )  )    //ping
    {   
    Print_PStrCR( PSTR("PONG") );   
    };

#ifdef ADC_USED_ENABLED
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("ADC"))  )    //ADC,0..7
    {   
    uart_puts_p(  PSTR("ADC") );
    uart_puts_p( MCA_ISTGLEICH );   
    PrintLongCR( ADC_10Bit( gsCmd.fCmdVal_1 ) );
    };
#endif



#ifdef STEPMOTOR_USED
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("MO"))  )
    {
    gu8StepMConditionFlag &= ~STEPM_PULSE_MODE_FLAG; //Kein Pulscount
    if((uint8_t)gsCmd.fCmdVal_1)    //OPTIONAL; GLEICH MIT pULScountangabe
        {
        gsStMPar.fSM_Soll_FRQ = gsCmd.fCmdVal_1;       
        };   
    StepMotorOn();
    };
#endif

#ifdef STEPMOTOR_USED
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("MOPD"))  ) //MOTOr ON Pulse, Direction
    {
    SM_Run_Puls_DIR( (uint32_t)gsCmd.fCmdVal_1, (uint8_t)gsCmd.fCmdVal_2 );    //Default ist 200...
    };
#endif

#ifdef STEPMOTOR_USED
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("MF"))  )
    {
    StepMotorOff();
    };
#endif

#ifdef STEPMOTOR_USED
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("MS"))  )
    {
    StepMotorStop();
    };
#endif

#ifdef STEPMOTOR_USED
if( !strcasecmp_P( gsCmd.ucaCmd,PSTR("SFR")) )    //TESTS
   {
    gsStMPar.fSM_Soll_FRQ = gsCmd.fCmdVal_1;
    Set_SM_FRQ(gsStMPar.fSM_Soll_FRQ);
    };
#endif

#ifdef STEPMOTOR_USED
if( !strcasecmp_P( gsCmd.ucaCmd,PSTR("DIR") ) )    //TESTS
   {
    if((uint8_t)gsCmd.fCmdVal_1)
        {
        SetMotorDirection( SM_DIR_LINKS );
        }
    else
        {
        SetMotorDirection( SM_DIR_RECHTS );
        };
    };
#endif

#ifdef STEPMOTOR_USED
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("RAMPE")) )
   {
    if( (uint8_t)gsCmd.fCmdVal_1 )
        {
        gsStMPar.u8SM_RampenSteigung = ((uint8_t)gsCmd.fCmdVal_1);
        gu8StepMConditionFlag |= STEPM_RAMPE_FLAG;        //Setze bits
        }
    else
        {
        gu8StepMConditionFlag &= ~STEPM_RAMPE_FLAG;        //Setze bits
        };
    };
#endif

#ifdef STEPMOTOR_USED
if( !strcasecmp_P( gsCmd.ucaCmd,PSTR("HALF") ) )
    {   
    Set_StepMotor_Mode( MODE_HALFSTEP );
    };
#endif
   
#ifdef STEPMOTOR_USED
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("FULL")) )
    {
    Set_StepMotor_Mode(  MODE_FULLSTEP );   
    };
#endif

#ifdef STEPMOTOR_USED
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("SPR"))  ) //Set Steps per Rotation
    {    //Default ist 200...
    gsStMPar.u16SM_StepsRotationType = (uint16_t)gsCmd.fCmdVal_1; //Normal 200
    };
#endif

if( !strcasecmp_P( gsCmd.ucaCmd,  PSTR("TT") ) )
    {
    PrintLongCR( gu32_Ticks );
    };
   
 };


// *******************************************************************
int main(void)
// *******************************************************************
{
//uint8_t u8NN;
//INITS
cli();//The global interrupt flag is maintained in the I bit of the status register (SREG). 
//Wichtige Schritte.. so bald wie möglich

//INIT HARDWARE
//USing of PORTOUTS  1=OUT, 0=IN
DDRA = PORTA_DDRX_OUT_MSK;
PORTA = PORTA_PRESET_PULL_MSK;
DDRB = PORTB_DDRX_OUT_MSK;
PORTB = PORTB_PRESET_PULL_MSK;
DDRC = PORTC_DDRX_OUT_MSK;
PORTC = PORTC_PRESET_PULL_MSK;
DDRD = PORTD_DDRX_OUT_MSK;
PORTD = PORTD_PRESET_PULL_MSK;

SM_INIT_DIRREG();
SM_InitStructVals();

//SFIOR = (1<<PUD); //Pullup Disable
StartTickTimer();    //8 Bit Timer 2 = MS Tick Counter
//Pointer and Strings init
wdt_enable(WDTO_2S); //Set 1.9Sec WatchDog ENABLE
wdt_reset();   //WATCHDOG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

// Initialize UART library, pass baudrate and avr cpu clock
// with the macro UART_BAUD_SELECT()
ResetRxBuff();
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU) );

Print_PStrCR( PSTR(HARDWARE) );
Print_PStrCR( PSTR(AUTOR) );
Print_PStrCR( PSTR(FUNKTION) );
Print_PStrCR( PSTR(DATUM) );
Print_PStrCR( PSTR(BAUDRATE) );
Print_PStrCR( PSTR(IHAVENOBRAIN) );
Print_PStrCR( PSTR(USEYOURS) );

gu32_Ticks = 0;
// ************ MAIN LOOP *********************
for (;;)  /* loop forever */ //Aber schnell > 200.000 mal/Sekunde
// ************ MAIN LOOP *********************
    {   
    sei();
     wdt_reset();    //WATCHDOG!
//SekundenTick
    if( !(gu32_Ticks % 244 ) ) //Hier kann was gemacht werden jede 1/10 Sekunde
        {
        PrintLongCR( gu32_Ticks);       
        };


    }; //main loop Ende
#ifdef UART_USE_ENABLED
UART_TXRX_Check();    //IMMER VORNAHANDEN !! IN ALLEN LOOPS DIE ZEIT BRAUCHEN
#endif
};
// ******************* MAIN END ********************************************



main.h


#ifndef MAIN_HEADER  //Prevents multiple includes
#define MAIN_HEADER
#include "stepmot.h"


#define UART_BAUD_RATE    9600    /* 9600 baud */
//#define UART_BAUD_RATE    19200
//#define UART_BAUD_RATE    57600

//#define USE_ENDPOSITION_SWITCH_INT0

#define TIMER_TICK_USED
#define UART_USE_ENABLED
#define ADC_USED_ENABLED

//#define EEPROM_USED
#define TEXT_SERVICE_USE_ENABLED

#define USE_ERROR_FLAG

#define FLOAT_PRAEDIGITS_MAX    6 // DIgits nach //dtostrf(fVal,NUMMAX, DIGITS_MAX, gcaNumStr);
#define FLOAT_DIGITS_MAX        3 // DIgits nach //dtostrf(fVal,NUMMAX, DIGITS_MAX, gcaNumStr);

/*
Jedes Port hat drei Register
DDxN
PORTXn
PINxn
IF PortX ist INPUT an PORTX= set to 1, PullUP IS ENABLED
*/


/*
Text verbraucht Speicher
Statt Pointer geht evtl auch diese Form
TESTEN !!!
const uint8_t MCA_CRLFSTR[] __attribute__ ((section (".text"))) = {13,10,0};
//Versus diesr Form, die Speicher verbraucht !! ROCKEN ALS EINFÜGESTRING DEFINIERT.
#define MCA_CRLFSTR (const char){CR,LF,0}  //redefined

*/


//For compatibility for OLDER Compilers
//#define    sbi(sfr, bit)   (_SFR_BYTE(sfr) |= _BV(bit))
//#define    cbi(sfr, bit)   (_SFR_BYTE(sfr) &= ~_BV(bit))

#define BIT_0    0x01
#define BIT_1    0x02
#define BIT_2    0x04
#define BIT_3    0x08
#define BIT_4    0x10
#define BIT_5    0x20
#define BIT_6    0x40
#define BIT_7    0x80


#define STRMAX 64
#define NUMMAX 32
#define RX_STRMAX 32
#define COMAMNDSIZEMAX  32

#define DELIMITER        ','
#define DELIMITERSTR    ","

#define LOW_NIPPEL__MSK        0x0F
#define HIGH_NIPPEL__MSK    0xF0

//TYPEN DEKLARATION
typedef struct
    {
    char ucaCmd[COMAMNDSIZEMAX +1];
    uint8_t ucCmdID;
    float fCmdVal_1;
    float fCmdVal_2;
//char * pcAuxStrucCmdID;
    }COMMAND_TYPE;

// Hardwareassignment
//F_CPU  in makefile !!!
#define PULS_PER_10TEL_SEc        25
#define PULS_PER_SEcONDTick    244
#define PULS_500MS_Tick            122
#define PULS_250MS_TICK            61
#define PULS_100MS_TICK            25
#define PULS_50MS_TICK            13
   

//DELAY
#define TIMEOUT_1_5MS     1
#define TIMEOUT_2_9MS     2
#define TIMEOUT_4_4MS     3
#define TIMEOUT_10_3MS     7
#define TIMEOUT_100_7MS    68
#define TIMEOUT_500_7MS    338
#define TIMEOUT_1S         675        //!!  uint16_t
#define TIMEOUT_5S         3375    //!!  uint16_t

//REGISTER
#define TCCR0_FAST_PWM    0x48    //Mode 3
#define TCCR0_OC0_MODE    0x20    //Clear ON compare Match
#define TCCR0_OC0_DISCONNECT_MODE    0x00
#define TCCR0_CLK_STOP    0x00   
#define TCCR0_CLK_0        0x01   
#define TCCR0_CLK_8        0x02   
#define TCCR0_CLK_64    0x03   
#define TCCR0_CLK_256    0x04   
#define TCCR0_CLK_1024    0x05   
#define TCCR0_EXT_CLK_FALL_T0    0x06   
#define TCCR0_EXT_CLK_RISE_T0    0x07

//TCCR1A
#define TCCR1A_CTC_MODE            0x00    //WGM11 WGM10  = 0
#define TCCR1A_FAST_PWM_ICR1    0x02 //WGM11
#define TCCR1A_FAST_PWM_OCR1A    0x03 //WGM11 WGM10
//TCCR1B
#define TCCR1B_CLOCKSEL_STOP        0x00    //Clock Select Bits
#define TCCR1B_CTC_MODE                0x08    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_1        0x01    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_8        0x02    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_64    0x03    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_256    0x04    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_1024    0x05    //Clock Select Bits
#define TCCR1B_CLK_STOP__MSK        0xF8//TCCR1A

//TCCR2
#define TCCR2_WGM_NORMAL        0x00
#define TCCR2_CTC_MODE            0x08 //0000 1000
#define TCCR2_COM_NORMALPORT    0x00
#define TCCR2_CLK_STOP            0x00
#define TCCR2_FASTPWM            0x48    //Mode 3
#define TCCR2_CS_BIST            0x0x    //Mode 3
#define TCCR2_CLK_1024    0x07   
#define TCCR2_CLK_256    0x06   
#define TCCR2_CLK_128    0x05
#define TCCR2_CLK_64    0x04    //
#define TCCR2_CLK_32    0x03
#define TCCR2_CLK_8        0x02    //    1/F =
#define TCCR2_CLK_0        0x01   
#define TCCR2_CLK_STOP    0x00   
//TIMER2 WIRD BERECHNET /z.B:OverFLow SYSCLK /  256 / TCCR2_CLK_64 =  OVL/Sec


//TIMER
#define TIMSK_TOIE0_FLAG    0x01
#define TIMSK_OCIE0_FLAG    0x02
#define TIMSK_TOIE1_FLAG    0x04
#define TIMSK_OCIE1B_FLAG    0x08
#define TIMSK_OCIE1A_FLAG    0x10
#define TIMSK_TICIE1_FLAG    0x20
#define TIMSK_TOIE2_FLAG    0x40
#define TIMSK_OCIE2_FLAG    0x80

#define TIMSK_T0_CLR_ALL_MASK 0b11111100
#define TIMSK_T1_CLR_ALL_MASK 0b11000011
#define TIMSK_T2_CLR_ALL_MASK 0b00111111

//INTERUPT CTRL REG //NICHT mit MCUCSR verwechseln !
#define MCUCR_LOWLEVEL_INT0        0x00   
#define MCUCR_ANYCHANGE_INT0    0x01 //=_BV(ISC01)    
#define MCUCR_FALLING_EDGE_INT0    0x02   
#define MCUCR_RISING_EDGE_INT0    0x03

#define MCUCR_LOWLEVEL_INT1        0x00   
#define MCUCR_ANYCHANGE_INT1    0x04 //=_BV(ISC10)    
#define MCUCR_FALLING_EDGE_INT1    0x08   
#define MCUCR_RISING_EDGE_INT1    0x0C

#define GATE_ANYCHANGE_INT1_MODE()    (MCUCR |= MCUCR_ANYCHANGE_INT1)


//Global Interrrupt CTRL REG
#define GICR_INT0_ON()    (GICR |= _BV(INT0)) //_BV(INT0)
#define GICR_INT0_OFF()    (GICR &= ~(_BV(INT0)))
#define GICR_INT1_ON()    (GICR |= _BV(INT1))
#define GICR_INT1_OFF()    (GICR &= ~(_BV(INT1)))
#define GICR_INT_0u1_OFF()    (GICR &= 0x3F)  //SIEHE DATENBLATT


#define RCO_B_INT_ON()    GICR_INT0_ON()
#define RCO_B_INT_OFF()    GICR_INT0_OFF()
#define GATE_INT1_ON()    GICR_INT1_ON()
#define GATE_INT1_OFF()    GICR_INT1_OFF()


#define OVERFLOW_CNT_ON_INT0()    RCO_B_INT_ON()
#define OVERFLOW_CNT_OFF_INT0()    RCO_B_INT_OFF()

#define GATE_ALL_EVENT_ON_INT1()    GATE_INT1_ON()
#define GATE_ALL_EVENT_OFF_INT1()    GATE_INT1_OFF()

//GIFR  I_FLAG
#define GIFR_INTF0_SET()    (GIFR |= _BV(INTF0)) //_BV(INT0)
#define GIFR_INTF0_CLR()    (GIFR &= ~(_BV(INTF0)))
#define GIFR_INTF1_CLR()    (GIFR |= _BV(INTF1))
#define GIFR_INTF1_SET()    (GIFR &= ~(_BV(INTF1)))
#define GIFR_INTF_0u1_CLR()    (GIFR &= 0x3F) //Siehe Datenblatt = letzten beiden Bits



//PORTB
#define MOSI_I         3//BIT3
#define MISO_0         4//BIT4
#define SCK_I          5//BIT5

//EEPROM
#define EEPROM_SECTION  __attribute__ ((section (".eeprom")))
#define IEEPROM_SIZE    512    //Interne EEPROM
#define EE_DUMMYLOAD 0x5AA5 //unwahrsch. wert 0101 1010 1010 0101
//If using 8 block by 512 max = 64 Byte/block
//#define IEEPROM_SECTIONSIZE    64   //by 8 Section




//INTERRUPT
#define INTx_INPORT    PIND
//#define INT1__MSK    0x08  //PD3
//#define INT0__MSK    0x04  //PD2
#define INT0_PIN_NR    PD2
#define INT1_PIN_NR    PD3

//PORTB
#define TWI_DIRREG        DDRC
#define TWI_OUT_PORT    PORTC
#define TWI_IN_PORT        PINC
#define TWI_SDA            PC4        //PC4    OUT
#define TWI_SCL            PC5        //PC5    IN


//WERT IN ADCW
#define I2C_CLOCK_BIT    PC0
#define I2C_DATA_BIT    PC1

/*
#define Clr_TWI_SDA()         TWI_OUT_PORT &= ~PC_SDA_BIT;     
#define Set_TWI_SDA()         TWI_OUT_PORT |= PC_SDA_BIT;     
#define TWI_SCL_IS_HIGH        (TWI_IN_PORT & PC_SCL_BIT )
#define TWI_SCL_IS_LOW        (!(TWI_IN_PORT & PC_SCL_BIT))
*/

//PORTD TX/RX ERST MAL FÜR  FLAGS
#define PD0_RX_BIT    0x01    //PIN2
#define PD1_TX_BIT    0x02    //PIN3


//========================================================================

//TIMERS
//TIMER2  = is 61 miliseconds Timer ~approx.
// 16MhZ / 1024 / 256  = 61,03515625 Hz
// T= 1/f = 0.016384 ms / Interrupt
//PORT_ASSIGMNEMTS
#define WDTO_2S   7 //WatchDog
//SOFTWARE USED DEFINES

#define ASC_CR    13
#define ASC_DELIMITER    ','

//TIMER
#define TI_MSK_TOIE0_FLAG    0x01
#define TI_MSK_OCIE0_FLAG    0x02
#define TI_MSK_TOIE1_FLAG    0x04
#define TI_MSK_OCIE1B_FLAG    0x08
#define TI_MSK_OCIE1A_FLAG    0x10
#define TI_MSK_TICIE1_FLAG    0x20
#define TI_MSK_TOIE2_FLAG    0x40    //#define TOIE2 6     (1 << TOIE2)
#define TI_MSK_OCIE2_FLAG    0x80

#define TI_MSK_T0_CLR_ALL__MSK 0b11111100
#define TI_MSK_T1_CLR_ALL__MSK 0b11000011
#define TI_MSK_T2_CLR_ALL__MSK 0b00111111


#define TIFR_TOV0_TIMER_OVERFLOW_FLAG    0x01
#define TIFR_OCF0_OUT_PCOMPARE_FLAG        0x02
#define TIFR_TOV1_TIMER_OVERFLOW_FLAG    0x04
#define TIFR_OCF1A_OUTP_COMPARE_A_FLAG    0x10
#define TIFR_OCF1B_OUTP_COMPARE_B_FLAG    0x08
#define TIFR_TOV2_TIMER_OVERFLOW_FLAG    0x40
#define TIFR_OCF2_OUTP_COMPARE_FLAG        0x80

//INTERRUPT MODE
//#define MCUCR_INT0_LOWLEVEL_CLR_MSK    0xFC
#define MCUCR_INT0_LOWLEVEL        0x00
#define MCUCR_INT0_ANY_CHANGE    0x01
#define MCUCR_INT0_FALLING_EDGE    0x02
#define MCUCR_INT0_RISING_EDGE    0x03
#define MCUCR_INT0_CLEAR__MSK    0xFC

//#define MCUCR_INT1_LOWLEVEL_CLR_MSK    0xF3
#define MCUCR_INT1_LOWLEVEL        0x00
#define MCUCR_INT1_ANY_CHANGE    0x04
#define MCUCR_INT1_FALLING_EDGE    0x08    //_BV(ISC11)
#define MCUCR_INT1_RISING_EDGE    0x0C
#define MCUCR_INT1_CLEAR__MSK    0xF3
 

#define GICR_INT1_FLAG    0x80
#define GICR_INT0_FLAG    0x40
#define GICR_INT2_FLAG    0x20

#define GIFR_INTF1_FLAG    0x80
#define GIFR_INTF0_FLAG    0x40
#define GIFR_INTF2_FLAG    0x20

//TIMERS
#define TCCR0_FAST_PWM    0x48    //Mode 3
#define TCCR0_OC0_MODE    0x20    //Clear ON compare Match
#define TCCR0_OC0_DISCONNECT_MODE    0x00
#define TCCR0_CLK_1024    0x05    //~61,035 PWM
#define TCCR0_CLK_256    0x04    //244,14Hz PWM
#define TCCR0_CLK_64    0x03    //976,56Hz PWM
#define TCCR0_CLK_8        0x02    //7812 Hz PWM
#define TCCR0_CLK_0        0x01    //62500 PWM
#define TCCR0_CLK_STOP__MSK    0xF8   

#define TCCR2_WGM_NORMAL    0x00
#define TCCR2_CTC_MODE        0x08 //0000 1000
#define TCCR2_COM_NORMALPORT    0x00
#define TCCR2_FASTPWM        0x48    //Mode 3
#define TCCR2_CS_BIST        0x0x    //Mode 3
#define TCCR2_CLK_0            0x01
#define TCCR2_CLK_8            0x02
#define TCCR2_CLK_32        0x03
#define TCCR2_CLK_64        0x04
#define TCCR2_CLK_128        0x05
#define TCCR2_CLK_256        0x06
#define TCCR2_CLK_1024        0x07
#define TCCR2_CLK_STOP__MSK    0xF8



#define TC1_USED_CLOCKS_PER_SEC        15625    //16^6 / 1024


//ADC //AT8
#define ADMUX_MUX0    0
#define ADMUX_MUX1    1
#define ADMUX_MUX2    2
#define ADMUX_MUX3    3
#define ADMUX_MUX4    4
#define ADMUX_MUX5    5
#define ADMUX_MUX_1_23V    0xE0
#define ADMUX_MUX_GND    0xF0
#define ADMUX_ADLAR    0x20
#define ADMUX_REFS0    0x40
#define ADMUX_REFS1    0x80
#define ADC_MUX__MSK    0x0F

//PRESCALER
#define ADCSRA_ADPS0    0x01
#define ADCSRA_ADPS1    0x02
#define ADCSRA_ADPS2    0x04
#define ADCSRA_ADIE        0x08
#define ADCSRA_ADIF        0x10        //INTERRRUPT FLAG
#define ADCSRA_ADFR        0x20    //FREE RUNNNG SEL
#define ADCSRA_ADSC        0x40    //START  //while (ADCSRA & _BV(ADSC) )
#define ADCSRA_ADEN        0x80    //Enable

#define  ADCSRA_PRESCALER_2        0x01
#define  ADCSRA_PRESCALER_4        0x02
#define  ADCSRA_PRESCALER_8        0x03
#define  ADCSRA_PRESCALER_16    0x04
#define  ADCSRA_PRESCALER_32    0x05
#define  ADCSRA_PRESCALER_64    0x06
#define  ADCSRA_PRESCALER_128    0x07

// **************** HARDWARE *********************************
//AT16 BOARD V3.3  Halbe Eurokarte 100x80
// **************** HARDWARE *********************************


//CHECK PUD = PULLUPDISSABLE in SFIOR
#define DISABLE_ALL_PULLUP()    (SFIOR |= _BV(PUD));
#define ENABLE_ALLUP_SCL()    (SFIOR &= ~(_BV(PUD)));
// 1.main.c einstellungen
//PORTA
//1=OUT
#define PORTA_DDRX_OUT_MSK        SM_ALLCTRL_MSK
#define PORTA_PRESET_PULL_MSK    0x00

//PORT B
#define PORTB_DDRX_OUT_MSK        0X00           
#define PORTB_PRESET_PULL_MSK    0X00

//PORT C
#define PORTC_DDRX_OUT_MSK        0x00
#define PORTC_PRESET_PULL_MSK    0X00

//PORT D
//da ist TX/RX & zusatzhardware
#define PORTD_DDRX_OUT_MSK        0x02
#define PORTD_PRESET_PULL_MSK    0x00

//HARDWARE --------------------------------------------------------------
//ADC intern 10Bit    
#define ADC_MUX_MASK            0x07    //Für internen ADC
#define ADC10BIT_NTC_CHAN    7
#define ADC10BIT_INDEX_CHAN    6

#endif  //MAIN_HEADER



stepmot.c

#include <avr\io.h>
#include <ctype.h>
#include <inttypes.h>
#include <avr\pgmspace.h> // <--#include <progmem.h>
#include <string.h>
#include <avr\interrupt.h>  // obsolete #include <avr\signal.h>
#include <util\delay.h>    //_delay_loop_1 _delay_loop_2 delay_ms
#include <avr\wdt.h>
#include <math.h>


#include "stepmot.h"


//FULLSTEP ENABLE_B ENABLE_A BITS 3..0
//0011 1010 = 0x3A
//0011 1001 = 0x39
//0011 0101 = 0x35
//0011 0110 = 0x36
//const uint8_t MCA_FULLSTEPS[] PROGMEM = {0xBA,0xB9,0xB5,0xB6};    //CONST ARRAY
const char MCA_FULLSTEPS[] PROGMEM = {0x3A,0x39,0x35,0x36};    //CONST ARRAY
//HALFSTEP ENABLE_B ENABLE_A BITS 3..0
//0011 1010 = 0x3A
//0010 1000 = 0x28
//0011 1001 = 0x39
//0001 0001 = 0x11
//0011 0101 = 0x35
//0010 0100 = 0x24
//0011 0110 = 0x36
//0001 0010 = 0x12
const char MCA_HALFSTEPS[] PROGMEM = {0x3A,0x28,0x39,0x11,0x35,0x24,0x36,0x12};    //CONST ARRAY

//Sonstige Globals

STEPMPARTYPE gsStMPar;    //SPEICHERT DIE PARAMETER //definition in Main.H
uint8_t gu8StepPars; //+1 or -1 for the Bitpatternselect

uint8_t gucModePatternModulo; // Modulo selector (HALF/FULLSTEP..)
static PGM_P gpmpaStepPattern;
static uint8_t gu8Timer_CSxxClkSelect;
static float gfSMRealFrq;
uint8_t gu8StepMConditionFlag;    //ISTZUSTAND wir Mode
uint8_t gu8SM_PostionFlag;


//************************    ****************************************
ISR(TIMER0_OVF_vect) //TIMER0_OVF_vect
//*******************************************************************
{
sei();
SM_PORT_OUT |= SM_ENABLE_MSK;     // ehalte alle anderen Bits
//|         (pgm_read_byte_near( (PGM_P)(gpmpaStepPattern + (gu8StepPars % gucModePatternModulo) ) ) );              
};


//************************    ****************************************
ISR(TIMER0_COMP_vect)
//*******************************************************************
{
sei();
SM_PORT_OUT &= ~SM_ENABLE_MSK;    // ehalte alle anderen Bits   
};


// ***** ***********************************************************
ISR( TIMER1_COMPA_vect )// signal handler    /#define SIG_OUTPUT_COMPARE1A    _VECTOR(6)
// *******************************************************************
{
//static uint8_t ucBitpattern;
//I_SREG automtaic clear by Interrupt and Enabled by RETI   
sei();    //INTERRUPT ENABLE
if( gu8StepMConditionFlag & STEPM_RUN_FLAG )
    {
#if SM_LINE_FUCNTIONS_ENABLED == 1
    //Long DISTAcNE with multiple roations --> ein Target in einer Bewegungsachse +/- um den Indexpunkt
    if( (gu8SM_PostionFlag & POSITION_STOP_ON_DISTANCE_MODE_FLAG) &&
        (gliLIneTargePoint == gsStMPar.iSM_IndexDifference  )
    )
        {
        StepMotorStop();
        //gu8SM_PostionFlag &= ~POSITION_STOP_ON_DISTANCE_MODE_FLAG;
        return;       
        };
#endif

#if SM_SECTOR_FUNCTIONS_ENABLED == 1   
    //Target ->meint Target in einer Rotation
    if( (gu8SM_PostionFlag & POSITION_STOP_ON_TARGET_MODE_FLAG) &&
        ( guiMTargetPoint == gsStMPar.iSM_RotPosition )
    )
        {
        StepMotorStop();
        //gu8SM_PostionFlag &= ~POSITION_STOP_ON_TARGET_MODE_FLAG;
        return;       
        };
#endif   
    //check MOP Count...
    if(    (gu8StepMConditionFlag & STEPM_PULSE_MODE_FLAG) &&
            (gsStMPar.u32MovedSteps >= gsStMPar.u32SM_ToRunCnt )
    )
        {       
        StepMotorStop();    //EVTL. MIT AUTORELEASE_TIMEOUT
        //gu8StepMConditionFlag &= ~STEPM_PULSE_MODE_FLAG;
        return;
        //StepMotorOff();//GEHT NICHT; WEIL ER SONST ZU SCHNELL AUSSCHALTET
        };   

    //Zuerst  Bitmuster wählen, damit Motor immer auf gu8StepPars steht.
    if( gu8StepMConditionFlag & STEPM_DIRECTION_FLAG )       
        {//Linksrum Relativ zu Markerpfeil am Rand....
        gu8StepPars--;
        }
    else
        {//Rechts
        gu8StepPars++;
        };   
    //gu8StepPars = ZahlenRing(gu8StepPars, gucModePatternModulo);
    //gu8StepPars %= ZahlenRing(gu8StepPars, gucModePatternModulo);
//PrintFloatCRLF(gu8StepPars);   
    //Bitmuster am Schrittmotor ausgeben
    SM_PORT_OUT = ((SM_PORT_OUT) & (~SM_ALLCTRL_MSK))    | //ODER . ehalte alle anderen Bits   
        (pgm_read_byte_near( (PGM_P)(gpmpaStepPattern + (gu8StepPars % gucModePatternModulo) ) ) );              
    gsStMPar.u32MovedSteps++; //Zähle die Pulse.. !!               

//RAMPE Nachstellen
    if( (gu8StepMConditionFlag & STEPM_RAMPE_FLAG ) && //RAMPEnFAHREN Situation
        (gu8StepMConditionFlag & STEPM_START_RAMPE_FLAG)
    )//Frequenz nur setzen, wenn Rampe aktiv
        {
        gsStMPar.fSM_Ist_Frq += (float)gsStMPar.u8SM_RampenSteigung; // Rampe hochfahren       
        if( gsStMPar.fSM_Ist_Frq > gsStMPar.fSM_Soll_FRQ )
            {           
            gsStMPar.fSM_Ist_Frq = gsStMPar.fSM_Soll_FRQ;
            gu8StepMConditionFlag &= ~STEPM_START_RAMPE_FLAG;    //RAMPE EREICHT                   
            };
        Set_SM_FRQ( gsStMPar.fSM_Ist_Frq );
        };   
    //---------------------
    }
else    //gu8StepMConditionFlag & STEPM_ENABLE_FLAG
    {
    StepMotorStop();
    };   
};



//Haltestrom mit PWM
// *************************************
void Timer0_PWM( uint8_t u8PwmRange) // 0..255 PWM 0  bis maximal
// *************************************
{  // 8BIT TIMER T0
unsigned char sreg;
sei();
sreg = SREG; //loakaler Speicher
TIMSK &= ~( _BV(TOIE0) | _BV(OCIE0)  );
TCNT0=  0;    //Timer MAX = TOP Compare
OCR0 = u8PwmRange;
TCCR0 =  TCCR0_CLK_0;
TIMSK |= (_BV(TOIE0) | _BV(OCIE0));
SREG = sreg;
};



// *************************************
void Timer0_PWM_STOP(void)
// *************************************
{
unsigned char sreg;
sei();
sreg = SREG; //loakaler Speicher
TIMSK &= ~( _BV(TOIE0) | _BV(OCIE0)  );
TCCR0 &= TCCR0_CLK_STOP_MASK;
SREG = sreg;
SM_PORT_OUT = ((SM_PORT_OUT) & (~SM_ALLCTRL_MSK))    | //ODER . ehalte alle anderen Bits   
        (pgm_read_byte_near( (PGM_P)(gpmpaStepPattern + (gu8StepPars % gucModePatternModulo) ) ) );              
};


// *************************************
void Set_StepMotor_Mode(uint8_t ucVal)
//gu8StepMConditionFlag & STEPM_STEPMODE12_MASK
// *************************************
{ //0 = FULL_STEP 1= HALFSTEP;
//Berechne tatsächliche Schritte pro Rotation
gsStMPar.u8SM_Mode = ucVal;
gsStMPar.u16StepsPerRotation = gsStMPar.u16SM_StepsRotationType * ucVal;//wegen:half/full
switch(ucVal)
    {
    case MODE_FULLSTEP :    //*1
        {//FULL 1
        //gsStMPar.u8SM_Mode = MODE_FULLSTEP;
        gpmpaStepPattern     = MCA_FULLSTEPS;    //MCA pointer Adr.
        gucModePatternModulo = FULLSTEPMODEPARSMAX;//4
        break;
        };
    case MODE_HALFSTEP :    //*2
        {
        //gsStMPar.u8SM_Mode = MODE_HALFSTEP;
        gpmpaStepPattern = MCA_HALFSTEPS;    //MCA pointer Adr.
        gucModePatternModulo = HALFSTEPMODEPARSMAX;//8
        break;
        };
    };
};


// *************************************
void SetMotorDirection(uint8_t ucVal)
// *************************************
{//0= Rechts  1=Linksrum
//Nur wenn nicht schon so eingestellt
//Geht nur, weil #define STEPM_DIRECTION_FLAG        0x01= NULL Bit --> Sonst Shift Bit
if( (gu8StepMConditionFlag & STEPM_DIRECTION_FLAG) ^ ucVal )  //EXOR ungleich?
    {
    if(ucVal) //1 == links
        {
        gu8StepMConditionFlag |= STEPM_DIRECTION_FLAG;
        }
    else//dir == 0 == rechts
        {
        gu8StepMConditionFlag &= ~STEPM_DIRECTION_FLAG;
        };
//Falls Motor grad aktiv ist,,halt in an,und ändere die Richtung       
    if( (gu8StepMConditionFlag & STEPM_ENABLE_FLAG)  &&
        (gu8StepMConditionFlag & STEPM_RUN_FLAG )
    )
        {
        StepMotorStop();
        gu8StepMConditionFlag |= STEPM_START_RAMPE_FLAG;       
        StepMotorOn();
        };
    };
};




// *************************************
void StepMotorOn(void)
// *************************************
{
    //Verriegelung, falls der Motor an den Anschlagschalterns steht,
    //das er in die falsche Richtung anstartet   
    //0x10 Wert des EXtswitch via INT1 = LINKS
    //define MODE_FULLSTEP 0x00    define MODE_HALFSTEP 0x01
    //1. Warte auf Stop --> Ist der Auftrag erledigt, (verhindert widersprechnede Befehle)
/*
    while( !(gu8SM_PostionFlag & POSITION_STOP_ON_TARGET_OK) )   
        {//Damit der Motor sich beruhigen kann
        wdt_reset();   //WATCHDOG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   
        };
*/
#ifdef USE_ENDPOSITION_SWITCH_INT0
if( !(gstInt0Key.ucKeyStat & KEYSTAT_RELEASED) &&
    (
    (
    (gstInt0Key.ucKey == KEY_ENDSWITCH_LEFT ) && (gu8StepMConditionFlag & STEPM_DIRECTION_FLAG)
    ) ||
    (
    ( gstInt0Key.ucKey == KEY_ENDSWITCH_RIGHT )  &&  !(gu8StepMConditionFlag & STEPM_DIRECTION_FLAG)
    )
    )
  )
    {
    return;
    };
#endif
       
    Timer0_PWM_STOP();
    Set_StepMotor_Mode( gsStMPar.u8SM_Mode );       
   
    //Nur Rampe wenn FRQ > PREDEF_RAMPENSSTARTFRQ
    if( (gsStMPar.fSM_Soll_FRQ > PREDEF_RAMPENSSTARTFRQ) && //> 10.0, also mit RAMPE
        (gu8StepMConditionFlag & STEPM_RAMPE_FLAG)
    )
        {
        gu8StepMConditionFlag |= STEPM_START_RAMPE_FLAG;  //START !!!! Situation
        gsStMPar.fSM_Ist_Frq = PREDEF_RAMPENSSTARTFRQ;
        }
    else//KEINE RAMPE
        {
        gsStMPar.fSM_Ist_Frq = gsStMPar.fSM_Soll_FRQ;    //Set Frequenz wie in Struct.
        };   
   
    gsStMPar.u32MovedSteps = 0;    //COUNTSZÄHLER !!!!!!!
   
    //Lege die letzen Bitts an...
    if( !(gu8StepMConditionFlag & STEPM_ENABLE_FLAG) )
        {       
        SM_PORT_OUT = ((SM_PORT_OUT ) & ~SM_ALLCTRL_MSK)    | //ODER . clear SMbit und erhalte alle anderen Bits   
            (pgm_read_byte_near( (PGM_P)(gpmpaStepPattern + gu8StepPars) ) );       
        //Unbedingt warten damit Magnetfeld sich aufbauen und fangen kann.
        wdt_reset();
        _delay_ms( Motor_START_LAST_BITPATTERN_ON_TIME );    //30ms   
        };   
    //3.erst dann Starte   
    gu8StepMConditionFlag |= STEPM_ENABLE_FLAG | STEPM_RUN_FLAG;//ENABLE ANZEIGEN (INTERRUPPT)UND SPEICHERN       
    gu8StepMConditionFlag &= ~(STEPM_STOP_ACTIVE_FLAG | STEPM_TIMEOUT_ENABLE_FLAG);    //Lösche Pausebedingung   
    gu8SM_PostionFlag &= ~POSITION_STOP_ON_TARGET_OK;
    Set_SM_FRQ(gsStMPar.fSM_Ist_Frq);
    StepFRQ_OnOff(FRQ_ON);
};



// *************************************
void StepMotorStop(void)    //hält mOTOR an, ictrl/pwm,bleibt ENABLE !!
// *************************************
{
StepFRQ_OnOff(FRQ_OFF);    //0
//ENABELD ( STROM AKTIV !!!!)
//Jetzt mit allen Flags aufräumen
gu8StepMConditionFlag &= ~(STEPM_RUN_FLAG | STEPM_PULSE_MODE_FLAG);
gu8SM_PostionFlag &= ~(POSITION_STOP_ON_DISTANCE_MODE_FLAG | POSITION_STOP_ON_TARGET_MODE_FLAG);
gu8SM_PostionFlag |= POSITION_STOP_ON_TARGET_OK;
//MIT BEIDE ENABLES ON
SM_PORT_OUT |= SM_ENABLE_MSK;
Timer0_PWM( gsStMPar.u8Stop_PWM_Rate ) ;
gu8StepMConditionFlag |= STEPM_STOP_ACTIVE_FLAG | STEPM_TIMEOUT_ENABLE_FLAG;    //Zeige Stopstatus-ENABLED an
};


// *************************************
void StepMotorOff(void)    //Komplett STOPS AND FREE axis.
// *************************************
{
StepMotorStop();
Timer0_PWM_STOP();
SM_PORT_OUT &= ~SM_ENABLE_MSK; // Lösche nur!  Enable Status
//Lösche Stopstatus
gu8StepMConditionFlag &= ~(STEPM_ENABLE_FLAG | STEPM_STOP_ACTIVE_FLAG | STEPM_RUN_FLAG);
//NUR CONTROLL LIENES; ENABLE ARE ACTIV. //BITS LASSEN; WIE SIE SIND..!!!!
};



// *************************************
void Set_SM_FRQ(float fVal)
// *************************************
{
float fComVal;
float fTimerDivider;

//if( fVal > MAXIMAL_FRQ ) return;
if( fVal < MINIMAL_FRQ ) return;
//Voreinstellung
fTimerDivider = TIMER_DIVIDE_FRQ_1; //if( fVal < TIMER_HALFCOMP_FRQ_1024)   
gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_1;
//Clock udn OCR1A so hoch als möglich
if( ( fComVal = F_CPU / fVal )  > 0xFFFF )
    {
    fTimerDivider = TIMER_DIVIDE_FRQ_8; //if( fVal < TIMER_HALFCOMP_FRQ_1024)   
    gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_8;
    if( ( fComVal = TIMER_DIVIDE_FRQ_8 / fVal )  > 0xFFFF )
        {
        fTimerDivider = TIMER_DIVIDE_FRQ_64; //if( fVal < TIMER_HALFCOMP_FRQ_1024)   
        gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_64;
        if( ( fComVal = TIMER_DIVIDE_FRQ_64 / fVal )  > 0xFFFF )
            {
            fTimerDivider = TIMER_DIVIDE_FRQ_256; //if( fVal < TIMER_HALFCOMP_FRQ_1024)   
            gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_256;
            if( ( fComVal = TIMER_DIVIDE_FRQ_256 / fVal )  > 0xFFFF )
                {   
                fTimerDivider = TIMER_DIVIDE_FRQ_1024; //if( fVal < TIMER_HALFCOMP_FRQ_1024)   
                gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_1024;
                fComVal = TIMER_DIVIDE_FRQ_1024 / fVal;
                }}}};
cli();
TCNT1 = 0;  //sicherung gegenen unbeabsichtigten Overrrun
OCR1A = (uint16_t)round( fComVal );
if(OCR1A)
    {
    gfSMRealFrq = fTimerDivider / OCR1A;
    };
//Vorteiler setzen
TCCR1B = TCCR1B_CTC_MODE | gu8Timer_CSxxClkSelect;    //mode 4 Clear Timer on Compare=CTC.  MODE 4 an OCR1A + / CLk/1024
sei();
};



// *************************************
void StepFRQ_OnOff(uint8_t uOnOff)
// *************************************
{
cli();
TCCR1B = TCCR1B_CLOCKSEL_STOP;    //Stopen, damit keine geschachtelten Interrrupts passieren...
if( uOnOff )  // Im FALLE DAS FRQ = 0 MOTOR STOP !
    {
    TCCR1B = TCCR1B_CTC_MODE | gu8Timer_CSxxClkSelect;//Clear Timer on Compare=CTC.  MODE an OCR1A + / CLk/1024
    TCNT1 = 0;/* reset TCNT1 */
    TIMSK |= _BV(OCIE1A );    //Interrupt ein
//1.Write High   
//    timer_enable_int(_BV(OCIE1A));    //WARNUNG TIMSK wird ÜBERSCHRIeBEN
    }
else
    {
    TIMSK &= ~_BV(OCIE1A );  //Interrupt OFF
    TCCR1B &=  TCCR1B_CLOCKSEL_MSK;
    };
sei();
};



// *******************************************************************
void SM_Run_Puls_DIR(uint32_t uiPuls, uint8_t ucDir)
// *******************************************************************
{
SetMotorDirection( ucDir );
gsStMPar.u32SM_ToRunCnt = uiPuls;
gu8StepMConditionFlag |= STEPM_PULSE_MODE_FLAG;
StepMotorOn();
};



//Init
// *******************************************************************
void SM_InitStructVals(void)
// *******************************************************************
{
gsStMPar.fSM_Soll_FRQ = PREDEF_STEPFREQUENZ;        //Default 100.0
gsStMPar.u8SM_Mode = PREDDEF_STEPMODE;                //MODE_HALFSTEP
gsStMPar.fSM_Ist_Frq = PREDEF_RAMPENSSTARTFRQ;     //10.0
gsStMPar.u8SM_RampenSteigung = PREDEF_RAMP_RISE;    //Default 0
gsStMPar.u32SM_ToRunCnt = PREDEF_STEPRCLOCKS;//= 1 wieviele Steps soll der Motor gehen(Default= 1)
gsStMPar.u16SM_StepsRotationType = PREFDEF_STEPS_PER_ROTATION;    //Default 400
gsStMPar.u8Stop_PWM_Rate = PREDEF_STOP_PWM_RATE;
};




stepmot.h



#ifndef STEPMOTOR_HEADER
#define STEPMOTOR_HEADER


//#define USE_ENDPOSITION_SWITCH_INT0
#define STEPMOTOR_USED


typedef struct
    {
    float fSM_Soll_FRQ;   
    float fSM_Ist_Frq;        //Wird incrementiert bis == gsStMPar.fSM_Soll_FRQ für Rampe   
    uint8_t u8SM_RampenSteigung;
    uint8_t u8SM_Mode;    //Full=1 Half  = 2
    uint32_t u32MovedSteps;//compare with MovedSteps //Wieviel hat sich der Motor gedreht..       
    uint32_t u32SM_ToRunCnt;    //PULSE die der Motor laufen soll   
    uint16_t u16SM_StepsRotationType; //=PREFDEF_STEPS_PER_ROTATION
    uint16_t u16StepsPerRotation; //u8SM_Mode * u16SM_StepsRotationType=PREFDEF_STEPS_PER_ROTATION=
    uint8_t u8Stop_PWM_Rate; //u0 ..255
}STEPMPARTYPE;    //gsStMPar.ucStepMConditionFlag


//REGISTER
#define TCCR0_FAST_PWM    0x48    //Mode 3
#define TCCR0_OC0_MODE    0x20    //Clear ON compare Match
#define TCCR0_OC0_DISCONNECT_MODE    0x00
#define TCCR0_CLK_STOP    0x00   
#define TCCR0_CLK_0        0x01    //62500 PWM
#define TCCR0_CLK_8        0x02    //7812 Hz PWM
#define TCCR0_CLK_64        0x03    //976,56Hz PWM
#define TCCR0_CLK_256    0x04    //244,14Hz PWM
#define TCCR0_CLK_1024    0x05    //~61,035 PWM
#define TCCR0_EXT_CLK_FALL_T0    0x06   
#define TCCR0_EXT_CLK_RISE_T0    0x07
#define TCCR0_CLK_STOP_MASK    0xF8   



#define TCCR0_FAST_PWM    0x48    //Mode 3
#define TCCR0_OC0_MODE    0x20    //Clear ON compare Match
#define TCCR0_OC0_DISCONNECT_MODE    0x00


//#define TCCR1B_CLOCKSEL_CTC1         0x08    //Clear Timer/Counter  on Compare Match Timer/Counter 1
#define TCCR1B_CLOCKSEL_STOP        0x00    //Clock Select Bits
#define TCCR1B_CLOCKSEL_MSK        0xF8 // zum Stoppen der CLK
#define TCCR1B_CTC_MODE                0x08    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_1        0x01    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_8        0x02    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_64    0x03    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_256    0x04    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_1024    0x05    //Clock Select Bits




#define PULS_PER_SECOND_T1    15625.0 //TCCR2_CLK_1024
#define SM_AFTERSTOPDELAY_TICKS    2    //~16ms 1=TIMER2_INTPERIODE

//STEPMOTOR HARDWARE
#define SM_PORT_OUT    PORTA   
#define SM_PORT_IN    PINA   
#define SM_PORT    PORTA   
#define SM_DIRREG    DDRA

#define SM_ALLCTRL_MSK    0x3F
#define SM_INPX_MSK        0x0F
#define SM_ENABLE_MSK    0x30

#define SM_INP1    0x01
#define SM_INP2    0x02
#define SM_INP3    0x04
#define SM_INP4     0x08
#define SM_ENA_A     0x10
#define SM_ENA_B     0x20
#define SM_ISENS_A    0x40
#define SM_ISENS_B    0x80

 
#define SM_INIT_DIRREG()   (SM_DIRREG |= SM_ALLCTRL_MSK) // OUT richtig Stellen

// SPEZIFISCHE DEFINITIONEN; JE NACH HARDWARE
//BEI 16 MHz Quarz = F_CPU / Teiler
// QUARZ/DIVIDE = FREQUENZ
#define TIMER_DIVIDE_FRQ_1        ((float)F_CPU)    // 16000000UL
#define TIMER_DIVIDE_FRQ_8        ((float)F_CPU / 8) //2000000UL       
#define TIMER_DIVIDE_FRQ_64    ((float)F_CPU / 64) //250000UL
#define TIMER_DIVIDE_FRQ_256    ((float)F_CPU / 256) //62500U
#define TIMER_DIVIDE_FRQ_1024    ((float)F_CPU / 1024) //15625U

#define MAXIMAL_FRQ    800
#define  MINIMAL_FRQ    0.2

#define FULLSTEPMODEPARSMAX 4   
#define HALFSTEPMODEPARSMAX 8   
//#define QUARTERSTEPMODEPARSMAX 16
//#define EIGHTHSTEPMODEPARSMAX 32
#define MODE_FULLSTEP    1    //Multiplikator 1X. gsStMPar.ucStepMConditionFlag |=  MODE_FULLSTEP
#define MODE_HALFSTEP     2    //Multiplikator 2X. Set_StepMotor_Mode(gsStMPar.ucStepMConditionFlag & STEPM_STEPMODE_)
#define FULLROT_DEGREE_360            360.0    //muss float sein
#define Motor_START_LAST_BITPATTERN_ON_TIME 15 //~20ms sec ms Zeit, damit der Motor unter vor der Bewegung unter Strom gesetzt wird.
//STEP FRQ
#define FRQ_OFF    0
#define FRQ_ON        1
//DIRECTION
#define SM_DIR_RECHTS    0
#define SM_DIR_LINKS        1

#define MOTORSTOP_PWM    200 // PWM RATE fuer den Motor bei Stop 8KHZ


#define PREFDEF_STEPS_PER_ROTATION    200 //DEFAULT, 200 Normal, 400=Fein=0.9Degree, grob=30=~12.857Degree
#define PREDEF_STEPFREQUENZ             100.0    //Hz
#define PREDEF_RAMPENSSTARTFRQ        10.0    //Die Frq ab der überhaubt erst eine Rampe gefahren wird..
#define PREDEF_RAMP_RISE                 0    //Anstieg der RampenFrequenz
#define PREDEF_STEPRCLOCKS              1    //STEPS
#define PREDDEF_STEPMODE                MODE_HALFSTEP
#define PREDEF_STOP_PWM_RATE            180 // 0.255 WPM bei 62500kHZ


//Es wird unterschieden nach CTRL und Condition Flags
//in STRUCT STEPMPARTYPE;
//Flags
#define STEPM_ENABLE_FLAG            0x01    // 0 = OFF
#define STEPM_PULSE_MODE_FLAG        0x02    // 0 = OFF
#define STEPM_RAMPE_FLAG            0x04    // MIT_RAMPE, ?
#define STEPM_START_RAMPE_FLAG    0x08    // 0 = Selected Counts, 1 = Countinous
//------
#define STEPM_STOP_ACTIVE_FLAG    0x10    //STOP, BUT ENABLED, (STROM ON!!) Absicht!!, STEMotor StoptMode ..mit ICTRL, SPÄTER PWM, oder Automatische Disable nach Timeout.
#define STEPM_TIMEOUT_ENABLE_FLAG    0x20    //After Stop Auto Disable after TIMEOUT
#define STEPM_DIRECTION_FLAG        0x40    // 0 = rechts ?? unbestimmt je nach verdrahtung
#define STEPM_RUN_FLAG                0x80    //Ohne RemainTime Zurücksetzung Run=Continue condtition
//    gsStMPar.ucStepMConditionFlag;    //ISTZUSTAND


#define POSITION_Index_Valid_FLAG        0x01
#define POSITION_LOW_DETECT                0x02
#define POSITION_HIGH_DETECT                0x04
//------
#define POSITION_STOP_ON_TARGET_MODE_FLAG    0x10   
#define POSITION_STOP_ON_TARGET_OK            0x20   
#define POSITION_STOP_ON_DISTANCE_MODE_FLAG    0x40   
#define POSITION_STOP_ON_DISTANCE_OK    0x80   

//gu8SM_PostionFlag
extern uint32_t gu32_Ticks; //  T2 timeCounter, only NN_Counter for Keypressings

extern STEPMPARTYPE gsStMPar;
extern uint8_t gu8StepMConditionFlag;    //ISTZUSTAND wir Mode
extern uint8_t gu8SM_PostionFlag;

extern void Timer0_PWM(unsigned char ucPwmRange);
extern void Set_StepMotor_Mode(uint8_t ucVal);
extern void SetMotorDirection(uint8_t ucVal);
extern void StepMotorOn(void);
extern void StepMotorStop(void);
extern void StepMotorOff(void);
extern void Set_SM_FRQ(float fVal);
extern void StepFRQ_OnOff(uint8_t uOnOff);
extern void SM_Run_Puls_DIR(uint32_t uiPuls, uint8_t ucDir);
extern void SM_InitStructVals(void);


//-----------------------------------------------------------
#endif //STEPMOTOR_HEADER