|
1 /* |
|
2 This file is part of CanFestival, a library implementing CanOpen Stack. |
|
3 |
|
4 Copyright (C): Edouard TISSERANT and Francis DUPIN |
|
5 AVR Port: Andreas GLAUSER and Peter CHRISTEN |
|
6 |
|
7 See COPYING file for copyrights details. |
|
8 |
|
9 This library is free software; you can redistribute it and/or |
|
10 modify it under the terms of the GNU Lesser General Public |
|
11 License as published by the Free Software Foundation; either |
|
12 version 2.1 of the License, or (at your option) any later version. |
|
13 |
|
14 This library is distributed in the hope that it will be useful, |
|
15 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
17 Lesser General Public License for more details. |
|
18 |
|
19 You should have received a copy of the GNU Lesser General Public |
|
20 License along with this library; if not, write to the Free Software |
|
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
22 */ |
|
23 /****************************************************************************** |
|
24 Project description: |
|
25 Test projekt for a DS 401 slave, running on Atmel's STK500 with AT90CAN128 |
|
26 Short description: |
|
27 PORTA: Inputs (Keys, low active) |
|
28 PORTB: Outputs (LEDs, low active) |
|
29 PORTC: Node ID (1 BCD switch) |
|
30 |
|
31 ******************************************************************************/ |
|
32 #include "hardware.h" |
|
33 #include "canfestival.h" |
|
34 #include "can_AVR.h" |
|
35 #include "objdict.h" |
|
36 #include "ds401.h" |
|
37 |
|
38 |
|
39 unsigned char timer_interrupt = 0; // Set if timer interrupt eclapsed |
|
40 unsigned char inputs; |
|
41 |
|
42 // CAN |
|
43 unsigned char nodeID; |
|
44 unsigned char digital_input[1] = {0}; |
|
45 unsigned char digital_output[1] = {0}; |
|
46 |
|
47 static Message m = Message_Initializer; // contain a CAN message |
|
48 |
|
49 void sys_init(); |
|
50 |
|
51 // macros to handle the schedule timer |
|
52 #define sys_timer timer_interrupt |
|
53 #define reset_sys_timer() timer_interrupt = 0 |
|
54 #define CYCLE_TIME 1000 // Sample Timebase [us] |
|
55 |
|
56 int main(void) |
|
57 { |
|
58 sys_init(); // Initialize system |
|
59 canInit(CAN_BAUDRATE); // Initialize the CANopen bus |
|
60 initTimer(); // Start timer for the CANopen stack |
|
61 nodeID = read_bcd(); // Read node ID first |
|
62 setNodeId (&ObjDict_Data, nodeID); |
|
63 setState(&ObjDict_Data, Initialisation); // Init the state |
|
64 |
|
65 for(;;) // forever loop |
|
66 { |
|
67 if (sys_timer) // Cycle timer, invoke action on every time slice |
|
68 { |
|
69 reset_sys_timer(); // Reset timer |
|
70 digital_input[0] = get_inputs(); |
|
71 digital_input_handler(&ObjDict_Data, digital_input, sizeof(digital_input)); |
|
72 digital_output_handler(&ObjDict_Data, digital_output, sizeof(digital_output)); |
|
73 set_outputs(digital_output[0]); |
|
74 |
|
75 // Check if CAN address has been changed |
|
76 if(!( nodeID == read_bcd())) |
|
77 { |
|
78 nodeID = read_bcd(); // Save the new CAN adress |
|
79 setState(&ObjDict_Data, Stopped); // Stop the node, to change the node ID |
|
80 setNodeId(&ObjDict_Data, nodeID); // Now the CAN adress is changed |
|
81 setState(&ObjDict_Data, Pre_operational); // Set to Pre_operational, master must boot it again |
|
82 } |
|
83 } |
|
84 |
|
85 // a message was received pass it to the CANstack |
|
86 if (canReceive(&m)) // a message reveived |
|
87 canDispatch(&ObjDict_Data, &m); // process it |
|
88 else |
|
89 { |
|
90 // Enter sleep mode |
|
91 #ifdef WD_SLEEP // Watchdog and Sleep |
|
92 wdt_reset(); |
|
93 sleep_enable(); |
|
94 sleep_cpu(); |
|
95 #endif // Watchdog and Sleep |
|
96 } |
|
97 } |
|
98 } |
|
99 |
|
100 void sys_init() |
|
101 /****************************************************************************** |
|
102 Initialize the relays, the main states and the modbus protocol stack. |
|
103 INPUT LOCK_STATES *lock_states |
|
104 OUTPUT void |
|
105 ******************************************************************************/ |
|
106 { |
|
107 OSCCAL = 0x43; |
|
108 |
|
109 PORTA = 0xFF; // Inputs (Keys, low active) with pullup |
|
110 DDRA = 0x00; // |
|
111 PORTB = 0xFF; // Outputs (LEDs, low active) all 1 |
|
112 DDRB = 0xFF; // |
|
113 PORTC = 0xFF; // 1 BCD switch with pullup |
|
114 DDRC = 0x00; // |
|
115 PORTD = 0x2C; // 2xCOM, unused, CAN, unused |
|
116 DDRD = 0x2A; // All init 0 or without pullup |
|
117 PORTE = 0x00; // Output |
|
118 DDRE = 0x3C; // 2x not used, 2x not used |
|
119 PORTF = 0x00; // Not used |
|
120 DDRF = 0xFF; // All output |
|
121 PORTG = 0x00; // Not used |
|
122 DDRG = 0x1F; // Output for debug (only 5 pins) |
|
123 |
|
124 // Set timer 0 for main schedule time |
|
125 TCCR0A |= 1 << WGM01 | 1 << CS01 | 1 << CS00;// Timer 0 CTC , Timer 0 mit CK/64 starten |
|
126 TIMSK0 = 1 << OCIE0A; // Timer Interrupts: Timer 0 Compare |
|
127 OCR0A = (unsigned char)(F_CPU / 64 * CYCLE_TIME/1000000 - 1); // Reloadvalue for timer 0 |
|
128 #ifdef WD_SLEEP // Watchdog and Sleep |
|
129 wdt_reset(); |
|
130 wdt_enable(WDTO_15MS); // Watchdogtimer start with 16 ms timeout |
|
131 #endif // Watchdog and Sleep |
|
132 sei(); // Enable Interrupts |
|
133 } |
|
134 |
|
135 |
|
136 #ifdef __IAR_SYSTEMS_ICC__ |
|
137 #pragma type_attribute = __interrupt |
|
138 #pragma vector=TIMER0_COMP_vect |
|
139 void TIMER0_COMP_interrupt(void) |
|
140 #else // GCC |
|
141 ISR(TIMER0_COMP_vect) |
|
142 #endif // GCC |
|
143 /****************************************************************************** |
|
144 Interruptserviceroutine Timer 2 Compare A for the main cycle |
|
145 ******************************************************************************/ |
|
146 |
|
147 { |
|
148 timer_interrupt = 1; // Set flag |
|
149 } |