📄 at90can.c
字号:
// ----------------------------------------------------------------------------/* * Copyright (c) 2007 Fabian Greif, Roboterclub Aachen e.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: at90can.c 6837 2008-11-16 19:05:15Z fabian $ */// ----------------------------------------------------------------------------#include "at90can_private.h"#ifdef SUPPORT_FOR_AT90CAN__#include <avr/pgmspace.h>#include "can_buffer.h"
// ----------------------------------------------------------------------------prog_char _at90can_cnf[8][3] = { // 10 kbps { 0x7E, 0x6E, 0x7F }, // 20 kbps { 0x62, 0x0C, 0x37 }, // 50 kbps { 0x26, 0x0C, 0x37 }, // 100 kbps { 0x12, 0x0C, 0x37 }, // 125 kbps { 0x0E, 0x0C, 0x37 }, // 250 kbps { 0x06, 0x0C, 0x37 }, // 500 kbps { 0x02, 0x0C, 0x37 }, // 1 Mbps { 0x00, 0x0C, 0x37 }};// ----------------------------------------------------------------------------#if CAN_RX_BUFFER_SIZE > 0can_buffer_t can_rx_buffer;can_t can_rx_list[CAN_RX_BUFFER_SIZE];#elsevolatile uint8_t _messages_waiting;#endif#if CAN_TX_BUFFER_SIZE > 0can_buffer_t can_tx_buffer;can_t can_tx_list[CAN_TX_BUFFER_SIZE];volatile uint8_t _transmission_in_progress = 0;#elsevolatile uint8_t _free_buffer; //!< Stores the numer of currently free MObs#endif// ----------------------------------------------------------------------------// get next free MObuint8_t _find_free_mob(void){ #if CAN_TX_BUFFER_SIZE == 0 if (_free_buffer == 0) return 0xff; #elif CAN_FORCE_TX_ORDER if (_transmission_in_progress) return 0xff; #endif uint8_t i; for (i = 0;i < 15;i++) { // load MOb page CANPAGE = i << 4; // check if MOb is in use if ((CANCDMOB & ((1 << CONMOB1) | (1 << CONMOB0))) == 0) return i; } return 0xff;}// ----------------------------------------------------------------------------// disable interrupt of corresponding MObvoid _disable_mob_interrupt(uint8_t mob){ if (mob < 8) CANIE2 &= ~(1 << mob); else CANIE1 &= ~(1 << (mob - 8));}// ----------------------------------------------------------------------------// enable interrupt of corresponding MObvoid _enable_mob_interrupt(uint8_t mob){ if (mob < 8) CANIE2 |= (1 << mob); else CANIE1 |= (1 << (mob - 8));}// ----------------------------------------------------------------------------bool at90can_init(uint8_t bitrate){ if (bitrate >= 8) return false; // switch CAN controller to reset mode CANGCON |= (1 << SWRES); // set CAN Bit Timing // (see datasheet page 260) CANBT1 = pgm_read_byte(&_at90can_cnf[bitrate][0]); CANBT2 = pgm_read_byte(&_at90can_cnf[bitrate][1]); CANBT3 = pgm_read_byte(&_at90can_cnf[bitrate][2]); // activate CAN transmit- and receive-interrupt CANGIT = 0; CANGIE = (1 << ENIT) | (1 << ENRX) | (1 << ENTX); // set timer prescaler to 199 which results in a timer // frequency of 10 kHz (at 16 MHz) CANTCON = 199; // disable all filters at90can_disable_filter( 0xff ); #if CAN_RX_BUFFER_SIZE > 0 can_buffer_init( &can_rx_buffer, CAN_RX_BUFFER_SIZE, can_rx_list ); #endif #if CAN_TX_BUFFER_SIZE > 0 can_buffer_init( &can_tx_buffer, CAN_TX_BUFFER_SIZE, can_tx_list ); #endif // activate CAN controller CANGCON = (1 << ENASTB); return true;}// ----------------------------------------------------------------------------// The CANPAGE register have to be restored after usage, otherwise it// could cause trouble in the application programm.ISR(CANIT_vect){ uint8_t canpage; uint8_t mob; if ((CANHPMOB & 0xF0) != 0xF0) { // save MOb page register canpage = CANPAGE; // select MOb page with the highest priority CANPAGE = CANHPMOB & 0xF0; mob = (CANHPMOB >> 4); // a interrupt is only generated if a message was transmitted or received if (CANSTMOB & (1 << TXOK)) { // clear MOb CANSTMOB &= 0; CANCDMOB = 0; #if CAN_TX_BUFFER_SIZE > 0 can_t *buf = can_buffer_get_dequeue_ptr(&can_tx_buffer); // check if there are any another messages waiting if (buf != NULL) { at90can_copy_message_to_mob( buf ); can_buffer_dequeue(&can_tx_buffer); // enable transmission CANCDMOB |= (1<<CONMOB0); } else { // buffer underflow => no more messages to send _disable_mob_interrupt(mob); _transmission_in_progress = 0; } #else _free_buffer++; // reset interrupt if (mob < 8) CANIE2 &= ~(1 << mob); else CANIE1 &= ~(1 << (mob - 8)); #endif CAN_INDICATE_TX_TRAFFIC_FUNCTION; } else { // a message was received successfully #if CAN_RX_BUFFER_SIZE > 0 can_t *buf = can_buffer_get_enqueue_ptr(&can_rx_buffer); if (buf != NULL) { // read message at90can_copy_mob_to_message( buf ); // push it to the list can_buffer_enqueue(&can_rx_buffer); } else { // buffer overflow => reject message // FIXME inform the user } // clear flags CANSTMOB &= 0; CANCDMOB = (1 << CONMOB1) | (CANCDMOB & (1 << IDE)); #else _messages_waiting++; // reset interrupt if (mob < 8) CANIE2 &= ~(1 << mob); else CANIE1 &= ~(1 << (mob - 8)); #endif CAN_INDICATE_RX_TRAFFIC_FUNCTION; } // restore MOb page register CANPAGE = canpage; } else { // no MOb matches with the interrupt => general interrupt CANGIT |= 0; }}// ----------------------------------------------------------------------------// Overflow of CAN timerISR(OVRIT_vect) {}
#endif // SUPPORT_FOR_AT90CAN__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -