Subversion Repositories HomeAutomation

Rev

Rev 29 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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