Subversion Repositories HomeAutomation

Rev

Rev 29 | Blame | Last modification | View Log | SVN | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Controller Area Network (CAN) Demo-Application
  4.  * Atmel AVR with Microchip MCP2515
  5.  *
  6.  * Copyright (C) 2005 Martin THOMAS, Kaiserslautern, Germany
  7.  * <eversmith@heizung-thomas.de>
  8.  * http://www.siwawi.arubi.uni-kl.de/avr_projects
  9.  *
  10.  *****************************************************************************
  11.  *
  12.  * File    : main.c
  13.  * Version : 0.9
  14.  *
  15.  * Summary : Application Entry
  16.  *           Test-Platform: Atmel ATmega + Microchip MCP2515
  17.  *           Here the MCP2515 is clocked by the AVR (see clock_init()).
  18.  *
  19.  * This application uses Peter Fleury's free AVR-U(S)ART library which
  20.  * has been slightly extended. See comments in uart.c.
  21.  *
  22.  *****************************************************************************/
  23.  
  24. #include <avr/io.h>
  25. #include <avr/interrupt.h>
  26. #include <avr/wdt.h>
  27. #include <avr/eeprom.h>
  28.  
  29. #include "uart.h"
  30. #include "spi.h"
  31. #include "can.h"
  32. #include "delay.h"
  33. #include "termio.h"
  34. #include "terminal.h"
  35. #include "gpio.h"
  36. #include "timebase.h"
  37. #include "debughelper.h"
  38.  
  39. #define VERBOSE (1)
  40.  
  41. #define OSCAL_READEEPROM (1)
  42.  
  43. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__)
  44. #define OSCAL_EEPROMADDR ((void*)0x1ff)
  45. #elif defined(__AVR_ATmega32__)
  46. #define OSCAL_EEPROMADDR ((void*)0x3ff)
  47. #else
  48. #error "eeprom addr. undefined for this target"
  49. #endif
  50.  
  51. #define OSCAL_VALUE (0xA5)
  52.  
  53. #define BAUD 19200
  54.  
  55. #define AUTOSENDPORT PORTD
  56. #define AUTOSENDDDR  DDRD
  57. #define AUTOSENDPIN  PIND
  58. #define AUTOSENDBIT  PD7
  59.  
  60. #if 0
  61. void clock_init_tc2(void)
  62. // to clock the MCP2515
  63. // - CTC Mode of Timer-Counter 2
  64. // - Freq at OC2 (datasheet): f=f_c/(2*N*(1+OCR2))
  65. //   with: f_c=system clock=8MHz, N=prescaler=1, OCR2=0 -> 4MHz @ Pin D7
  66. {
  67.     // set OC2-Pin (PD7 on ATmega16) as output
  68.     DDRD |= _BV(DDD7);
  69.     // CTC limit in OCR2
  70.     OCR2=0;
  71.     // Clear Timer on Compare Match (CTC) mode; toogle OC2(PD7) on compare match;
  72.     //  clock select (timer2 prescaler) to clk/1 (no prescaling CS20=1)
  73.     TCCR2=_BV(WGM21)|_BV(COM20)|_BV(CS20);
  74. }
  75. #endif
  76.  
  77. void clock_init_tc1a(void)
  78. // to clock the MCP2515 on Mega8/Mega32
  79. // - CTC Mode of Timer-Counter 1 use OC1A as clock-pin
  80. // - Freq at OC2 (datasheet): f=f_c/(2*N*(1+OCR2))
  81. //   with: f_c=system clock=8MHz, N=prescaler=1, OCR1A=0 -> 4MHz
  82. //   @ Pin B1 Mega8
  83. //   @ Pin D5 Mega32
  84. {
  85.     #if defined(__AVR_ATmega8__)
  86.     // set OC2-Pin (PB1 on ATmega8) as output
  87.     DDRB |= _BV(DDB1);
  88.     #elif defined(__AVR_ATmega32__) || defined(__AVR_ATmega16__)
  89.     // set OC2-Pin (PD5 on ATmega32) as output
  90.     DDRD |= _BV(DDD5);
  91.     #else
  92.     #error "OCR1A pin undefined for this target"
  93.     #endif
  94.    
  95.     // CTC limit in OCR1A
  96.     OCR1A=0;
  97.     // Clear Timer on Compare Match (CTC) mode; toogle OC1A(PB1) on compare match;
  98.     TCCR1A=_BV(COM1A0);
  99.     // clock select (timer2 prescaler)
  100.     TCCR1B=_BV(CS10)|_BV(WGM12); // to clk/1 (no prescaling CS10=1)
  101. }
  102.  
  103. static void process_CANMessages(void)
  104. {
  105.     CanMessage msg;
  106.     uint8_t data2;
  107.  
  108. #ifdef VERBOSE
  109.     term_puts_P("AutoProcessing\n");
  110. #endif
  111.     while ( can_readMessage(&msg) == CAN_OK ) {
  112.         data2 = msg.dta[2];
  113.         if ( data2<3 ) {
  114.             gpio_toggle_led( (1<<data2) );
  115. #ifdef VERBOSE
  116.             Debug_ByteToUart_P("data2",data2);
  117. #endif
  118.         }
  119.     }  
  120. }
  121.  
  122. int main(void)
  123. {
  124.     uint8_t res, flag;
  125.     uint8_t shellstate;
  126.     uint16_t timebuf;
  127.  
  128. #if OSCAL_READEEPROM
  129.     res = eeprom_read_byte(OSCAL_EEPROMADDR);
  130.     if (res != 0xff) OSCCAL = res;
  131.     else OSCCAL = OSCAL_VALUE; // take default from define
  132. #else
  133.     OSCCAL = OSCAL_VALUE;
  134. #endif
  135.    
  136.     gpio_init();
  137.     gpio_set_led(LED1);
  138.    
  139.     timebase_init();
  140.    
  141.     uart_init((UART_BAUD_SELECT((BAUD),F_OSC)));
  142.    
  143.     sei();
  144.    
  145.     term_puts_P( "\n\nMCP2515 Interface Demo  (c) Martin Thomas\n" );
  146.     Debug_ByteToUart_P("OSCCAL", OSCCAL);
  147.    
  148.     term_puts_P("\nSetting up MCP clock to FOSC/2\n");
  149.     clock_init_tc1a();  // init MCP2515 clock-source (=AVR FOSC/2)
  150.     // old:  clock_init(); */
  151.    
  152.     term_puts_P("SPI init\n");
  153.     spi_init();     // init SPI-Interface (as "Master")
  154.    
  155.     term_puts_P("CAN init ");
  156.     // res = can_init(CAN_125KBPS);
  157.     res = can_init(CAN_20KBPS);
  158.     if (res == CAN_OK) term_puts_P("- OK\n");
  159.     else term_puts_P("- FAIL\n");
  160.    
  161.    
  162.     term_puts_P("Autosend (\"Autosendbit\"-State) : ");
  163.     AUTOSENDDDR &= ~(1<<AUTOSENDBIT); // as input
  164.     AUTOSENDPORT |= (1<<AUTOSENDBIT); // int pullup on
  165.     if ( AUTOSENDPIN & (1<<AUTOSENDBIT) ) {
  166.         gTimedSend = CANAUTOOFF;
  167.         term_puts_P("off");
  168.     }
  169.     else {
  170.         gTimedSend = CANAUTOON;
  171.         term_puts_P("on");
  172.     }
  173.     term_puts_P("\n");
  174.    
  175.     can_debug1();
  176.    
  177.     shellstate = COMMANDSHELL_MODEINIT;
  178.    
  179.     flag = 0;
  180.     timebuf = timebase_actTime();
  181.    
  182. #if 0
  183.     for (;;) {
  184.         if (timebase_passedTimeMS(timebuf)>=1000) {
  185.             timebuf = timebase_actTime();
  186.             term_puts_P("(.)");
  187.         }
  188.     }
  189. #endif
  190.    
  191.     for (;;) {
  192.         CommandShell(&shellstate);
  193.         if ( shellstate == COMMANDSHELL_MODEEXIT ) {
  194.             term_puts_P("I have no operation system to exit to :-( -> WD-Reset");
  195.             wdt_enable ( WDTO_500MS );
  196.             while(1);
  197.         }
  198.        
  199.         if ( ( can_checkReceive() == CAN_MSGAVAIL ) ) {
  200.             if (!flag) {
  201. #ifdef VERBOSE
  202.                 term_puts_P("\nAt least one CAN-Message available!\n");
  203.                 shellstate = COMMANDSHELL_REDRAW;
  204. #endif
  205.                 flag = 1;
  206.             }
  207.             if ( gCANAutoProcess == CANAUTOON ) {
  208.                 process_CANMessages();
  209. #ifdef VERBOSE
  210.                 shellstate = COMMANDSHELL_REDRAW;
  211. #endif
  212.             }
  213.         }
  214.         else {
  215.             flag = 0;
  216.         }
  217.        
  218.         if (timebase_passedTimeMS(timebuf)>=1000) {
  219.             timebuf = timebase_actTime();
  220.             if (gTimedSend == CANAUTOON) {
  221.                 if ( can_testTransmit(CAN_STDID, 1) != CAN_OK ) {
  222.                     term_puts_P("\nAuto-Transmit (debug) failed\n");
  223.                     can_dumpStatus();
  224.                     shellstate = COMMANDSHELL_REDRAW;
  225.                 }
  226.             }
  227.             if ( can_checkError() != CAN_OK ) {
  228.                 can_dumpStatus();
  229.             }
  230.         }
  231.        
  232.         // else term_puts_P("Checking\n");
  233.     }
  234.    
  235.     return 0;
  236. }
  237.