//wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww/** I N C L U D E S **********************************************************/ #include #include #include #include #include #include #include"LCD\\xlcd.h" #define Light_ON LATCbits.LATC6 // output Light ON #define Brake_ON LATCbits.LATC5 // output Brake ON #define LCD_ON LATCbits.LATC4 // output LED ON #define LED LATBbits.LATB3 // output for LED #define D7 LATDbits.LATD7 // output -T1 #define D6 LATDbits.LATD6 // output -T2 #define D5 LATDbits.LATD5 // output -T3 #define D4 LATDbits.LATD4 // output -T4 #define B7 PORTBbits.RB7 // input UP #define B6 PORTBbits.RB6 // input DOWN #define B5 PORTBbits.RB5 // input LEFT #define B4 PORTBbits.RB4 // input RIGHT #define Brake PORTBbits.RB0 // input Brake #pragma config OSC = HS //HS Speed (IRCIO7 interner Takt) Internal RC with OS as RA7 and OSC2 as divide by 4 clock out #pragma config FCMENB = OFF //Fail-safe clock monitor disabled #pragma config IESOB = OFF //Internal OSC switch over bit #pragma config PWRT = ON //Power up timer ON #pragma config BOR = BOACTIVE //enabled whenever part is active, SBOREN disabled #pragma config BORV = 42 //Reset if Vcc smaller 4,2V; 2,7V; 2,0V #pragma config WDT = ON //Watchdog ON #pragma config WDTPS = 16384 //after 65,5 s reset #pragma config PBADEN = ON //Pins are configured as analog input channels on Reset #pragma config LPT1OSC = OFF //bei 0; Timer1 configured for higher power operation #pragma config MCLRE = ON //Reset at MCLR ON #pragma config LVP = OFF //LVP OFF //12.04.2015 TRISx bestimmt die Richtung. PORTx zeigt Eingänge, LATx setzt Ausgänge //Always read inputs from PORTx and write outputs to LATx. If you need to read what you set an output to, read LATx." //-------------------------------------------------------------------------------------------------------------------- void InterruptHandlerHigh (void); void InterruptHandlerLow (void); void DelayFor18TCY( void ) { int i_18; for( i_18=0;i_18<36;i_18++ ) { Nop(); } } //--------------------------------------------------------- void DelayPORXLCD( void ) { Delay1KTCYx(75); //Delay of 15ms (was 200 bei 4 MHz) //75 return; } //--------------------------------------------------------- void DelayXLCD( void ) { Delay1KTCYx(25); //Delay of 5ms (was 100 bei 4 MHz) //25 return; } //--------------------------------------------------------- volatile unsigned char LastKnownPORTB; //part in ISR volatile unsigned char PORTB7 =0; //part in ISR volatile unsigned char PORTB6 =0; //part in ISR volatile unsigned char PORTB5 =0; //part in ISR volatile unsigned char PORTB4 =0; //part in ISR //--------------------------------------------------------- volatile unsigned int AN0; // not part in ISR 0 -> 65535 throttle volatile unsigned char AN0_offset = 200; // not part in ISR 0 -> 255 Offset value throttle plus safety margin // Gas kann max. 858 bei 5.12 V (858-200= 658 Teile zur Verfügung) // 1024 / 658 Teile = 1,556 / 1,55* 658 = 1020 volatile unsigned float AN0_DC =1.55; // Kommazahl Umrechnung ANO zu Duty cycle volatile unsigned short ERG; // part in ISR 0 -> 65535 calculated duty cycle for PWM //--------------------------------------------------------- volatile unsigned int AN1; // not part in ISR 0 -> 65535 Light dependend Resistor //--------------------------------------------------------- volatile unsigned int AN2; // part in ISR 0 -> 65535 Motor Current volatile unsigned int MOTOR_CURRENT; // not part in ISR 0 -> 65535 Motor Current //--------------------------------------------------------- volatile unsigned int AN4; // not part in ISR 0 -> 65535 BATTERIE volatile unsigned int BAT_WERT; // not part in ISR 0 -> 65535 BATTERIE //--------------------------------------------------------- volatile unsigned int DC_max = 1000; // part in ISR 0 -> 65535 volatile unsigned int DC_alt = 0; // part in ISR 0 -> 65535 volatile unsigned int DC_act = 0; // part in ISR 0 -> 65535 volatile unsigned char DC_speed = 20; // part in ISR 0 -> 255 stepwide for duty cycle volatile unsigned int SW_Z = 0; // part in ISR 0 -> 65535 counter intervall volatile unsigned int SW_Intervall = 290; // part in ISR 0 -> 65535 Intervall 1/5000* Wert = Intervall volatile unsigned char Gas = 0; // not part in ISR 0 -> 255 volatile unsigned int RPM_count = 0; // part in ISR 0 -> 65535 volatile unsigned int RPM = 0; // part in ISR 0 -> 65535 volatile unsigned int Speed = 0; // not part in ISR 0 -> 65535 volatile float Speed_1 = 0; // not part in ISR volatile unsigned char Go = 0; // part in ISR 0 -> 255 //--------------------------------------------------------- volatile unsigned long int cm = 0; // not part in ISR 0 bis 4294967295 volatile unsigned char distance = 0; // not part in ISR 0 -> 255 char LCDdata1[40]; // not part in ISR void main(void) { LATCbits.LATC6=0; // set to LOW Light ON LATCbits.LATC5=0; // set to LOW brake ON LATCbits.LATC4=0; // set to LOW LCD on LATBbits.LATB3=0; // set to LOW LED TRISBbits.TRISB7 = 1; // set PORTB7 as input port TRISBbits.TRISB6 = 1; // set PORTB6 as input port TRISBbits.TRISB5 = 1; // set PORTB5 as input port TRISBbits.TRISB4 = 1; // set PORTB4 as input port TRISBbits.TRISB0 = 1; // set PORTB0 as input port Brake signal TRISCbits.TRISC6 = 0; // set PORTC6 as output port Light_ON TRISCbits.TRISC5 = 0; // set PORTC5 as output port Brake_ON TRISCbits.TRISC4 = 0; // set PORTC4 as output port LCD_ON TRISBbits.TRISB3 = 0; // set PORTB3 as output port LED TRISCbits.TRISC2 = 0; // set PORTC2 as output port PWM TRISAbits.TRISA0 = 1; // set PORTA0 as input port Throttle TRISAbits.TRISA1 = 1; // set PORTA2 as input port DR TRISAbits.TRISA2 = 1; // set PORTA2 as input port Current TRISAbits.TRISA5 = 1; // set PORTA0 as input port Battery TRISDbits.TRISD7 = 0; // set PORTD7 as output port TRISDbits.TRISD6 = 0; // set PORTD6 as output port TRISDbits.TRISD5 = 0; // set PORTD5 as output port TRISDbits.TRISD4 = 0; // set PORTD4 as output port OSCCONbits.SCS1 = 0; // SCS<1:0>: System Clock Select bits 00 for PLL OSCCONbits.SCS0 = 0; // 1x = Internal oscillator block // 01 = Timer1 oscillator // 00 = Primary oscillator OSCTUNEbits.PLLEN = 0; // PLLEN: Frequency Multiplier PLL for INTOSC Enable bit(1) // 1 = PLL enabled for INTOSC (4 MHz and 8 MHz only) // 0 = PLL disabled //--------------------------------------------------------------------------------------------------------------// //--------------------------------------------------------------------------------------------------------------// //Timer 0 high priority interrupt aller 1,67 s = 0,6 Hz durch Timer schreiben auf 1 Hz eingestellt T0CONbits.T0PS2 = 1; // T0PS<2:0>: Timer0 Prescaler Select bits T0CONbits.T0PS1 = 1; // 111 = 1:256 Prescale value T0CONbits.T0PS0 = 0; // 110 = 1:128 Prescale value // 101 = 1:64 Prescale value // 100 = 1:32 Prescale value // 011 = 1:16 Prescale value // 010 = 1:8 Prescale value // 001 = 1:4 Prescale value // 000 = 1:2 Prescale value T0CONbits.T0PS3 = 0; // PSA: Timer0 Prescaler Assignment bit .PSA laut Datenblatt geht nicht!! // 1 = TImer0 prescaler is not assigned. Timer0 clock input bypasses prescaler. if 1 = prescaler not working and 1:2 ratio // 0 = Timer0 prescaler is assigned. Timer0 clock input comes from prescaler output. T0CONbits.T0SE = 1; // T0SE: Timer0 Source Edge Select bit // 1 = Increment on high-to-low transition on T0CKI pin // 0 = Increment on low-to-high transition on T0CKI pin T0CONbits.T0CS = 0; // T0CS: Timer0 Clock Source Select bit // 1 = Transition on T0CKI pin input edge // 0 = Internal clock (FOSC/4) T0CONbits.T08BIT = 0; // 0= 16bit Timer 1= 8bit Timer T0CONbits.TMR0ON = 1; // 1= enable Timer 0 INTCON2bits.TMR0IP = 1; //TMR0 Overflow Interrupt Priority bit //1 = High priority //0 = Low priority INTCONbits.TMR0IE = 1; //TMR0 Overflow Interrupt Enable bit //1 = Enables the TMR0 overflow interrupt //--------------------------------------------------------------------------------------------------------------// //Timer1 @ low priority interrupt xxx Hz T1CONbits.RD16 = 1; //1 = Enables register read/write of Timer1 in one 16-bit operation //0 = Enables register read/write of Timer1 in two 8-bit operations T1CONbits.T1RUN = 0; //1 = Device clock is derived from Timer1 oscillator //0 = Device clock is derived from another source T1CONbits.T1CKPS1 = 1; //Prescale 1=8 1=4 0=1 T1CONbits.T1CKPS0 = 1; //Prescale 1=8 0=4 0=1 T1CONbits.T1OSCEN = 0; //1 = Timer1 oscillator is enabled //0 = Timer1 oscillator is shut off //T1CONbits.T1SYNC = 1; //Timer1 External Clock Input Synchronization Select bit //When TMR1CS = 1: //1 = Do not synchronize external clock input //0 = Synchronize external clock input //When TMR1CS = 0: //This bit is ignored. Timer1 uses the internal clock when TMR1CS = 0 T1CONbits.TMR1CS = 0; //Timer1 Clock Source Select bit //1 = External clock from pin RC0/T1OSO/T13CKI (on the rising edge) //0 = Internal clock (FOSC/4) T1CONbits.TMR1ON = 1; //Timer1 On bit //1 = Enables Timer1 //0 = Stops Timer1 //-----------------------------------------------------------------------------------------------------------------// PIE1bits.TMR1IE = 1; //TMR1 Overflow Interrupt Enable bit //1 = Enables the TMR1 overflow interrupt PIE1bits.TMR2IE = 1; //1 = Enables the TMR2 to PR2 match interrupt //0 = Disables the TMR2 to PR2 match interrupt IPR1bits.TMR1IP = 1; //TMR1 Overflow Interrupt Priority bit //1 = High priority //0 = Low priority IPR1bits.TMR2IP = 1; //TMR2 Overflow Interrupt Priority bit //1 = High priority //0 = Low priority //Timer2 Einstellungen //-----------------------------------------------------------------------------------------------------------------// T2CONbits.T2OUTPS3 = 0; //00 = Prescaler is 1 T2CONbits.T2OUTPS2 = 0; //00 = Prescaler is 1 T2CONbits.T2OUTPS1 = 0; //00 = Prescaler is 1 T2CONbits.T2OUTPS0 = 0; //00 = Prescaler is 1 T2CONbits.TMR2ON = 1; //1= Timer2 is on T2CONbits.T2CKPS1 = 0; //01 = Prescaler is 4 T2CONbits.T2CKPS0 = 1; //01 = Prescaler is 4 //-----------------------------------------------------------------------------------------------------------------// RCONbits.IPEN = 1; //IPEN: Interrupt Priority Enable bit //1 = Enable priority levels on interrupts //0 = Disable priority levels on interrupts INTCONbits.GIEH = 1; //When IPEN = 1: //1 = Enables all high-priority interrupts //0 = Disables all high-priority interrupts INTCONbits.GIEL = 0; //When IPEN = 1: //1 = Enables all low-priority peripheral interrupts //0 = Disables all low-priority peripheral interrupts INTCONbits.INT0IE = 1; //INT0 External Interrupt Enable bit //1 = Enables the INT0 external interrupt //0 = Disables the INT0 external interrupt INTCONbits.RBIE = 1; //RB Port 4 to 7 Change Interrupt Enable bit //1 = Enables the RB port change interrupt //0 = Disables the RB port change interrupt //-----------------------------------------------------------------------------------------------------------------// //PWM Settings PR2 = 249; CCP1CONbits.CCP1M3 = 1; //11xx = PWM mode CCP1CONbits.CCP1M2 = 1; //11xx = PWM mode SetDCPWM1(DC_act); //-----------------------------------------------------------------------------------------------------------------// //ADC Einstellungen ADCON0bits.CHS3 = 0; ADCON0bits.CHS2 = 0; ADCON0bits.CHS1 = 0; ADCON0bits.CHS0 = 0; //ADCON0bits.GO = 1; //1 = A/D conversion in progress ADCON0bits.ADON = 1; //1 = A/D Converter module is enabled ADCON1bits.VCFG1 = 0; //0 = AVSS (AN2) Voltage Reference Configuration bit (VREF- source) //1 = VREF- (AN2) ADCON1bits.VCFG0 = 1; //0 = AVDD (AN3) Voltage Reference Configuration bit (VREF+ source) //1 = VREF+ (AN3) 5,00 V ADCON1bits.PCFG3 = 1; //1110 (AN10) D D D D D D A A A A A (AN0) ADCON1bits.PCFG2 = 0; //1110 (AN10) D D D D D D A A A A A (AN0) ADCON1bits.PCFG1 = 1; //1110 (AN10) D D D D D D A A A A A (AN0) ADCON1bits.PCFG0 = 0; //1110 (AN10) D D D D D D A A A A A (AN0) ADCON2bits.ADCS2 = 1; //110 = FOSC/64 ADCON2bits.ADCS1 = 1; //110 = FOSC/64 ADCON2bits.ADCS0 = 0; //110 = FOSC/64 ADCON2bits.ACQT2 = 1; //111 = 20 TAD ADCON2bits.ACQT1 = 1; //111 = 20 TAD ADCON2bits.ACQT0 = 1; //111 = 20 TAD ADCON2bits.ADFM = 1; //1 = Right justified //-----------------------------------------------------------------------------------------------------------------// INTCON2bits.RBPU = 1; //PORTB Pull-up Enable bit //1 = All PORTB pull-ups are disabled //0 = PORTB pull-ups are enabled by individual port latch values INTCON2bits.INTEDG0 = 1; //External Interrupt 0 Edge Select bit //1 = Interrupt on rising edge //0 = Interrupt on falling edge INTCON2bits.INTEDG1 = 1; //External Interrupt 1 Edge Select bit //1 = Interrupt on rising edge //0 = Interrupt on falling edge INTCON2bits.INTEDG2 = 1; //External Interrupt 2 Edge Select bit //1 = Interrupt on rising edge //0 = Interrupt on falling edge INTCON2bits.RBIP = 1; //RB Port Change Interrupt Priority bit //1 = High priority //0 = Low priority //CONFIG4Lbits.DEBUG =1; //Background Debugger Enable bit //1 = Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins //0 = Background debugger enabled, RB6 and RB7 are dedicated to In-Circuit Debug //-----------------------------------------------------------------------------------------------------------------// INTCON3bits.INT2IP = 1; //INT2 External Interrupt Priority bit //1 = High priority //0 = Low priority INTCON3bits.INT1IP = 1; //INT1 External Interrupt Priority bit //1 = High priority //0 = Low priority /* INT0 it´s always a high-priority interrupt source*/ INTCON3bits.INT2IE = 1; //INT2 External Interrupt Enable bit //1 = Enables the INT2 external interrupt //0 = Disables the INT2 external interrupt INTCON3bits.INT1IE = 1; //INT1 External Interrupt Enable bit //1 = Enables the INT1 external interrupt //0 = Disables the INT1 external interrupt //-----------------------------------------------------------------------------------------------------------------// //-----------------------------------------------------------------------------------------------------------------// LCD_ON = 1; Delay10KTCYx(100); // 0,2 s delay very important and needed OpenXLCD(FOUR_BIT & LINES_5X7 ); while( BusyXLCD() ) { } SetDDRamAddr((unsigned char) 0); // 1. row in display putrsXLCD(( char*)"Willkommen NIC"); SetDDRamAddr((unsigned char) 40); // 2. row in display putrsXLCD(( char*)"E-Kart Version 1"); Delay10KTCYx(250); // 0,5 s delay while (1) { ClrWdt() // clear Watchdog //--------------------------------------------------------------------------------------------------------// SetChanADC( ADC_CH0); // Throttle ConvertADC(); while( BusyADC() ){} AN0 = ReadADC(); if(AN0 > AN0_offset) { ERG = (float)AN0_DC * (AN0 - AN0_offset); // Throttle pressed } else { ERG = 0; // Throttle not pressed } //--------------------------------------------------------------------------------------------------------// SetChanADC( ADC_CH1); // LDR ConvertADC(); while( BusyADC() ){} AN1 = ReadADC(); if (AN1<500) // If darkness, then turn ON the light { Light_ON=1; } if (AN1>700) { Light_ON=0; } //-------------------------------------------------------------------------------------------------------- if (Brake) // If brake, then turn ON the brake light { Brake_ON =1; } else { Brake_ON =0; } //--------------------------------------------------------------------------------------------------------// SetChanADC( ADC_CH4); // Battery voltage ConvertADC(); while( BusyADC() ){} AN4 = ReadADC(); BAT_WERT = (int) AN4 * 0.004883 * 6.2457 * 10 ; //--------------------------------------------------------------------------------------------------------// SetChanADC( ADC_CH2); // Motor current ConvertADC(); while( BusyADC() ){} AN2 = ReadADC(); MOTOR_CURRENT = (int) AN2 * 0.0413 * 10 ; //--------------------------------------------------------------------------------------------------------// if(RPM ==0) // Speed calculation { Speed = 0; } else { Speed_1 = (float) 0.82 /((RPM *0.2)/1000)*36 ; // 36 insted of 3.6 m/s x 10 Speed = (int) Speed_1; } //--------------------------------------------------------------------------------------------------------// if (distance ==1) // meilage counter { cm = cm + 82 ; distance =0; } //--------------------------------------------------------------------------------------------------------// strcpypgm2ram(LCDdata1," "); LCDdata1[0] = (Speed % 1000) / 100 + '0'; // Hunderterstelle LCDdata1[1] = (Speed % 100) / 10 + '0'; // Zehnerstelle LCDdata1[2] = ','; LCDdata1[3] = Speed % 10 + '0'; // Einnerstelle LCDdata1[4] = ' '; LCDdata1[5] = 'k'; LCDdata1[6] = 'm'; LCDdata1[7] = '/'; LCDdata1[8] = 'h'; LCDdata1[9] = ' '; LCDdata1[10] = ERG /1000+'0'; // Tausenderstelle LCDdata1[11] = (ERG % 1000) / 100 + '0'; // Hunderterstelle LCDdata1[12] = (ERG % 100) / 10 + '0'; // Zehnerstelle LCDdata1[13] = ERG % 10 + '0'; // Einnerstelle LCDdata1[14] = ' '; LCDdata1[15] = ' '; //--------------------------------------------------------------------------------------------------------// if (PORTB7==1) LCDdata1[16] = '1'; if (PORTB7==0) LCDdata1[16] = '0'; //--------------------------------------------------------------------------------------------------------// if (PORTB6==1) LCDdata1[17] = '1'; if (PORTB6==0) LCDdata1[17] = '0'; //--------------------------------------------------------------------------------------------------------// if (PORTB5==1) LCDdata1[18] = '1'; if (PORTB5==0) LCDdata1[18] = '0'; //--------------------------------------------------------------------------------------------------------// if (PORTB4==1) LCDdata1[19] = '1'; if (PORTB4==0) LCDdata1[19] = '0'; //--------------------------------------------------------------------------------------------------------// SetDDRamAddr((unsigned char) 0); // 1. row in display putsXLCD( LCDdata1); SetDDRamAddr((unsigned char) 40); // 2. row in display putrsXLCD(( char*)"PWM STROM VOLT 4567"); } } //--------------------------------------------------------------------------------------------------------// // High priority interrupt vector #pragma code InterruptVectorHigh = 0x08 void InterruptVectorHigh (void) { _asm goto InterruptHandlerHigh //jump to interrupt routine _endasm } //--------------------------------------------------------------------------------------------------------// // High priority interrupt routine 1 Hz #pragma code #pragma interrupt InterruptHandlerHigh void InterruptHandlerHigh () { if (INTCONbits.TMR0IF) // Timer 0 { INTCONbits.GIEH = 0; //disable interrupts WriteTimer0(26475); //was 80 , @ 3 h it was 2 sek to fast INTCONbits.TMR0IF = 0; //clear interrupt flag INTCONbits.GIEH = 1; //enable interrupts } if (PIR1bits.TMR1IF) //clear interrupt flag Timer 1 { PIR1bits.TMR1IF = 0; } if (INTCON3bits.INT1IF) { INTCON3bits.INT1IF = 0; //clear interrupt 1 flag RPM signal distance =1; if (RPM_count <= 7000) { RPM = RPM_count; RPM_count =0; } Go=1; } if (PIR1bits.TMR2IF) //Timer 2 Interrupt 5 kHz each 0,2 ms (200µs) { PIR1bits.TMR2IF = 0; //clear interrupt flag INTCONbits.GIEH = 0; //disable interrupts SW_Z ++; if (Go==1) { RPM_count ++; } if (RPM_count > 7000) { RPM_count =0; RPM = RPM_count; Go=0; } if (SW_Z == SW_Intervall) { SW_Z = 0; // reset counter if(ERG == 0) //ERG = 0 if AN0 <=200 { DC_act = 0; Gas =0; } if(ERG > 1) //if AN0 >= 201 Throttle pressed { //increase PWM with ramp if( Gas == 0) { DC_act = 10; Gas =1; } else { DC_alt = DC_act; DC_act = (int) DC_alt + DC_speed; if(DC_act >= DC_max ) { DC_act = DC_max; } } if (ERG < DC_act) //if throttle value is lower than before, then set PWM to lower value { DC_act = ERG; } } SetDCPWM1(DC_act); } INTCONbits.GIEH = 1; //enable interrupts } if (INTCONbits.INT0IF) //Brake pedal pushed { INTCONbits.INT0IF = 0; //clear interrupt 0 flag } if (INTCON3bits.INT2IF) { INTCON3bits.INT2IF = 0; //clear interrupt 2 flag // LED = !LED; } if (INTCONbits.RBIF) { LastKnownPORTB = PORTB; // clear the mismatch to enable RBIF to be cleared. INTCONbits.RBIF = 0; // clear interrupt flag LastKnownPORTB = PORTB; // read and save the new state of PORTB. if(B7 ==1) { PORTB7 =1; } else { PORTB7 =0; } if(B6 ==1) { PORTB6 =1; } else { PORTB6 =0; } if(B5 ==1) { PORTB5 =1; } else { PORTB5 =0; } if(B4 ==1) { PORTB4 =1; } else { PORTB4 =0; } } } //--------------------------------------------------------------------------------------------------------// // Low priority interrupt vector #pragma code InterruptVectorLow = 0x18 void InterruptVectorLow (void) { _asm goto InterruptHandlerLow //jump to interrupt routine _endasm } //--------------------------------------------------------------------------------------------------------// // Low priority interrupt routine #pragma code #pragma interrupt InterruptHandlerLow void InterruptHandlerLow () { }