Guest User

Untitled

a guest
May 23rd, 2018
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.38 KB | None | 0 0
  1. /*
  2. * mega32m1_sleep.c
  3. *
  4. * Created: 17/05/2018 14:01:51
  5. * Author : Aner Torre
  6. *
  7. * Sleep modes test. The main purpose of this test is to demonstrate which sleep modes
  8. * can the CAN message RX interrupts wake the MCU from. Blinks a LED for 4 times
  9. * and enters sleep_mode until the MCU is waken by receiving CAN message RX interrupt
  10. *
  11. * The results show that CAN message received interrupts ( ISR(CAN_INT_vect) ) can ONLY
  12. * wake the MCU from SLEEP_MODE_IDLE.
  13. * Power consumptions (INCLUDING MCP2561 CAN transceiver):
  14. * - NORMAL FUNCTION: about 10 mA
  15. * - SLEEP_MODE_IDLE: about 9 mA
  16. * - SLEEP_MODE_PWR_DOWN: about 4.5 mA
  17. */
  18.  
  19. #ifndef F_CPU
  20. #define F_CPU 8000000UL
  21. #endif
  22.  
  23. #include <avr/interrupt.h>
  24. #include <avr/io.h>
  25. #include <avr/sleep.h>
  26. #include <stdbool.h>
  27. #include <stdint.h>
  28. #include <util/delay.h>
  29.  
  30. volatile bool msg_rcv = 0;
  31. volatile uint16_t id = 0;
  32. volatile uint8_t data[8];
  33.  
  34. ISR (CAN_INT_vect) {
  35. int8_t length, savecanpage;
  36.  
  37. savecanpage = CANPAGE; // Save current MOB
  38.  
  39. CANPAGE = CANHPMOB & 0xF0; // Selects MOB with highest priority interrupt
  40.  
  41. if (CANSTMOB & (1 << RXOK)) {
  42. // Interrupt caused by receive finished
  43. id = ((uint16_t)CANIDT2 >> 5) | ((uint16_t)CANIDT1 << 3); // considering 11 bit ID (CAN v2.0A)
  44. length = (CANCDMOB & 0x0F); // DLC, number of bytes to be received
  45. for (int8_t i = 0; i < length; i++) data[i] = CANMSG; // Get data, INDX auto increments CANMSG
  46.  
  47. CANCDMOB = ((1 << CONMOB1) | (0 << IDE) | (8 << DLC0)); // Enable Reception 11 bit IDE DLC8
  48.  
  49. msg_rcv = 1;
  50. }
  51.  
  52. CANSTMOB = 0x00; // Reset reason on selected channel
  53. CANPAGE = savecanpage; // Restore original MOB
  54. }
  55.  
  56. void chip_init(void) {
  57. // defining all pins as OUTPUT reduces power consumption
  58. DDRB = 0xFF;
  59. DDRC = 0xFF;
  60. DDRD = 0xFF;
  61. DDRE = 0xFF;
  62.  
  63. PORTB = 0xFE;
  64. PORTC = 0x00;
  65. PORTD = 0x00;
  66. PORTE = 0x00;
  67.  
  68. PRR = 0x00; // Individual peripheral clocks enabled
  69. }
  70.  
  71. void can_init(void) {
  72.  
  73. CANGCON = ( 1 << SWRES ); // Software reset
  74.  
  75. CANTCON = 0x00; // CAN timing prescaler set to 0;
  76.  
  77. // Set baud rate to 500 kbit/s (with 8Mhz internal osc)
  78. CANBT1 = 0x02;
  79. CANBT2 = 0x04;
  80. CANBT3 = 0x13;
  81.  
  82. for (int8_t mob = 0; mob < 6; mob++) {
  83. CANPAGE = (mob << 4); // Selects Message Object 0-5
  84. CANCDMOB = 0x00; // Disable mob
  85. CANSTMOB = 0x00; // Clear mob status register;
  86. }
  87.  
  88. CANPAGE = ( 1 << MOBNB0 ); // Select MOB1
  89. CANIE2 = ( 1 << IEMOB1 ); // Enable interrupts on MOB1 for reception and transmission
  90. CANGIE = ( 1 << ENIT ) | ( 1 << ENRX ) /*| ( 1 << ENTX )*/; // Enable interrupts ONLY on receive
  91.  
  92. // Filter all IDs not matching (all except 0x201)
  93. CANIDT1 = (uint8_t) (0x201 >> 3);
  94. CANIDT2 = (uint8_t) (0x201 << 5);
  95. CANIDT3 = 0x00;
  96. CANIDT4 = 0x00;
  97. // mask = 0b11111111111
  98. CANIDM1 = 0xFF >> 3;
  99. CANIDM2 = 0xFF << 5;
  100. CANIDM3 = 0x00;
  101. CANIDM4 = (1 << RTRMSK) | (1 << IDEMSK);
  102.  
  103. //CANCDMOB = ( 1 << CONMOB1) | ( 1 << IDE ) | ( 8 << DLC0); // Use this to enable reception 29 bit IDE DLC8 (CAN v2.0B)
  104. CANCDMOB = ( 1 << CONMOB1) | ( 0 << IDE ) | ( 8 << DLC0); // Use this to enable reception 11 bit IDE DLC8 (CAN v2.0A)
  105.  
  106. CANGCON |= (1 << LISTEN); // Put CAN in LISTEN mode (no ACK)
  107. CANGCON |= ( 1 << ENASTB ); // Enable mode. CAN channel enters in enable mode once 11 recessive bits have been read
  108.  
  109. sei();
  110.  
  111. }
  112.  
  113. int main(void) {
  114.  
  115. chip_init();
  116. can_init();
  117.  
  118. DDRB |= (1 << PB7);
  119.  
  120. while (1) {
  121. // Test different sleep modes
  122. // set_sleep_mode(SLEEP_MODE_IDLE);
  123. // sleep_mode();
  124. // interrupt_wait();
  125. //
  126. // set_sleep_mode(SLEEP_MODE_STANDBY);
  127. // sleep_mode();
  128. // interrupt_wait();
  129. //
  130. // /* Three times power down to differentiate */
  131. // set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  132. // sleep_mode();
  133. // set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  134. // sleep_mode();
  135. // set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  136. // sleep_mode();
  137. // interrupt_wait();
  138.  
  139. // Blink LED for (3 + 1) times and enter SLEEP_MODE_IDLE until CAN RX interrupt. Then, continue...
  140. for (uint8_t i = 0; i < 6; i++) {
  141. PORTB &= ~(1 << PB7);
  142. _delay_ms(1000);
  143. PORTB |= (1 << PB7);
  144. _delay_ms(1000);
  145. if (i == 3) {
  146. set_sleep_mode(SLEEP_MODE_IDLE);
  147. sleep_mode();
  148. }
  149. }
  150.  
  151. _delay_ms(9);
  152.  
  153. }
  154.  
  155. return(0);
  156.  
  157. }
Add Comment
Please, Sign In to add comment