Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * *
- * This code is based on publicly available code available at the following sources:
- * http://pastebin.com/NQtbVCFh
- * http://forums.leaflabs.com/topic.php?id=1038
- *
- * The above sources provided period measurement guidance for generic timer
- * The following uses advanced timer capabilities such as timer with slave and PWM input mode to measure period and duty cycle
- */
- #include <timer.h>
- // initialize global variables
- int periodvalue = 0;
- int dutycyclevalue = 0;
- int count = 0;
- int overflow_flag = 0;
- HardwareTimer timer1 = HardwareTimer(1);
- //quick method to return if there's anyone on the other end of the serialusb link yet.
- boolean isConnected(){
- return (SerialUSB.isConnected() && (SerialUSB.getDTR() || SerialUSB.getRTS()));
- }
- void setup()
- {
- SerialUSB.begin();
- while(!isConnected()); //wait till console attaches.
- SerialUSB.println("Hello!");
- //Setup Timer1 Channel 1 (pin 6) as an input
- pinMode(6, INPUT);
- //Configure pin 7 as an output (100 Hz 50% duty cycle with be genaerted and outputed pin 7. A jumper from pin 7 to pin 6 will be applied.
- pinMode(7, OUTPUT);
- // set up advanced timer capabilities
- setup_timer();
- }
- void __measurePulse_irq()
- {
- //For some reason, the interrupt is triggered as soon as
- //the device is turned on. This gets around that bug.
- // came with sample code - probably used because pulse may be in unknown state
- if( count == 0 )
- return;
- else {
- if(~overflow_flag) {
- periodvalue = TIMER1_BASE->CCR1; //read the captured value - period defined from pulse going up to next cycle where pulse goes high. CCR1 contains period count
- }
- else {
- periodvalue = 0;
- overflow_flag = 0;
- }
- timer1.setCount(0); //Zero timer
- }
- }
- void __measureDutyCycle_irq()
- {
- //For some reason, the interrupt is triggred as soon as
- //the device is turned on. This gets around that bug.
- if( count == 0 )
- return;
- else {
- if(~overflow_flag) {
- dutycyclevalue = TIMER1_BASE->CCR2; //read the captured value - dutycycle count defined from pulse going up to pulse going down. CCR2 contains duty cycle count
- }
- else {
- dutycyclevalue = 0;
- overflow_flag = 0;
- }
- }
- }
- // overflow irq accounts for when the counter overflows. overflow is defined in this case as 65535 (2^16- 1). should not be getting overflow.
- void handle_overflow() {
- overflow_flag = 1;
- }
- void loop() {
- //Display the counter values (period and duty cycle) very 500 mS
- if( count == 100 ) {
- //delay(500);
- SerialUSB.print("Period: ");
- SerialUSB.println(periodvalue);
- SerialUSB.print("Duty Cycle: ");
- SerialUSB.println(dutycyclevalue); //value = 0;
- count = 0;
- }
- //Pulse pin 7 at a rate of 100 Hz @ 50% DC - this is the PWM signal with 100Hz and 50% duty cycle.
- digitalWrite(7, HIGH);
- delay(5);
- digitalWrite(7, LOW);
- delay(5);
- count++;
- }
- //Halt processor and flash LED - used for debugging - code that calls this function is currently not used - can be removed.
- void HaltAll(void) {
- //Timer1.pause();
- timer1.pause();
- pinMode(BOARD_LED_PIN, OUTPUT);
- while(1) {
- toggleLED();
- delay(1000);
- }
- }
- // configure timer1 which is an advanced timer wuth a slave to measure period and duty cycle.
- void setup_timer(void) {
- //Create a pointer to the timer (why?)
- timer_dev *t = TIMER1;
- //Initialize timer
- timer1.pause();
- /*
- A prescaler of 288 means that at 72MHz, I get the following:
- 100 Hz = 2510
- 10 Hz = 25084
- */
- timer1.setPrescaleFactor(288);
- timer1.setOverflow(65535);
- timer1.setCount(0);
- //New code to set overflow timer
- timer1.setMode(3, TIMER_OUTPUT_COMPARE); //Set this channel to compare
- timer1.setCompare(3, 65534); //Set the compare for the channel to the overflow value
- timer1.attachInterrupt(3, handle_overflow); //Assign the interrupt handler
- timer1.refresh();
- //Create a pointer to the timer registers (why?)
- timer_reg_map r = t->regs;
- //capture compare regs TIMx_CCRx used to hold val after a transition on corresponding ICx
- //when cap occurs, flag CCXIF (TIMx_SR register) is set,
- //and interrupt, or dma req can be sent if they are enabled.
- //if cap occurs while flag is already high CCxOF (overcapture) flag is set..
- //CCIX can be cleared by writing 0, or by reading the capped data from TIMx_CCRx
- //CCxOF is cleared by writing 0 to it.
- //Capture/Compare 1 Selection
- // set CC1S bits to 01 in the capture compare mode register.
- // 01 selects TI1 as the input to use. (page 336 stm32 reference)
- // (assuming here that TI1 is D6, according to maple master pin map)
- //CC1S bits are bits 0,1
- bitSet(r.adv->CCMR1, 0);
- bitClear(r.adv->CCMR1, 1);
- //Input Capture 1 Filter.
- // need to set IC1F bits according to a table saying how long
- // we should wait for a signal to be 'stable' to validate a transition
- // on the input.
- // (page 336 stm32 reference)
- //IC1F bits are bits 7,6,5,4
- bitClear(r.adv->CCMR1, 7);
- bitClear(r.adv->CCMR1, 6);
- bitSet(r.adv->CCMR1, 5);
- bitSet(r.adv->CCMR1, 4);
- //sort out the input capture prescaler..
- //00 no prescaler.. capture is done as soon as edge is detected
- bitClear(r.adv->CCMR1, 3);
- bitClear(r.adv->CCMR1, 2);
- //select the edge for the transition on TI1 channel using CC1P in CCER
- //CC1P is bit 1 of CCER (page 339)
- // 0 = rising
- // 1 = falling
- bitClear(r.adv->CCER,1);
- //Capture/Compare 1 Selection of down part of the pulse on TI1
- // set CC2S bits to 10 in the capture compare mode register.
- // 01 selects TI1 as the input to use. (page 336 stm32 reference)
- // (assuming here that TI1 is D6, according to maple master pin map)
- //CC2S bits are bits 8,9
- bitSet(r.adv->CCMR1, 9);
- bitClear(r.adv->CCMR1, 8);
- //select the edge for the transition on TI1 channel using CC2P in CCER
- //CC2P is bit 5 of CCER (page 339)
- // 0 = active high
- // 1 = active low
- bitSet(r.adv->CCER,5);
- //select filtered trigger option: TS bits are set 101 in SMCR
- // seelects the trigger input to be used to synchronize counter
- // in this case a filtered TI1 (page 328)
- bitSet(r.adv->SMCR,6);
- bitClear(r.adv->SMCR,5);
- bitSet(r.adv->SMCR,4);
- //select slave mode selection: SMS bits are set 100 in SMCR
- // configure slave mode in reset mode (page 329)
- bitSet(r.adv->SMCR,2);
- bitClear(r.adv->SMCR,1);
- bitClear(r.adv->SMCR,0);
- //set the CC1E bit to enable capture from the counter.
- //CCE1 is bit 0 of CCER (page 339)
- //Enable capture
- bitSet(r.adv->CCER,0);
- //set the CC2E bit to enable capture from the counter.
- //CCE2 is bit 4 of CCER (page 339)
- bitSet(r.adv->CCER,4);
- // attach interrupts for when pulse goes high for period measurement and pulse goes low for duty cycle measurement
- timer1.attachInterrupt(1, __measurePulse_irq);
- timer1.attachInterrupt(2, __measureDutyCycle_irq);
- //timer_resume(TIMER4);
- timer1.resume();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement