|
|
View previous topic :: View next topic |
Author |
Message |
EL
Joined: 24 Feb 2008 Posts: 15 Location: POLSKA
|
Problem with Controller area network (CAN) |
Posted: Thu Mar 27, 2008 12:02 pm |
|
|
Hi
I use from PIC16F876 MCP2515.
Bus speed: 125kb/s
I can not send data to card CAN at PC "Advantech PCL -841"
My hardware this:
16F876 MCP2515 PCA82C250
---SI---->S0-----
---S0---->SI----- ----->TX -RX-------->CANH
---SCK-->SCK-- ------>RX-TX-------->CANL
---C0---->CS----
Software this:
"can - mcp 2515x.h" and
"can - mcp 251x.c" :
Code: |
/////////////////////////////////////////////////////////////////////////
//// can-mcp2510.c ////
//// CAN Library routines for Microchip's MCP2510 (and compatable) ////
//// CAN IO expanders. ////
//// ////
//// ////
//// PRZEROBIONE przez ERYK ////
/////////////////////////////////////////////////////////////////////////
#include <can-mcp251x_eryk.h>
//IO pins connected to MCP2510
#ifndef EXT_CAN_CS
#define EXT_CAN_CS PIN_C0
#define EXT_CAN_SI PIN_C5
#define EXT_CAN_SO PIN_C4
#define EXT_CAN_SCK PIN_C3
// #define EXT_CAN_RESET PIN_B5 //reset
#endif
#if CAN_DO_DEBUG
#define can_debug printf
#else
#define can_debug
#endif
#define READ 0x03
#define WRITE 0x02
#define READSTATUS 0xA0
////////////////////////////////////////////////////////////////////////
//
// can_init()
//
// Inicjalizacja MCP2515.Ustawiam tak filtry i maski by wszystkie ID's mogly byc odebrane.
// Konfiguruje bufory tak by odbieraly wszystkie wazne wiadomosci...
//
////////////////////////////////////////////////////////////////////////
void can_init(void) {
struct struct_RXB0CTRL b_rxb0ctrl;
mcp2510_init();
can_set_mode(CAN_OP_CONFIG); //tryb konfiguracyjny
can_set_baud(); //predkosci
b_rxb0ctrl=0; //RXB0CTRL=0
b_rxb0ctrl.rxm=CAN_RX_VALID; //tryb 00 otrzymuj wszystkie wazne wiadomoĊci
b_rxb0ctrl.bukt=CAN_USE_RX_DOUBLE_BUFFER; //gdy RXB0 pelny to przeslij do RXB1
mcp2510_write(RXB0CTRL, (int)b_rxb0ctrl); //przeslij do RXB0CTRL
mcp2510_write(RXB1CTRL, (int)b_rxb0ctrl); //przeslij do RXB1CTRL
can_set_id(RX0MASK, CAN_MASK_ACCEPT_ALL, CAN_USE_EXTENDED_ID); //maska 0 (RX bufor 0) //adres=0x23h(RXM0EIDL),id=0,uzywam rozszerzonej ramki
can_set_id(RX0FILTER0, 0, CAN_USE_EXTENDED_ID); //filtr 0 w masce 0 (RX bufor 0) //adres=0x03h(RXF0EIDL),id=0,uzywam rozszerzonej ramki
can_set_id(RX0FILTER1, 0, CAN_USE_EXTENDED_ID); //filtr 1 w masce 0 (RX bufor 0) //adres=0x07h(RXF1EIDL),id=0,uzywam rozszerzonej ramki
can_set_id(RX1MASK, CAN_MASK_ACCEPT_ALL, CAN_USE_EXTENDED_ID); //maska 1 (RX bufor 1) //adres=0x27h(RXM1EIDL),id=0,uzywam rozszerzonej ramki
can_set_id(RX1FILTER2, 0, CAN_USE_EXTENDED_ID); //filtr 0 w masce 1 (RX bufor 1) //adres=0x0bh(RXF2EIDL),id=0,uzywam rozszerzonej ramki
can_set_id(RX1FILTER3, 0, CAN_USE_EXTENDED_ID); //filtr 1 w masce 1 (RX bufor 1) //adres=0x13h(RXF3EIDL),id=0,uzywam rozszerzonej ramki
can_set_id(RX1FILTER4, 0, CAN_USE_EXTENDED_ID); //filtr 2 w masce 1 (RX bufor 1) //adres=0x17h(RXF4EIDL),id=0,uzywam rozszerzonej ramki
can_set_id(RX1FILTER5, 0, CAN_USE_EXTENDED_ID); //filtr 3 w masce 1 (RX bufor 1) //adres=0x1bh(RXF5EIDL),id=0,uzywam rozszerzonej ramki
can_set_mode(CAN_OP_NORMAL); //tryb normalny
}
////////////////////////////////////////////////////////////////////////
//
// can_set_baud()
//
// Konfiguracja Baud Rate(predkosci transmisji)
// SyncSeg=1TQ
// PropSeg=1TQ
// PhSeg1=3TQ
// PhSeg2=3TQ
// -------------
// BIT TIME=8TQ=8us
// Predkosc=1/8TQ=1/8us=125kb/s
////////////////////////////////////////////////////////////////////////
void can_set_baud(void) {
struct struct_CNF1 new_CNF1;
struct struct_CNF2 new_CNF2;
struct struct_CNF3 new_CNF3;
new_CNF1.brp=CAN_BRG_PRESCALAR; //BRP=7 czyi TQ=2x(7+1)/16MHz=1us
new_CNF1.sjw=CAN_BRG_SYNCH_JUMP_WIDTH; //SJW=0 czyli 1TQ
new_CNF2.prseg=CAN_BRG_PROPAGATION_TIME; //PRSEG=0 czyli 1TQ
new_CNF2.phseg1=CAN_BRG_PHASE_SEGMENT_1; //PHSEG1=2 czyli 3TQ
new_CNF2.sam=CAN_BRG_SAM; //SAM=0
new_CNF2.btlmode=CAN_BRG_SEG_2_PHASE_TS; //BTLMODE=1
new_CNF3.phseg2=CAN_BRG_PHASE_SEGMENT_2; //PHSEG2=2 czyli 3TQ
new_CNF3.wakfil=CAN_BRG_WAKE_FILTER; //WAKFIL=1
mcp2510_write(CNF1, (int)new_CNF1);
mcp2510_write(CNF2, (int)new_CNF2);
mcp2510_write(CNF3, (int)new_CNF3);
}
void can_set_mode(CAN_OP_MODE mode) //funkcja ustawiajaca tryb w normalny
{
struct struct_CANCTRL old_CANCTRL;
old_CANCTRL=mcp2510_read(CANCTRL);
old_CANCTRL.reqop=mode;
mcp2510_write(CANCTRL, (int)old_CANCTRL);
do {
old_CANCTRL=mcp2510_read(CANCTRL);
} while (old_CANCTRL.reqop != mode);
}
////////////////////////////////////////////////////////////////////////
//
// can_set_id()
//
// Konfiguracja rejestrow xxxxEIDL, xxxxEIDH, xxxxSIDL i xxxxSIDH
// Konfiguruje zdefiniowane bufory by uzywaly odpowiednich ID
//
// Parametry:
// addr - wskaznik do pierwszego bajtu z ID rejestru, zaczynajac od xxxxeidl.
//
// id - ustawia ID w buforze
// ext - TRUE gdy uzywam rozszerzonego ID, FALSE gdy nie.
//
////////////////////////////////////////////////////////////////////////
void can_set_id(int addr, int32 id, int1 ext) {
int converted_id[4];
int *ptr;
ptr=&converted_id[3]; //3=eidl, 2=eidh, 1=sidl, 0=sidh
if (ext) { //extended
//eidl
*ptr=make8(id,0); //0:7
//eidh
ptr--;
*ptr=make8(id,1); //8:15
//sidl
ptr--;
*ptr=make8(id,2) & 0x03; //16:17
*ptr|=(make8(id,2) << 3) & 0xE0; //18:20
*ptr|=0x08;
//sidh
ptr--;
*ptr=((make8(id,2) >> 5) & 0x07 ); //21:23
*ptr|=((make8(id,3) << 3) & 0xF8);//24:28
}
else { //standard
//eidl
*ptr=0;
//eidh
ptr--;
*ptr=0;
//sidl
ptr--;
*ptr=(make8(id,0) << 5) & 0xE0;
//sidh
ptr--;
*ptr=(make8(id,0) >> 3) & 0x1F;
*ptr|=(make8(id,1) << 5) & 0xE0;
}
//0=eidl, 1=eidh, 2=sidl, 3=sidh
mcp2510_write(addr--, converted_id[3]);
mcp2510_write(addr--, converted_id[2]);
mcp2510_write(addr--, converted_id[1]);
mcp2510_write(addr, converted_id[0]);
}
////////////////////////////////////////////////////////////////////////
//
// can_get_id()
//
// Zwraca ID z odpowiedniego bufora(odwrotnosc funkcji can_set_id())
// Uzywam tej funkcji gdy odbieram wiadomosc, widze wiadomosc i jaki ma ID.
//
// Parametry:
// addr - wskaznik do pierwszego bajtu z ID rejestru, zaczynajac od xxxxeidl.
// ext - TRUE gdy uzywam rozszerzonego ID, FALSE gdy nie.
//
// Zwraca:
// ID z buforu
//
////////////////////////////////////////////////////////////////////////
int32 can_get_id(int addr, int1 ext) {
int32 ret;
int * ptr;
int converted_id[4];
ptr=&converted_id[3]; //3=eidl, 2=eidh, 1=sidl, 0=sidh
converted_id[3]=mcp2510_read(addr--);
converted_id[2]=mcp2510_read(addr--);
converted_id[1]=mcp2510_read(addr--);
converted_id[0]=mcp2510_read(addr);
ret=0;
if (ext) {
ret=*ptr; //eidl
ptr--; //eidh
ret|=((int32)*ptr << 8);
ptr--; //sidl
ret|=((int32)*ptr & 0x03) << 16;
ret|=((int32)*ptr & 0xE0) << 13;
ptr--; //sidh
ret|=((int32)*ptr << 21);
}
else {
ptr-=2; //sidl
ret=((int32)*ptr & 0xE0) >> 5;
ptr--; //sidh
ret|=((int32)*ptr << 3);
}
return(ret);
}
////////////////////////////////////////////////////////////////////////
//
// can_putd()
//
// Funkcja wysylania danych na magistrali CAN
//
// Parametry:
// id - identyfikator
// data - wskaznik danych
// len - dlugosc danych wysylanych
// priority - Priorytet wiadomosci(od 0-najnizszy do 3-najwyzszy)
//
// ext - TRUE gdy uzywam rozszerzonego ID, FALSE gdy nie.
// rtr - TRUE ustawia RTR (prosba/zadanie) bit w ID, FALSE nie.
//
// Zwraca:
// Gdy SUKCES TRUE
// GDy PORAZKA FALSE
//
////////////////////////////////////////////////////////////////////////
int1 can_putd(int32 id, int * data, int len, int priority, int1 ext, int1 rtr) {
int i;
int port;
int TXRXBaD0; //pole danych (8 bitow)
int TXBaCTRL; //rejestr konfiguracyjny
int TXRXBaEIDL; //rejestry identyfikatorow
int TXBaDLC; //rejestr dlugosci danych (RTR + 4 bity DLC)
struct txbNctrl_struct b_TXBaCTRL;
struct rxbNdlc_struct b_TXBaDLC;
struct txbNctrl_struct b_TXB0CTRL, b_TXB1CTRL, b_TXB2CTRL;
b_TXB0CTRL=mcp2510_read(TXB0CTRL); //odczyt z TXB0CTRL i zapis do b_TXB0CTRL
b_TXB1CTRL=mcp2510_read(TXB1CTRL);
b_TXB2CTRL=mcp2510_read(TXB2CTRL);
// znajduje wolny nadajnik
// mapowanie dostepnych bankow adresow
if (!b_TXB0CTRL.txreq) {
TXRXBaD0=TXB0D0; //dane
TXBaCTRL=TXB0CTRL; //bity kontrolne
TXRXBaEIDL=TXB0EIDL; //identyfikator
TXBaDLC=TXB0DLC; //dl.danych
port=0; //bufor0
}
else if (!b_TXB1CTRL.txreq) {
TXRXBaD0=TXB1D0;
TXBaCTRL=TXB1CTRL;
TXRXBaEIDL=TXB1EIDL;
TXBaDLC=TXB1DLC;
port=1;
}
else if (!b_TXB2CTRL.txreq) {
TXRXBaD0=TXB2D0;
TXBaCTRL=TXB2CTRL;
TXRXBaEIDL=TXB2EIDL;
TXBaDLC=TXB2DLC;
port=2;
}
else {
#if CAN_DO_DEBUG
can_debug("\r\nCAN_PUTD() FAIL: NO OPEN TX BUFFERS\r\n");
#endif
return(0);
}
//***PRIORYTET***
b_TXBaCTRL=mcp2510_read(TXBaCTRL);
b_TXBaCTRL.txpri=priority;
mcp2510_write(TXBaCTRL, (int)b_TXBaCTRL);
//***ustawiam maski TX***
can_set_id(TXRXBaEIDL, id, ext);
//**ustawiam dlugosc danych***
b_TXBaDLC=len;
b_TXBaDLC.rtr=rtr;
mcp2510_write(TXBaDLC, (int)b_TXBaDLC);
//***zapis do bufora***
for (i=TXRXBaD0; i<(TXRXBaD0 + len); i++) {
mcp2510_write(i,*data);
data++;
}
//***ENABLE transmisja***
b_TXBaCTRL=mcp2510_read(TXBaCTRL);
b_TXBaCTRL.txreq=1;
mcp2510_write(TXBaCTRL, (int)b_TXBaCTRL);
#if CAN_DO_DEBUG
can_debug("\r\nCAN_PUTD(): BUFF=%U ID=%LX LEN=%U PRI=%U EXT=%U RTR=%U\r\n", port, id, len, priority, ext, rtr);
if ((len)&&(!rtr)) {
data-=len;
can_debug(" DATA = ");
for (i=0;i<len;i++) {
can_debug("%X ",*data);
data++;
}
can_debug("\r\n");
}
#endif
return(1);
}
////////////////////////////////////////////////////////////////////////
//
// can_getd()
//
// Odczyt danych z biufora odbioru (jezeli sa tam dane)
//
// Parametry:
// id - ID
// data - wskaznik danych
// len - dlugosc(liczba) danych
// stat - struktura z informacjami (ktory bufor odbiera, ext czy standard, itp)
//
// Zwraca:
// Funkcja wywoluje TRUE jesli cos jest w buforze odbioru,FALSE gdy nie
//
////////////////////////////////////////////////////////////////////////
int1 can_getd(int32 & id, int * data, int & len, struct rx_stat & stat)
{
int i;
struct struct_RXB0CTRL b_RXB0CTRL;
struct struct_RXB1CTRL b_RXB1CTRL;
struct struct_EFLG b_EFLG;
int RXBaDLC;
struct rxbNdlc_struct b_RXBaDLC;
int TXRXBaSIDL;
struct struct_TXRXBaSIDL b_TXRXBaSIDL;
int RXBaD0;
struct struct_CANINTF b_CANINTF;
b_CANINTF=mcp2510_read(CANINTF); //odczyt rejestru CANINTF(
b_RXB0CTRL=mcp2510_read(RXB0CTRL); //odczyt rejestrow kontrolnych poszczegolnych buforow
b_RXB1CTRL=mcp2510_read(RXB1CTRL);
b_EFLG=mcp2510_read(EFLG); //odczyt flagi EFLG(flaga bledu)
if (b_CANINTF.rx0if) { //jezeli jest wiadomosc w buforze 0
stat.buffer=0;
stat.err_ovfl=b_EFLG.rx0ovr; //informuje czy bufor 0 jest pelny
b_EFLG.rx0ovr=0; //nie jest pelny
mcp2510_write(EFLG, (int)b_EFLG); //przeslij do EFLG
if (b_RXB0CTRL.bukt) { //jezeli BUKT=1, czyli gdy RXBO jest pelny to dane sa przesylane do RXB1
stat.filthit=b_RXB0CTRL.filhit0; //filtry
}
RXBaDLC=RXB0DLC; //dlugosc pola danych
TXRXBaSIDL=RXB0SIDL; //maskowanie
RXBaD0=RXB0D0; //dane
}
else if (b_CANINTF.rx1if)
{
stat.buffer=1;
stat.err_ovfl=b_EFLG.rx1ovr;
b_EFLG.rx1ovr=0;
mcp2510_write(EFLG, (int)b_EFLG);
stat.filthit=b_RXB1CTRL.filhit0;
RXBaDLC=RXB1DLC;
TXRXBaSIDL=RXB1SIDL;
RXBaD0=RXB1D0;
}
else {
#if CAN_DO_DEBUG
can_debug("\r\nFAIL ON CAN_GETD(): NO MESSAGE IN BUFFER\r\n");
#endif
return (0);
}
//***odczyt dlugosci pola danych***
b_RXBaDLC=mcp2510_read(RXBaDLC); //odczyt RXBaDLC i wpisanie do zmiennej b_RXBaDLC
len = b_RXBaDLC.dlc; //len (dlugosc danych)
stat.rtr=b_RXBaDLC.rtr; //rtr (ramka danych czy ramka zdalna)
//***extended czy standard?***
b_TXRXBaSIDL=mcp2510_read(TXRXBaSIDL);
stat.ext=b_TXRXBaSIDL.ext;
id=can_get_id(TXRXBaSIDL + 2,stat.ext);
//***odczyt danych***
for ( i = RXBaD0; i < (RXBaD0 + len); i++ ) {
*data=mcp2510_read(i);
data++;
}
stat.inv=b_CANINTF.merrf;
if (b_CANINTF.merrf) { //gdy MERRF=1 to nastapil blad (oczekiwanie na przerwanie)
b_CANINTF.merrf=0; //zerowanie
}
if (stat.buffer) { //jezeli bufor 1
b_CANINTF.rx1if=0; //nie oczekuje na przerwanie od przepelnienia bufora 1
}
else {
b_CANINTF.rx0if=0; //nie oczekuje na przerwanie od przepelnienia bufora 0
}
mcp2510_write(CANINTF, (int)b_CANINTF);
#if CAN_DO_DEBUG
can_debug("\r\nCAN_GETD(): BUFF=%U ID=%LX LEN=%U OVF=%U ", stat.buffer, id, len, stat.err_ovfl);
can_debug("FILT=%U RTR=%U EXT=%U INV=%U", stat.filthit, stat.rtr, stat.ext, stat.inv);
if ((len)&&(!stat.rtr)) {
data-=len;
can_debug("\r\n DATA = ");
for (i=0;i<len;i++) {
can_debug("%X ",*data);
data++;
}
}
can_debug("\r\n");
#endif
return(1);
}
////////////////////////////////////////////////////////////////////////
//
// can_kbhit()
//
// Zwraca TRUE jezeli w buforze odbioru sa jakies dane
//
//////////////////////////////////////////////////////////////////////////////
int1 can_kbhit(void) {
struct struct_CANINTF b_CANINTF;
b_CANINTF=mcp2510_read(CANINTF);
if (b_CANINTF.rx0if || b_CANINTF.rx1if)
{return(1);}
return(0);
}
////////////////////////////////////////////////////////////////////////
//
// can_tbe()
//
// Zwraca TRUE jesli bufory transmisji sa puste i gotowe do transmitowania danych
//
//////////////////////////////////////////////////////////////////////////////
int1 can_tbe(void) {
struct txbNctrl_struct b_TXB0CTRL, b_TXB1CTRL, b_TXB2CTRL;
b_TXB0CTRL=mcp2510_read(TXB0CTRL);
b_TXB1CTRL=mcp2510_read(TXB1CTRL);
b_TXB2CTRL=mcp2510_read(TXB2CTRL);
if (!b_TXB0CTRL.txreq || !b_TXB1CTRL.txreq || !b_TXB2CTRL.txreq)
{return(1);}
return(0);
}
////////////////////////////////////////////////////////////////////////
//
// can_abort()
//
// Odrzuca wszystkie oczekujace transmisje
//
//////////////////////////////////////////////////////////////////////////////
void can_abort(void) {
struct struct_CANCTRL b_CANCTRL;
b_CANCTRL=mcp2510_read(CANCTRL);
b_CANCTRL.abat=1; //ABAT=1,odrzucenie transmisji
mcp2510_write(CANCTRL, (int)b_CANCTRL);
delay_ms(5);
b_CANCTRL.abat=0;
mcp2510_write(CANCTRL, (int)b_CANCTRL);
}
///////////////////
///
//
// SPI CODE
//
///
//////////////////
//data clocked in on rising edge
//data driven out on falling edge
/*
int mcp2510_read(int address)
{
int command[2];
int i;
int data;
command[1]=0x03;
command[0]=address;
output_low(EXT_CAN_CS);
for (i=0;i<16;i++)
{
output_bit(EXT_CAN_SI, shift_left(&command[0],2,0));
output_high(EXT_CAN_SCK);
output_low(EXT_CAN_SCK);
}
for (i=0;i<8;i++)
{
shift_left(&data,1,input(EXT_CAN_SO));
output_high(EXT_CAN_SCK);
output_low(EXT_CAN_SCK);
}
output_high(EXT_CAN_CS);
return(data);
}
*/
////////////////kod ERYK//////////////////////
int mcp2510_read(int address)
{
int data;
output_low(EXT_CAN_CS); //zalaczenie MCP2515
spi_write(READ); //wyslanie instrukcji odczytu
spi_write(address); //odczyt z rejestru
data = spi_read(0x00); //odczyt z rejestru do data
output_high(EXT_CAN_CS); //SPI koniec
return(data);
}
////////////////KONIEC kod ERYK//////////////////////
/*
int mcp2510_status(void) {
int command;
int data;
int i;
command=0xA0;
output_low(EXT_CAN_CS);
for (i=0;i<8;i++) {
output_bit(EXT_CAN_SI, shift_left(&command,1,0));
output_high(EXT_CAN_SCK);
output_low(EXT_CAN_SCK);
}
for (i=0;i<8;i++) {
shift_left(&data,1,input(EXT_CAN_SO));
output_high(EXT_CAN_SCK);
output_low(EXT_CAN_SCK);
}
for (i=0;i<8;i++) {
output_high(EXT_CAN_SCK);
output_low(EXT_CAN_SCK);
}
output_high(EXT_CAN_CS);
return(data);
}
*/
////////////////kod ERYK//////////////////////
int mcp2510_status(void)
{
int data;
output_low(EXT_CAN_CS); //zalaczenie MCP2515
spi_write(READSTATUS); //wyslanie instrukcji statusu
data = spi_read(0x00); //odczyt z rejestru do data
output_high(EXT_CAN_CS); //wylaczenie MCP2515
return(data);
}
////////////////KONIEC kod ERYK//////////////////////
/*
void mcp2510_write(int address, int data) {
int command[3];
int i;
command[2]=0x02;
command[1]=address;
command[0]=data;
output_low(EXT_CAN_CS);
for (i=0;i<24;i++) {
output_bit(EXT_CAN_SI, shift_left(&command[0],3,0));
output_high(EXT_CAN_SCK);
output_low(EXT_CAN_SCK);
}
output_high(EXT_CAN_CS);
}
*/
////////////////kod ERYK//////////////////////
void mcp2510_write(int address, int data)
{
output_low(EXT_CAN_CS); //zalaczenie MCP2515
spi_write(WRITE); //wyslanie instrukcji zapisu
spi_write(address); //adres
spi_write(data); //dana
output_high(EXT_CAN_CS); //SPI koniec
}
////////////////KONIEC kod ERYK//////////////////////
/*
void mcp2510_command(int command) {
int i;
output_low(EXT_CAN_CS);
for (i=0;i<8;i++) {
output_bit(EXT_CAN_SI, shift_left(&command,1,0));
output_high(EXT_CAN_SCK);
output_low(EXT_CAN_SCK);
}
output_high(EXT_CAN_CS);
}
*/
////////////////kod ERYK//////////////////////
void mcp2510_command(int command)
{
output_low(EXT_CAN_CS); //zalaczenie MCP2515
spi_write(command); //wyslanie komendy
output_high(EXT_CAN_CS); //SPI koniec
}
////////////////KONIEC kod ERYK//////////////////////
void mcp2510_init(void)
{
output_high(EXT_CAN_CS);
mcp2510_command(0xC0); //reset
delay_ms(5);
}
///////////////KONIEC/////////////////////////////////
|
main:
Code: |
#include <16F876.h>
#include <F876.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define CAN_DO_DEBUG TRUE
#include <can-mcp251x.c>
void main()
{
struct rx_stat rxstat;
int32 rx_id;
int buffer[8];
int rx_len;
int data=0x05;
int i;
trisc_0=0;
trisc_1=0;
trisc_2=0;
trisc_3=0;
trisc_4=0;
trisc_5=1;
trisc_6=0;
trisc_7=0;
//Tryb MASTER,czestowliowsc 1MHz
//SSPCON=00100000(SSPEN=1),SSPSTAT=1000000(SMP=1,CKP=0,CKE=0)
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 | SPI_SAMPLE_AT_END);
for(i=0;i<8;i++) {
buffer[i]=0;
}
can_init();
while(TRUE)
{
can_putd(0x202, &data, 1,1,1,0); //put data on transmit buffer
delay_ms(1000);
}
}
|
What do I do bad?
I thank for help |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 27, 2008 3:42 pm |
|
|
Your question is really how to convert the CCS MCP2515 driver from
using software SPI to using hardware SPI.
Quote: |
trisc_0=0;
trisc_1=0;
trisc_2=0;
trisc_3=0;
trisc_4=0;
trisc_5=1;
trisc_6=0;
trisc_7=0;
|
CCS handles setting the TRIS for you. You don't have to do this.
If you use "standard i/o" mode (the default mode of the compiler)
and if you use CCS i/o functions (such as output_low(), etc.), then
the compiler will automatically set the correct TRIS for you.
Also, if you use CCS built-in functions such as setup_spi(), the compiler
will automatically setup the correct TRIS for the SDO, SDI, and SCK pins.
Delete those lines above.
Quote: |
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 | SPI_SAMPLE_AT_END); |
This is wrong. You're setting the wrong SPI mode. Here is a list of
SPI mode definitions. You're setting mode 1, with sample at end.
Code: |
#define SPI_MODE_0_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1 (SPI_L_TO_H)
#define SPI_MODE_1_0 (SPI_H_TO_L)
#define SPI_MODE_1_1 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
|
Look on page 63 of the MCP2515 data sheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/21801e.pdf
It tells you the correct SPI mode to use:
Quote: | 12.0 SPI INTERFACE
12.1 Overview
The MCP2515 is designed to interface directly with the
Serial Peripheral Interface (SPI) port available on many
microcontrollers and supports Mode 0,0 and Mode 1,1. |
Add those #define statements to your program and then change the
setup_spi() statement to this:
Code: | setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_4); |
Also make sure you connect a 120 ohm termination resistor across the
CANH and CANL lines next to the PCA82C250 on your PIC board.
You need a termination resistor on your board and also on the PCL-841.
The Advantech PCL-841 board has terminator resistors on it for each
CAN bus connector. But you must install a jumper on the board (JP9 or
JP10) to enable the resistors. Make sure you do that. |
|
|
EL
Joined: 24 Feb 2008 Posts: 15 Location: POLSKA
|
|
Posted: Fri Mar 28, 2008 3:50 am |
|
|
I thank PCM programmer
I will check this all really on Monday because I will be then dust card CAN.
You assured me in conviction from these TRIS'es.thanks
I will improve also settings SPI and resistor (120 ohm) I have on single board only I forgot about inserting jumper.
Salute:) |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|