Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * mega32m1_sleep.c
- *
- * Created: 17/05/2018 14:01:51
- * Author : Aner Torre
- *
- * Sleep modes test. The main purpose of this test is to demonstrate which sleep modes
- * can the CAN message RX interrupts wake the MCU from. Blinks a LED for 4 times
- * and enters sleep_mode until the MCU is waken by receiving CAN message RX interrupt
- *
- * The results show that CAN message received interrupts ( ISR(CAN_INT_vect) ) can ONLY
- * wake the MCU from SLEEP_MODE_IDLE.
- * Power consumptions (INCLUDING MCP2561 CAN transceiver):
- * - NORMAL FUNCTION: about 10 mA
- * - SLEEP_MODE_IDLE: about 9 mA
- * - SLEEP_MODE_PWR_DOWN: about 4.5 mA
- */
- #ifndef F_CPU
- #define F_CPU 8000000UL
- #endif
- #include <avr/interrupt.h>
- #include <avr/io.h>
- #include <avr/sleep.h>
- #include <stdbool.h>
- #include <stdint.h>
- #include <util/delay.h>
- volatile bool msg_rcv = 0;
- volatile uint16_t id = 0;
- volatile uint8_t data[8];
- ISR (CAN_INT_vect) {
- int8_t length, savecanpage;
- savecanpage = CANPAGE; // Save current MOB
- CANPAGE = CANHPMOB & 0xF0; // Selects MOB with highest priority interrupt
- if (CANSTMOB & (1 << RXOK)) {
- // Interrupt caused by receive finished
- id = ((uint16_t)CANIDT2 >> 5) | ((uint16_t)CANIDT1 << 3); // considering 11 bit ID (CAN v2.0A)
- length = (CANCDMOB & 0x0F); // DLC, number of bytes to be received
- for (int8_t i = 0; i < length; i++) data[i] = CANMSG; // Get data, INDX auto increments CANMSG
- CANCDMOB = ((1 << CONMOB1) | (0 << IDE) | (8 << DLC0)); // Enable Reception 11 bit IDE DLC8
- msg_rcv = 1;
- }
- CANSTMOB = 0x00; // Reset reason on selected channel
- CANPAGE = savecanpage; // Restore original MOB
- }
- void chip_init(void) {
- // defining all pins as OUTPUT reduces power consumption
- DDRB = 0xFF;
- DDRC = 0xFF;
- DDRD = 0xFF;
- DDRE = 0xFF;
- PORTB = 0xFE;
- PORTC = 0x00;
- PORTD = 0x00;
- PORTE = 0x00;
- PRR = 0x00; // Individual peripheral clocks enabled
- }
- void can_init(void) {
- CANGCON = ( 1 << SWRES ); // Software reset
- CANTCON = 0x00; // CAN timing prescaler set to 0;
- // Set baud rate to 500 kbit/s (with 8Mhz internal osc)
- CANBT1 = 0x02;
- CANBT2 = 0x04;
- CANBT3 = 0x13;
- for (int8_t mob = 0; mob < 6; mob++) {
- CANPAGE = (mob << 4); // Selects Message Object 0-5
- CANCDMOB = 0x00; // Disable mob
- CANSTMOB = 0x00; // Clear mob status register;
- }
- CANPAGE = ( 1 << MOBNB0 ); // Select MOB1
- CANIE2 = ( 1 << IEMOB1 ); // Enable interrupts on MOB1 for reception and transmission
- CANGIE = ( 1 << ENIT ) | ( 1 << ENRX ) /*| ( 1 << ENTX )*/; // Enable interrupts ONLY on receive
- // Filter all IDs not matching (all except 0x201)
- CANIDT1 = (uint8_t) (0x201 >> 3);
- CANIDT2 = (uint8_t) (0x201 << 5);
- CANIDT3 = 0x00;
- CANIDT4 = 0x00;
- // mask = 0b11111111111
- CANIDM1 = 0xFF >> 3;
- CANIDM2 = 0xFF << 5;
- CANIDM3 = 0x00;
- CANIDM4 = (1 << RTRMSK) | (1 << IDEMSK);
- //CANCDMOB = ( 1 << CONMOB1) | ( 1 << IDE ) | ( 8 << DLC0); // Use this to enable reception 29 bit IDE DLC8 (CAN v2.0B)
- CANCDMOB = ( 1 << CONMOB1) | ( 0 << IDE ) | ( 8 << DLC0); // Use this to enable reception 11 bit IDE DLC8 (CAN v2.0A)
- CANGCON |= (1 << LISTEN); // Put CAN in LISTEN mode (no ACK)
- CANGCON |= ( 1 << ENASTB ); // Enable mode. CAN channel enters in enable mode once 11 recessive bits have been read
- sei();
- }
- int main(void) {
- chip_init();
- can_init();
- DDRB |= (1 << PB7);
- while (1) {
- // Test different sleep modes
- // set_sleep_mode(SLEEP_MODE_IDLE);
- // sleep_mode();
- // interrupt_wait();
- //
- // set_sleep_mode(SLEEP_MODE_STANDBY);
- // sleep_mode();
- // interrupt_wait();
- //
- // /* Three times power down to differentiate */
- // set_sleep_mode(SLEEP_MODE_PWR_DOWN);
- // sleep_mode();
- // set_sleep_mode(SLEEP_MODE_PWR_DOWN);
- // sleep_mode();
- // set_sleep_mode(SLEEP_MODE_PWR_DOWN);
- // sleep_mode();
- // interrupt_wait();
- // Blink LED for (3 + 1) times and enter SLEEP_MODE_IDLE until CAN RX interrupt. Then, continue...
- for (uint8_t i = 0; i < 6; i++) {
- PORTB &= ~(1 << PB7);
- _delay_ms(1000);
- PORTB |= (1 << PB7);
- _delay_ms(1000);
- if (i == 3) {
- set_sleep_mode(SLEEP_MODE_IDLE);
- sleep_mode();
- }
- }
- _delay_ms(9);
- }
- return(0);
- }
Add Comment
Please, Sign In to add comment