-
Notifications
You must be signed in to change notification settings - Fork 0
/
can.c
152 lines (133 loc) · 4.98 KB
/
can.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
* can.c
*
* Created by SQ8KFH on 2014-08-15.
*
* Copyright (C) 2014-2020 Kamil Palkowski. All rights reserved.
*/
#include "can.h"
can_buf_t can_rx_buf[CAN_RX_BUF_SIZE];
volatile uint8_t can_rx_buf_top = 0;
volatile uint8_t can_rx_buf_bottom = 0;
can_buf_t can_tx_buf[CAN_TX_BUF_SIZE];
volatile uint8_t can_tx_buf_top = 0;
volatile uint8_t can_tx_buf_bottom = 0;
#if F_CPU == 8000000UL
static uint8_t can_bitrate_map[9][3] = {
{0x0e, 0x04, 0x13}, //S0 10Kbit //TODO: calculate
{0x0e, 0x04, 0x13}, //S1 20Kbit //TODO: calculate
{0x0e, 0x04, 0x13}, //S2 50Kbit //TODO: calculate
{0x12, 0x04, 0x13}, //S3 100Kbit
{0x0e, 0x04, 0x13}, //S4 125Kbit
{0x06, 0x04, 0x13}, //S5 250Kbit
{0x02, 0x04, 0x13}, //S6 500Kbit
{0x0e, 0x04, 0x13}, //S7 800Kbit //TODO: calculate
{0x00, 0x04, 0x12}, //S8 1Mbit
};
#else
#error "Please specify F_CPU"
#endif
ISR(CAN_INT_vect) {
uint8_t canhpmob = CANHPMOB;
uint8_t cangit = CANGIT;
if (canhpmob != 0xf0) {
uint8_t savecanpage = CANPAGE;
CANPAGE = canhpmob;
if (CANSTMOB & (1 << RXOK)) {
uint8_t next_rx_top = (uint8_t)((can_rx_buf_top + 1) & CAN_RX_BUF_INDEX_MASK);
if (next_rx_top != can_rx_buf_bottom) { //else drop frame
can_rx_buf[can_rx_buf_top].canidt1 = CANIDT1;
can_rx_buf[can_rx_buf_top].canidt2 = CANIDT2;
can_rx_buf[can_rx_buf_top].canidt3 = CANIDT3;
can_rx_buf[can_rx_buf_top].canidt4 = CANIDT4;
can_rx_buf[can_rx_buf_top].cancdmob = CANCDMOB & 0x1f;
for (uint8_t i = 0; i < 8; ++i) {
can_rx_buf[can_rx_buf_top].data[i] = CANMSG;
}
can_rx_buf_top = next_rx_top;
}
CANIDM1 = 0;
CANIDM2 = 0;
CANIDM3 = 0;
CANIDM4 = 0;
CANCDMOB = (1<<CONMOB1); //rx mob
}
else if (CANSTMOB & (1 << TXOK)) {
CANCDMOB = 0; //disable mob
if (can_tx_buf_bottom != can_tx_buf_top) {
CANSTMOB = 0x00; // Clear mob status register
CANIDT4 = can_tx_buf[can_tx_buf_bottom].canidt4;
CANIDT3 = can_tx_buf[can_tx_buf_bottom].canidt3;
CANIDT2 = can_tx_buf[can_tx_buf_bottom].canidt2;
CANIDT1 = can_tx_buf[can_tx_buf_bottom].canidt1;
for ( int8_t i = 0; i < 8; ++i ) {
CANMSG = can_tx_buf[can_tx_buf_bottom].data[i];
}
CANCDMOB = can_tx_buf[can_tx_buf_bottom].cancdmob | ( 1 << CONMOB0 ); // Enable transmission
can_tx_buf_bottom = (uint8_t)((can_tx_buf_bottom + 1u) & CAN_TX_BUF_INDEX_MASK);
}
}
CANSTMOB = 0x00; // Reset reason on selected channel
CANPAGE = savecanpage;
}
//other interrupt
CANGIT |= (cangit & 0x7f);
}
void CAN_init(uint8_t bitrate) {
CANGCON = ( 1 << SWRES ); // CAN reset
CANTCON = 0xff; // CAN timing prescaler
CANHPMOB = 0x00; // preprograowanie 4 najmlodszych bitow dla CANPAGE = CANHPMOB;
CANBT1 = can_bitrate_map[bitrate][0];
CANBT2 = can_bitrate_map[bitrate][1];
CANBT3 = can_bitrate_map[bitrate][2];
for ( uint8_t mob=0; mob<6; mob++ ) {
CANPAGE = ( mob << MOBNB0); // Selects Message Object 0-5
CANCDMOB = 0x00; // Disable mob
CANSTMOB = 0x00; // Clear mob status register;
}
for ( uint8_t mob=2; mob<6; mob++ ) {
CANPAGE = mob << MOBNB0;
CANIDM1 = 0;
CANIDM2 = 0;
CANIDM3 = 0;
CANIDM4 = 0;
CANCDMOB = (1<<CONMOB1); /*| (1<<IDE) | (8<<DLC0); *///rx mob
}
CANIE2 = ( 1 << IEMOB0 ) | ( 1 << IEMOB1 ) | ( 1 << IEMOB2 ) | ( 1 << IEMOB3 ) | ( 1 << IEMOB4 ) | ( 1 << IEMOB5 );
CANGIE = (1<<ENIT) |(1<<ENBOFF) | (1<<ENRX) | (1<<ENTX) | (1<<ENERR) | (1<<ENBX) | (1<<ENERG);
CANGCON = 1<<ENASTB;
}
void CAN_disable(void) {
CANGCON = (1 << SWRES); // CAN reset
}
uint8_t CAN_tx(can_buf_t *buf) {
if (!(CANGSTA & (1 << ENFG))) return 0; //bus disable
//while (1) {
if (!(CANEN2 & ( 1 << ENMOB0 ))) {
CANPAGE = 0 << MOBNB0;
//break;
}
else if (!(CANEN2 & ( 1 << ENMOB1 ))) {
CANPAGE = 1 << MOBNB0;
//break;
}
//}
else {
uint8_t next_top = (uint8_t)((can_tx_buf_top + 1u) & CAN_TX_BUF_INDEX_MASK);
if (next_top == can_tx_buf_bottom) return 0; //drop
//while(next_top == can_tx_buf_bottom); //tx buf full
can_tx_buf[can_tx_buf_top] = *buf;
can_tx_buf_top = next_top;
return 1;
}
CANSTMOB = 0x00; // Clear mob status register
CANIDT4 = buf->canidt4;
CANIDT3 = buf->canidt3;
CANIDT2 = buf->canidt2;
CANIDT1 = buf->canidt1;
for ( int8_t i = 0; i < 8; ++i ) {
CANMSG = buf->data[i];
}
CANCDMOB = buf->cancdmob | ( 1 << CONMOB0 ); // Enable transmission
return 1;
}