timer.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * =====================================================================================
  3. *
  4. * .d8888b 88888b. .d88b. .d8888b 888d888 8888b. 88888b.d88b.
  5. * 88K 888 "88b d8P Y8b 88K 888P" "88b 888 "888 "88b
  6. * "Y8888b. 888 888 88888888 "Y8888b. 888 .d888888 888 888 888
  7. * X88 888 888 Y8b. X88 888 888 888 888 888 888
  8. * 88888P' 888 888 "Y8888 88888P' 888 "Y888888 888 888 888
  9. *
  10. * www.optixx.org
  11. *
  12. *
  13. * Version: 1.0
  14. * Created: 07/21/2009 03:32:16 PM
  15. * Author: david@optixx.org
  16. *
  17. * =====================================================================================
  18. */
  19. #include <stdint.h>
  20. #include <stdio.h>
  21. #include <avr/io.h>
  22. #include <avr/io.h>
  23. #include <avr/interrupt.h> /* for sei() */
  24. #include "debug.h"
  25. #ifndef OCR1A
  26. #define OCR1A OCR1 // 2313 support
  27. #endif
  28. #ifndef WGM12
  29. #define WGM12 CTC1 // 2313 support
  30. #endif
  31. //#define XTAL 11059201L // nominal value
  32. #define XTAL 20000000UL
  33. #define DEBOUNCE 500L // debounce clock (256Hz = 4msec)
  34. #define uint8_t unsigned char
  35. #define uint unsigned int
  36. uint16_t prescaler;
  37. uint16_t volatile second; // count seconds
  38. ISR (SIG_OUTPUT_COMPARE1A)
  39. {
  40. #if XTAL % DEBOUNCE // bei rest
  41. OCR1A = 20000000UL / DEBOUNCE - 1; // compare DEBOUNCE - 1 times
  42. #endif
  43. if( --prescaler == 0 ){
  44. prescaler = (uint16_t)DEBOUNCE;
  45. second++; // exact one second over
  46. #if XTAL % DEBOUNCE // handle remainder
  47. OCR1A = XTAL / DEBOUNCE + XTAL % DEBOUNCE - 1; // compare once per second
  48. #endif
  49. }
  50. }
  51. void timer_start( void )
  52. {
  53. TCCR1B = (1<<WGM12) | (1<<CS10); // divide by 1
  54. // clear on compare
  55. OCR1A = XTAL / DEBOUNCE - 1UL; // Output Compare Register
  56. TCNT1 = 0; // Timmer startet mit 0
  57. second = 0;
  58. prescaler = (uint16_t)DEBOUNCE; //software teiler
  59. TIMSK1 = 1<<OCIE1A; // beim Vergleichswertes Compare Match
  60. // Interrupt (SIG_OUTPUT_COMPARE1A)
  61. sei();
  62. }
  63. double timer_stop(void)
  64. {
  65. double t = ((double)(DEBOUNCE - prescaler) / DEBOUNCE ) + second;
  66. return t;
  67. }