Dirk Guest
|
ECAN works fine in LEGACY_MODE, but not in ENHANCED_MODE? |
Posted: Mon Sep 14, 2009 10:53 am |
|
|
Hello,
I am trying to start with CAN communication with a PIC18F2685. After solving first problems by reading older posts about CAN in this Forum now I have big trouble with ENHANCED Mode.
Everything is working fine if I use LEGACY Mode, but changing the Mode to ENHANCED (no FIFO), switching off all filters and program Buffers B0 to B5 as TX, I do a double receive every time a CAN-Message is sent to on the bus. First I receive on Buffer 0 with filter 0, but data is wrong. The second kbhit is on correct buffer with correct Data. And: I receive my own TX, but with wrong data and wrong ID.
It seems to me as the kbhit comes, but no data was received. What am I missing?
Here is the interesting part of the code (tested):
Code: |
void can_init(void){
byte mode;
can_set_mode(CAN_OP_CONFIG); //must be in config mode before params can be set
mode = CAN_FUN_OP_ENHANCED; // choose functional mode CAN_FUN_ENHANCED
//mode = CAN_FUN_OP_LEGACY;
ECANCON.mdsel= mode; // CAN_FUN_ENHANCED
curfunmode=mode; // CAN_FUN_ENHANCED_FIFO
can_set_baud();
RXB0CON=0;
RXB0CON.rxm=CAN_RX_VALID; // RX-Mode: Valid = STD and extended IDs, STD = only STD IDs, EXT = only extended IDs
RXB0CON.rxb0dben= CAN_USE_RX_DOUBLE_BUFFER; // Receive Buffer 0 overflow will write to Receive Buffer 1
RXB1CON=RXB0CON;
CIOCON.endrhi=CAN_ENABLE_DRIVE_HIGH; // CANTX pin will drive VDD when recessive
CIOCON.cancap=CAN_ENABLE_CAN_CAPTURE; // Enable CAN capture, CAN message receive signal replaces input on RC2/CCP1
// used to generate a time-stamp within Timer1 or Timer3
can_set_id(RX0MASK, CAN_MASK_ACCEPT_ALL, CAN_USE_EXTENDED_ID); //set mask 0
can_set_id(RXFILTER0, 0, CAN_USE_EXTENDED_ID); //set filter 0 of mask 0
can_set_id(RXFILTER1, 0, CAN_USE_EXTENDED_ID); //set filter 1 of mask 0
can_set_id(RX1MASK, CAN_MASK_ACCEPT_ALL, CAN_USE_EXTENDED_ID); //set mask 1
can_set_id(RXFILTER2, 0, CAN_USE_EXTENDED_ID); //set filter 0 of mask 1
can_set_id(RXFILTER3, 0, CAN_USE_EXTENDED_ID); //set filter 1 of mask 1
can_set_id(RXFILTER4, 0, CAN_USE_EXTENDED_ID); //set filter 2 of mask 1
can_set_id(RXFILTER5, 0, CAN_USE_EXTENDED_ID); //set filter 3 of mask 1
// set dynamic filters
can_set_id(RXFILTER6, 0, CAN_USE_EXTENDED_ID); // set IDs for all RX-filters
can_set_id(RXFILTER7, 0, CAN_USE_EXTENDED_ID);
can_set_id(RXFILTER8, 0, CAN_USE_EXTENDED_ID);
can_set_id(RXFILTER9, 0, CAN_USE_EXTENDED_ID);
can_set_id(RXFILTER10, 0, CAN_USE_EXTENDED_ID);
can_set_id(RXFILTER11, 0, CAN_USE_EXTENDED_ID);
can_set_id(RXFILTER12, 0, CAN_USE_EXTENDED_ID);
can_set_id(RXFILTER13, 0, CAN_USE_EXTENDED_ID);
can_set_id(RXFILTER14, 0, CAN_USE_EXTENDED_ID);
can_set_id(RXFILTER15, 0, CAN_USE_EXTENDED_ID);
can_disable_filter(RXF6EN);
can_disable_filter(RXF7EN);
can_disable_filter(RXF8EN);
can_disable_filter(RXF9EN);
can_disable_filter(RXF10EN);
can_disable_filter(RXF11EN);
can_disable_filter(RXF12EN);
can_disable_filter(RXF13EN);
can_disable_filter(RXF14EN);
can_disable_filter(RXF15EN);
can_enable_b_transfer(0xFC);
set_tris_b((*0xF93 & 0xFB ) | 0x08); //b3 is out, b2 is in
can_set_mode(CAN_OP_NORMAL);
}
|
And here is my main program:
Code: |
#opt 0
#if defined(__PCH__)
#include <18F2685.h>
#DEVICE ADC=10, HIGH_INTS = TRUE
#fuses NOPBADEN,BBSIZ1K,NOIESO,STVREN,NOWRT,NOWRTD,NOFCMEN,NOWRTC,NOWRTB,NOCPB,NOLPT1OSC,MCLR,NOXINST,PUT,BROWNOUT,BORV45,HS,WDT,NOPROTECT,NOLVP
#use delay(clock = 40M, oscillator = 10M, restart_wdt)
#use i2c(master, SDA=PIN_C4, SCL=PIN_C3, FORCE_HW, restart_wdt)
#use fixed_io(A_outputs = PIN_A4)
#use fixed_io(B_outputs = PIN_B5, PIN_B6, PIN_B7)
#use fixed_io(C_outputs = PIN_C0, PIN_C2, PIN_C5, PIN_C6, PIN_C7)
#define CAN_BRG_PRESCALAR 9 // baud rate generator prescalar value: 3
#define CAN_BRG_SYNCH_JUMP_WIDTH 1 // synchronized jump width (def: 1 x Tq)
#define CAN_BRG_PROPAGATION_TIME 1 // propagation time select (def: 3 x Tq)
#define CAN_BRG_PHASE_SEGMENT_1 7 // phase segment 1 (def: 6 x Tq)
#define CAN_BRG_PHASE_SEGMENT_2 4 // phase segment 2 time select (def: 6 x Tq)
#define CAN_BRG_SEG_2_PHASE_TS 1 // phase segment 2 time select bit (true: free programmable)
#define CAN_BRG_SAM 0 // sample once
#define CAN_BRG_WAKE_FILTER 0 // selects can bus line filter for wake up bit
#define CAN_ENABLE_DRIVE_HIGH 1 // CANTX will drive Vdd when recessive
#define CAN_USE_EXTENDED_ID 1 // use extended or standard ID
#include <string.h>
#include <can-18F2685.c>
#include <F:\PCWH\LCDIIC3\LCDIIC3_tools.c>
#zero_ram
#define LCD1 30 // i2c-address for external intelligent LCD
#define RelAuf PIN_A4
#define RelAb PIN_C2
#define CurrSens PIN_B0
#define CANEN PIN_C5
// Global Variables
struct rx_stat rxstat;
int32 rx_id;
int in_data[8];
int rx_len;
int out_data[8];
int32 tx_id = 1400;
int1 tx_rtr = 0;
int1 tx_ext = 1;
int tx_len = 2;
int tx_pri = 3;
byte rtr_data = 50;
byte rtr_len = 1;
// ********** Makros ************************************************
#define RelAuf_on output_high (RelAuf);
#define RelAuf_off output_low (RelAuf);
#define RelAb_on output_high (RelAb);
#define RelAb_off output_low (RelAb);
#define CAN_enable output_low (CANEN);
#define CAN_disable output_high (CANEN);
// MAIN
void main(){
byte val = 0;
byte info = 0;
port_b_pullups(false);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_OFF);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED);
setup_ccp1(CCP_OFF);
setup_vref(FALSE);
RelAuf_off
RelAb_off
CAN_enable // enable the PCA82C250
can_init();
can_set_filter(800, 100, 400, 400, 600, 900, 400, 400, 400, 400); // set recieve filter
do{
restart_wdt();
if (can_kbhit()){ // if data is waiting in buffer...
LCD_mode(LCD1,clear);
if(RXB0CON.rxful){
LCD_showchar(LCD1,'0');
delay_ms(1000); // wait a little bit
}
else if(RXB1CON.rxful){
LCD_showchar(LCD1,'1');
delay_ms(1000);
}
else if(B0CONR.rxful){
LCD_showchar(LCD1,'2');
delay_ms(1000);
}
else if(B1CONR.rxful){
LCD_showchar(LCD1,'3');
delay_ms(1000);
}
if(can_getd(rx_id, &in_data[0], rx_len, rxstat)) { //...then get data from buffer
LCD_gotoyx(LCD1,2,1); // set cursor on Line 2
LCD_showvalue(LCD1, integer5, nosign, make16(make8(rx_id,1),make8(rx_id,0)));
LCD_showvalue(LCD1, integer3, nosign, in_data[0]);
LCD_showvalue(LCD1, integer3, nosign, in_data[1]);
LCD_showvalue(LCD1, integer3, nosign, in_data[2]);
LCD_gotoyx(LCD1,3,1); // set Cursor on Line 3
LCD_showvalue(LCD1, integer3, nosign, rxstat.buffer);
LCD_showvalue(LCD1, integer3, nosign, rxstat.filthit);
if (in_data[0] == 2){ // turn on Relay "AUF"
RelAuf_on
}
else if (in_data[0] == 4){ // turn on Relay "AB"
RelAb_on
}
else if (in_data[0] == 1){ // turn off both Relays
RelAuf_off
RelAb_off
}
}
else {
LCD_backlight(LCD1,off); // blink backlight if there was an error
delay_ms(500);
LCD_backlight(LCD1,bright);
}
delay_ms(1000);
}
if(input(CurrSens)){
out_data[0] = 50;
out_data[1] = 4;
//tx_id = 20;
if(can_putd(tx_id, &out_data[0], tx_len, tx_pri, tx_ext, tx_rtr)){
LCD_showchar(LCD1,'G'); // sign for: GOOD TX
}
else {
LCD_backlight(LCD1,off); // blink backlight if there was an error
delay_ms(100);
LCD_backlight(LCD1,bright);
}
}
}while(true);
}
|
And here is my can_set_filter - routine:
Code: |
void can_set_filter(int16 rxid1, int16 rxid2, int16 rxid3, int16 rxid4, int16 rxid5, int16 rxid6, int16 rxid7, int16 rxid8, int16 rxid9, int16 rxid10) {
can_set_mode(CAN_OP_CONFIG); //must be in config mode before params can be set
can_set_id(RX0MASK, CAN_MASK_FILTER_ALL, 1); //set mask 0 // MATCH MASK 100%
can_set_id(RX0FILTER0, rxid1, CAN_USE_EXTENDED_ID); //set filter 0 of mask 0
can_set_id(RX0FILTER1, rxid2, CAN_USE_EXTENDED_ID); //set filter 1 of mask 0
can_set_id(RX1MASK, CAN_MASK_FILTER_ALL, 1); //set mask 1 // MATCH MASK 100%
can_set_id(RX1FILTER2, rxid3, CAN_USE_EXTENDED_ID); //set filter 0 of mask 1
can_set_id(RX1FILTER3, rxid4, CAN_USE_EXTENDED_ID); //set filter 1 of mask 1
can_set_id(RX1FILTER4, rxid5, CAN_USE_EXTENDED_ID); //set filter 2 of mask 1
can_set_id(RX1FILTER5, rxid6, CAN_USE_EXTENDED_ID); //set filter 3 of mask 1
can_set_id(RXFILTER6, rxid7, CAN_USE_EXTENDED_ID); //
can_set_id(RXFILTER7, rxid8, CAN_USE_EXTENDED_ID);
can_set_id(RXFILTER8, rxid9, CAN_USE_EXTENDED_ID);
can_set_id(RXFILTER9, rxid10, CAN_USE_EXTENDED_ID);
can_set_mode(CAN_OP_NORMAL);
}
|
The routines about the LCD work on i2c and are tested well.
I use the LCD because there is no RS232 on the hardware.
There is only one other node on the bus and it sends one single message with ID 600 every time it is triggered.
Thanks for Your help anywhere.
Dirk |
|