?? canopdriver.c
字號:
/*******************************************************************************
CANopDriver.c - Functions for CANopenNode
Copyright (C) 2004 Janez Paternoster, Slovenia
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Author: janez.paternoster@siol.net
History:
2004/06/25 [JP] File Created
2004/08/09 [JP] Revised, many changes (interrupt and init routines), added setup 'defines'
*******************************************************************************/
#include <p18cxxx.h>
#include <string.h>
#include "CANopDriver.h"
#include "CANopErrors.h"
#ifdef CO_ALLOW_FLASH_WRITE
#include "memcpyram2flash.h"
#endif
//following is not real header file, because it contains variable definitions,
//it may be included only at this point
#include "CANopObjDict.h"
/*******************************************************************************
Variables used in CANopen
*******************************************************************************/
//CANopen nodeID
unsigned char CO_NodeID = CO_DEFAULT_NODE_ID;
//CANopen Bit rate
unsigned char CO_BitRate = CO_DEFAULT_BIT_RATE;
//timer variable increments every 1ms
volatile unsigned int CO_Timer16Value;
//NMT operating state of node
volatile unsigned char CO_NMToperatingState;
//Variables used in High Interrupt
#pragma udata access CO_udata_access
near unsigned char CO_IsrHighIndex; //index of matched CANid
near unsigned char CO_IsrHighRxNoOfBytes; //number of bytes in recived message
near volatile struct{ //signals from IsrHigh to IsrLow or ProcessMain
unsigned char ResetComm :1;
union{
unsigned char byte;
struct{
unsigned char NMTlength :1;
unsigned char NMTcmd :1;
unsigned char HeartBeatLength :1;
unsigned char SyncLength :1;
unsigned char SDOlength :1;
unsigned char PDOlength :1;
}bits;
}Error;
}CO_IsrHighSignal;
#pragma udata
//SDOs
unsigned char CO_SDOrequest; //0=ready for new communication, 1=busy, 0xFF=abort
unsigned char CO_SDORXdata[8]; //data arrived from bus
unsigned char CO_SDOTXdata[8]; //data transmitted to bus
//PDOs
#pragma udata CO_udata=0x100 //some variables are in separate section to avoid section overflow
#define CO_SIZE_OF_RPDO_DATA 8 //value must match size of one CO_RPDO member !!!
#if CO_NO_RPDO > 0
volatile tData8bytes CO_RPDO[CO_NO_RPDO]; //Data
volatile unsigned char CO_RPDOlength[CO_NO_RPDO]; //length of recive PDOs in bytes, calculated from mapping parameters
volatile unsigned char CO_RPDOcount[CO_NO_RPDO]; //counter of recived PDOs, incremented each time PDO is recived, may be erased
#endif
#if CO_NO_TPDO > 0
volatile tData8bytes CO_TPDO[CO_NO_TPDO]; //Data
volatile unsigned char CO_TPDOlength[CO_NO_TPDO]; //length of transmit PDOs in bytes, calculated from mapping parameters
volatile unsigned char CO_tTPDOwait[CO_NO_TPDO]; //timer used for trigger PDO sending
#endif
#pragma udata
//Sync
volatile struct{
unsigned int period;
unsigned int periodTimeout;
unsigned int window;
}CO_SYNC;
//HeartBeat Consumer
#if CO_NO_CONS_HEARTBEAT > 0
volatile unsigned int CO_HBcons_TimerValue[CO_NO_CONS_HEARTBEAT];
volatile unsigned char CO_HBcons_NMTstate[CO_NO_CONS_HEARTBEAT];
#endif
//Emergency message control and Error codes
volatile struct{
char CheckErrors :1;
char EmergencyToSend :1;
unsigned int EmergencyErrorCode;
unsigned char CodeVal;
}ErrorControl;
rom unsigned int ErrorCodesTable[] = ERROR_CODES;
unsigned char CO_EmergencyTXdata[8]; //data transmitted to bus
//Status LEDs
struct {
unsigned char On :1;
unsigned char Off :1;
unsigned char Flickering :1;
unsigned char Blinking :1;
unsigned char SingleFlash :1;
unsigned char DoubleFlash :1;
unsigned char TripleFlash :1;
} CO_StatusLED;
//variable for reciving CAN messages
unsigned int CO_RXCAN_ID[3+CO_NO_RPDO+CO_NO_CONS_HEARTBEAT];
//filled at CanInit, IDs are << 5 to match the RXBnSIDx register bit order:
// 0=NMT ID, 1=SYNC ID, 2=SDO ID,
// 3...(2+CO_NO_RPDO)=RPDO ID,
// (3+CO_NO_RPDO)...(2+CO_NO_RPDO+CO_NO_CONS_HEARTBEAT)=Heartbeat consumer ID
//variables for transmitting CAN messages
//filled at CanInit, IDs are << 5 to match the RXBnSIDx register bit order:
//PDOs through Hardware transmit buffer 0, interrupt driven
#if CO_NO_TPDO > 0
unsigned char CO_TXCAN_PDOsendReq; //flag variable for request sending message
CO_CanMessage CO_TXCAN_PDOmsgs[CO_NO_TPDO];
#endif
//Emergencies, SDOs, Heartbeats and User defined msgs through Hardware transmit buffer 1, interrupt driven
unsigned char CO_TXCAN_OtherSendReq; //flag variable for request sending message
CO_CanMessage CO_TXCAN_OtherMsgs[CO_NO_USR_CAN_BUFF+2];
// 0...(CO_NO_USR_CAN_BUFF-1)=User defined messages,
// (CO_NO_USR_CAN_BUFF)=SDO, (CO_NO_USR_CAN_BUFF+1)=HeartBeat
#if(CO_NO_USR_CAN_BUFF+2) > 8
#error define_CO_NO_USR_CAN_BUFF CO_NO_USR_CAN_BUFF too big
#endif
//SYNCs and Emergency through Hardware transmit buffer 2, interrupt driven
unsigned char CO_TXCAN_SEMsendReq; //flag variable for request sending message
CO_CanMessage CO_TXCAN_SEMmsgs[2];
/*******************************************************************************
CAN bit rates and Timer2 setup
*******************************************************************************/
#if CO_OSCILATOR_FREQ == 16
#define TIMER2PRESCALE 0 //0=1:1, 1=1:4, 2=1:16
#define TIMER2POSTSCALE 16 //1...16
#define TIMER2PR2 249 //0...255
#elif CO_OSCILATOR_FREQ == 20
#define TIMER2PRESCALE 1 //0=1:1, 1=1:4, 2=1:16
#define TIMER2POSTSCALE 10 //1...16
#define TIMER2PR2 124 //0...255
#elif CO_OSCILATOR_FREQ == 32
#define TIMER2PRESCALE 1 //0=1:1, 1=1:4, 2=1:16
#define TIMER2POSTSCALE 16 //1...16
#define TIMER2PR2 124 //0...255
#elif CO_OSCILATOR_FREQ == 40
#define TIMER2PRESCALE 1 //0=1:1, 1=1:4, 2=1:16
#define TIMER2POSTSCALE 10 //1...16
#define TIMER2PR2 249 //0...255
#else
#error define_CO_OSCILATOR_FREQ CO_OSCILATOR_FREQ not supported
#endif
rom struct{
UNSIGNED8 BRP; //(1...64) Baud Rate Prescaler
UNSIGNED8 SJW; //(1...4) SJW time
UNSIGNED8 PROP; //(1...8) PROP time
UNSIGNED8 PhSeg1; //(1...8) Phase Segment 1 time
UNSIGNED8 PhSeg2; //(1...8) Phase Segment 2 time
}CO_BitRateData[8] =
#if CO_OSCILATOR_FREQ == 16
{50, 1, 4, 8, 3, //CAN=10kbps
25, 1, 4, 8, 3, //CAN=20kbps
10, 1, 4, 8, 3, //CAN=50kbps
4, 1, 4, 8, 3, //CAN=125kbps
2, 1, 4, 8, 3, //CAN=250kbps
1, 1, 4, 8, 3, //CAN=500kbps
1, 1, 2, 4, 3, //CAN=800kbps
1, 1, 2, 3, 2};//CAN=1000kbps
#elif CO_OSCILATOR_FREQ == 20
{50, 1, 6, 8, 5, //CAN=10kbps
25, 1, 6, 8, 5, //CAN=20kbps
10, 1, 6, 8, 5, //CAN=50kbps
5, 1, 4, 8, 3, //CAN=125kbps
2, 1, 6, 8, 5, //CAN=250kbps
1, 1, 6, 8, 5, //CAN=500kbps
1, 1, 3, 5, 3, //CAN=800kbps //combination does not work
1, 1, 2, 4, 3};//CAN=1000kbps
#elif CO_OSCILATOR_FREQ == 32
{64, 1, 8, 8, 8, //CAN=10kbps
50, 1, 4, 8, 3, //CAN=20kbps
20, 1, 4, 8, 3, //CAN=50kbps
8, 1, 4, 8, 3, //CAN=125kbps
4, 1, 4, 8, 3, //CAN=250kbps
2, 1, 4, 8, 3, //CAN=500kbps
2, 1, 2, 4, 3, //CAN=800kbps
2, 1, 2, 3, 2};//CAN=1000kbps
#elif CO_OSCILATOR_FREQ == 40
{64, 4, 8, 8, 8, //CAN=10kbps //combination does not work
50, 1, 6, 8, 5, //CAN=20kbps
25, 1, 4, 8, 3, //CAN=50kbps
10, 1, 4, 8, 3, //CAN=125kbps
5, 1, 4, 8, 3, //CAN=250kbps
2, 1, 6, 8, 5, //CAN=500kbps
1, 1, 8, 8, 8, //CAN=800kbps
2, 1, 2, 4, 3};//CAN=1000kbps
#else
#error define_CO_OSCILATOR_FREQ CO_OSCILATOR_FREQ not supported
#endif
/*******************************************************************************
INIT CAN BUS INTERFACE, executed at node reset
*******************************************************************************/
void CO_InitResetNode(void){
unsigned char i;
/* Init Timer2 ****************************************************************/
//timer2 is used for 1ms interrupt. It is also time-base for PWM modules.
//So if PWM is used, frequency is set here.
T2CON = ((TIMER2POSTSCALE-1) << 3) | 0x04 | TIMER2PRESCALE;
PR2 = TIMER2PR2;
TMR2 = 0;
//interrupts
PIR1bits.TMR2IF = 0;
IPR1bits.TMR2IP = 0; //low priority interrupt
PIE1bits.TMR2IE = 1;
/* Init Printed Board *********************************************************/
PCB_BANDWIDTH_IsrLow_INIT;
PCB_BANDWIDTH_IsrHigh_INIT;
PCB_RUN_LED_INIT;
PCB_ERROR_LED_INIT;
/* Read EEPROM ****************************************************************/
#ifdef CO_USE_EEPROM
EECON1bits.EEPGD = 0;
EECON1bits.CFGS = 0;
i=sizeof(ODE_EEPROM);
do{
i--;
EEADR = i;
EECON1bits.RD = 1;
*((unsigned char*)&ODE_EEPROM + i) = EEDATA;
}while(i>0);
#endif
/* Init variables *************************************************************/
CO_Timer16Value = 0;
CO_StatusLED.On = 1;
CO_StatusLED.Off = 0;
ODE_EEPROM.PowerOnCounter++;
}
/*******************************************************************************
INIT CAN BUS INTERFACE, executed at communication reset
*******************************************************************************/
void CO_InitResetComm(void){
static char i;
PCB_RUN_LED(CO_StatusLED.Off);
CO_NMToperatingState = NMT_INTIALIZING;
CANCON = 0x80; //request configuration mode
while((CANSTAT & 0xE0) != 0x80); //wait until configuration mode is set
/* Setup variables ************************************************************/
CO_NodeID = ReadNodeID();
if(CO_NodeID==0 || CO_NodeID>127){
ErrorReport(ERROR_WrongNodeIDorBitRate, CO_NodeID);
CO_NodeID = 1;
}
CO_BitRate = ReadBitRate();
if(CO_BitRate > 7){
ErrorReport(ERROR_WrongNodeIDorBitRate, CO_BitRate);
CO_BitRate = 1;
}
CO_IsrHighSignal.ResetComm = 0;
CO_IsrHighSignal.Error.byte = 0;
//SDOs
CO_SDOrequest = 0;
ODE_Server_SDO_Parameter.COB_ID_Client_to_Server = 0x00000600L + CO_NodeID;
ODE_Server_SDO_Parameter.COB_ID_Server_to_Client = 0x00000580L + CO_NodeID;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -