/* This simple program makes writes the time to the screen (Secure CRT), makes LEDs flash, and reads from a variable resistor It used timer1 and interupts */ #include #define FCY 117920000 #include #include #include #include #include #include #include #include #include #include #define PERIOD 7300 // for 1000 Hz pwm frequency #define MAX_DUTY 2*7300 // MAX_DUTY = 2*PERIOD since pwm prescaler is 2 // Configuration Bits _FOSC(CSW_FSCM_OFF & FRC_PLL16); //FRC 7.37MHz * 16 = 117.92MHz/29.48MIPS Tcy=33.9nS _FWDT(WDT_OFF); // watchdog timer off _FBORPOR(PBOR_OFF & BORV27 & PWRT_16 & MCLR_EN); //brown out parameters _FGS(GWRP_OFF); // define some variables unsigned int AD_value; unsigned int GO; /***********************************************************************/ // external input interupt handler void __attribute__((interrupt,no_auto_psv)) _INT4Interrupt( void ) { unsigned int dutycyclereg, dutycycle; char updatedisable; // turn off the pwm signal dutycycle = (unsigned int)0; dutycyclereg = 3; updatedisable = 0; SetDCMCPWM( dutycyclereg, dutycycle, updatedisable ); // duty cycle set to low // turn off the LED to indicate power if off TRISDbits.TRISD7 = 0; PORTD = 0b0000000100000000; // signal the power is off // Disable the interrupt DisableINT4; // now just wait while(1); } /***********************************************************************/ // timer 1 interupt handler void __attribute__((interrupt,auto_psv)) _T1Interrupt( void ) { unsigned int ReadQEI( void ); extern unsigned int AD_value; extern unsigned int GO; // read from the A/D channel ADCON1bits.SAMP = 1; // start the sampling while(!ADCON1bits.DONE); AD_value = ReadADC10(0); // reset Timer 1 interrupt flag IFS0bits.T1IF = 0; // we have a new value GO = 1; } /****************************************************************************************************/ // Initialize external interrupt 4 void Init_INT4(void) { unsigned int config; config = FALLING_EDGE_INT & // interrupt on a falling edge EXT_INT_ENABLE & // enable the interrupts //EXT_INT_PRI_0 ; GLOBAL_INT_ENABLE; ConfigINT4( config ); // turn on the LED to show interrupt is set TRISDbits.TRISD7 = 0; PORTD = 0b0000000010000000; // signal the interrupt is set // prepare for an input on RD11 TRISDbits.TRISD11 = 1; // enable the interrupt DisableINT4; EnableINT4; return; } /****************************************************************************************************/ // Initialize timer 1 void Init_Timer1( unsigned int period ) { unsigned int config; config = T1_INT_PRIOR_4 & // set interrupt priority to 2 T1_INT_ON; // enable the interrupts ConfigIntTimer1( config ); config = T1_ON & // turn on the timer T1_IDLE_CON & // operate during sleep T1_GATE_OFF & // timer gate accumulation is disabled T1_PS_1_256 & // timer prescale is 256 T1_SYNC_EXT_OFF & // don't synch with external clock T1_SOURCE_INT; // use the internal clock OpenTimer1( config, period ); return; } /***********************************************************************/ // setup ADC10 void adc_init(void){ unsigned int config1, config2, config3, configport, configscan; ADCON1bits.ADON = 0 ; // turn off ADC SetChanADC10( ADC_CH0_NEG_SAMPLEA_VREFN & // negative reference for channel 0 is VREF negative ADC_CH0_POS_SAMPLEA_AN3 // // ADC_CHX_NEG_SAMPLEA_VREFN & // negative reference for channel 1 is VREF negative // ADC_CHX_POS_SAMPLEA_AN3AN4AN5 ); ConfigIntADC10( ADC_INT_DISABLE ); // disable the interrupts config1 = ADC_MODULE_ON & //turn on ADC module ADC_IDLE_CONTINUE & // let it idle if not in use ADC_FORMAT_INTG & // unsigned integer format ADC_CLK_AUTO & // manual trigger source ADC_AUTO_SAMPLING_OFF & // do not continue sampling ADC_SAMPLE_SIMULTANEOUS & // sample both channels at the same time ADC_SAMP_ON; // enable sampling config2 = ADC_VREF_AVDD_AVSS & // voltage reference ADC_SCAN_OFF & // don't scan ADC_CONVERT_CH0 & // convert channel 0 ADC_SAMPLES_PER_INT_1 & // 1 samples per interupt ADC_ALT_BUF_OFF & // don't use the alternate buffer ADC_ALT_INPUT_OFF; // don't use an alternate input config3 = ADC_SAMPLE_TIME_2 & // auto sample time bits ADC_CONV_CLK_SYSTEM & // use the system clock ADC_CONV_CLK_13Tcy; // conversion clock speed (coeff of TCY is ADCS) configport = ENABLE_AN3_ANA; // parameters to be configured in the to ADPCFG configscan = SCAN_NONE; // scan select parameter for the ADCSSL register OpenADC10( config1, config2, config3, configport, configscan ); } /*****************************************************************/ // setup pwm void pwm_init(void){ unsigned int config1, config2, config3; unsigned int sptime; config1 = PWM_INT_DIS & // disable the interrupt PWM_FLTA_DIS_INT; // disable the interrupt on fault ConfigIntMCPWM( config1 ); config1 = PWM_EN & // enable the PWM module PWM_IPCLK_SCALE4 & // input prescaler set to 2 PWM_OP_SCALE1 & // post scalar set to 1 PWM_MOD_UPDN; // free running mode config2 = PWM_MOD1_IND & // pwm modules run independently PWM_MOD2_IND & PWM_MOD3_IND & PWM_MOD4_IND & PWM_PDIS1H & // disable 1 high PWM_PDIS2H & // disabale 2 high PWM_PDIS3H & // enable 3 high PWM_PDIS4H & // disable 4 high PWM_PDIS1L & // disable 1 low PWM_PDIS2L & // disable 2 low PWM_PDIS3L & // disable 3 low PWM_PDIS4L ; //disable 4 low config3 = PWM_UEN; // enable updates sptime = 0x0; OpenMCPWM( PERIOD, sptime, config1, config2, config3 ); } /*****************************************************************/ // setup the UART void uart1_init(void) { unsigned int config1, config2, ubrg; config1 = UART_EN & // enable the UART UART_IDLE_CON & // set idle mode UART_DIS_WAKE & // disable wake-up on start UART_DIS_LOOPBACK & // disable loopback UART_DIS_ABAUD & // diable autobaud rate detect UART_NO_PAR_8BIT & // no parity, 8 bits UART_1STOPBIT; // one stop bit config2 = UART_INT_TX_BUF_EMPTY & // interrupt anytime a buffer is empty UART_TX_PIN_NORMAL & // set transmit break pin UART_TX_ENABLE & // enable UART transmission UART_INT_RX_CHAR & // recieve interrupt mode selected UART_ADR_DETECT_DIS & // disable address detect UART_RX_OVERRUN_CLEAR; // overrun bit clear ubrg = 15; // 11520 baud OpenUART1( config1, config2, ubrg); } /*****************************************************************/ int main ( void ) { extern unsigned int AD_value; extern unsigned int GO; unsigned int dutycyclereg, dutycycle, period; char updatedisable; double scale, time, dt; int on; // set up the A/D parameters adc_init(); // set up the pwm // pwm_init(); // set up the uart uart1_init(); // set up the external interrupt // Init_INT4(); // disable updates updatedisable = 0; // get some scaling out of the way scale = ((double) MAX_DUTY)/1024.0; // initialize timer1 dt = 0.1; // the sampling inverval in seconds // dt = N*256/29,480,000; assuming a 256 prescalar. // so N = dt* 115156 period = (unsigned int) (dt*115156.0); if (period > 32768 ) { period = 32768; } Init_Timer1( period ); AD_value = 0; time = 0; on = 0; /********************* MAIN LOOP **********************/ while(1){ while(!GO ); GO = 0; time = time + dt; if (on == 0) { PORTE = 0b11111111; on = 1; } else { PORTE = 0b00000000; on = 0; } /* dutycycle = (unsigned int) ((double) AD_value)*scale; dutycyclereg = 4; SetDCMCPWM( dutycyclereg, dutycycle, updatedisable); */ printf("%8.4f \n", time); } }