Konfigurace obvodů Intel 82527 & Bosch CC750/CC770 a jejich derivátů

Tento materiál je určen všem těm, kteří si chtějí postavit vlastní zařízení s CAN rozhraním. Pamatuji si, že když jsem před několika lety s CANem začínal, tak se mi ze všech těch bitů v tehdy používaném řadiči MCP2510 pěkně motala hlava. Před nedávnou dobou jsem si hrál s obvodem CC750, takže se tu pokusím shrnout to co o tomto obvodu znám a snad tím někomu ulehčím práci. 

Obsah:

1.

Úvod Rozdělení CAN controllerů na kategorie.

2.

Popis rozdílů mezi obvody Intel 82527 a Bosch CC750/CC770 V čem jsou tyto obvody shodné a v čem se liší.

3.

SPI interface Popis komunikace prostřednictvím rozhraní SPI.

4.

Popis registrů Popis adresního prostoru, registrů a řídících bitů.

5.

SPI prakticky Praktická ukázka formou zdrojových kódů v jazyce C.

6.

Inicializace Praktická ukázka formou zdrojových kódů v jazyce C.

7.

Komunikace Praktická ukázka formou zdrojových kódů v jazyce C.

Díl první: Úvod

    CAN controllery (řadiče) sběrnice CAN je možno rozdělit do dvou základních skupin podle principu jejich funkce a to nezávisle na tom, zda se jedná o samostatné obvody, jádra pro hradlová pole, nebo periferie různých procesorů. První skupina obvodů obvykle obsahuje několik bufferů, nebo jeden FIFO (SJA1000) buffer, kdy buffer(y) může(mohou) obsahovat několik zpráv se stejným identifikátorem. Druhá skupina obsahuje obvykle větší množství bufferů, z nichž každý je určen pro jednu konkrétní zprávu nebo skupinu zpráv v případě implementace lokálních masek. Samozřejmě hranice mezi těmito skupinami není nijak ostrá. U mnoha obvod se dá diskutovat o tom, do které skupiny by bylo možno je zařadit.

    První skupina controllerů je vhodná zejména pro různé karty pro PC, kdy potřebujeme přijímat obvykle všechny zprávy bez ohledu na identifikátor. Druhá skupina je pak určena pro cílová zařízení jako jsou různé IO karty, řídící jednotky pohonů apod. Vlastnosti obvodů první kategorie se nám mohou na první pohled zdát vhodné i pro jednoduché aplikace s nejrůznějšími jednočipy, nicméně později zjistíme že na obsluhu tohoto obvodu z jednočipu spotřebujeme příliš režie, jako například:

  • nutnost u přijaté zprávy dekódovat identifikátor v případě, že jednotka odesílá zprávy s několika ID

  • v případě že jednotka odesílá zprávy s několika identifikátory, je nutno vždy identifikátor znovu nastavit

  • nutnost kompletní obsluhy a zpracování při příjmu zprávy RTR procesorem

    Obvody druhé kategorie s množstvím bufferů nám toto značně zjednodušují. K těmto obvodům patří Intel 82527 a Bosch CC750/770. Popis jejich vlastností, konfigurace a řízení bude obsahem tohoto článku.

Díl druhý: Popis rozdílů mezi obvody Intel 82527 a Bosch CC750/CC770

    Obvody CC770 a AN82527 jsou pinově a softwarově shodné, liší se jen několika v AN82527 rezervovanými bity, které jsou v CC770 použity. Dále pak obvod CC770 má implementovány pro čtení čítače TEC (Transmit Error Counter) a REC (Receive Error Counter) a podporuje maskování bitů Xtd a Dir v Message 15 Mask registru.

    Obvod CC750 se od AN82527 a CC770 liší takto:

            - pouze jeden SPI mód

            - s CPU může komunikovat pouze prostřednictvím SPI, nemá paralelní sběrnici

            - nemá paralelní porty a s jejich řízením spojné bity v registrech

            - nemá Clockout pin

            - pouze po jednom výstupu Tx a Rx

    Obvod CC750 se pak navíc liší od CC770 adresou registrů TEC a REC.

    V dalším textu se primárně zaměříme na popis CC750 a budeme si uvádět rozdíly od CC770 a AN82527. Speciální vlastnosti (paralelní výstupy atd.) CC750 a AN82527 nebudu popisovat, neboť nemám s nimi praktickou zkušenost.

     Díl třetí: SPI interface

    Na připojení SPI rozhraní není nic zvláštního, CAN controller se chová jako slave. S masterem je propojen 4 vodiči MOSI, MISO,SPICLK a CS. CS nemusí být teoreticky použito a lze se synchronizovat pomocí registru Serial Reset Address. V dokumentaci k CC750 se píše, že CPU musí zapsat string 16 bajtů 0xFF pro navázání synchronizace. S touto funkcí bohužel nemám žádné zkušenosti.

    Obvod CC750 má jen jeden mód SPI. Obvody CC770 a 82527 dovolují výběr módu SPI pomocí multifunkčních pinů AD0-AD3 takto:

    AD0 (ICP) Idle Clock Polarity

 

one

SCLK is idle high

 

zero

SCLK is idle low

    AD1 (CP) Clock Phase

 

one

Je-li ICP=0 jsou data samplována na sestupné hraně.

Je-li ICP=1 jsou data samplována na nástupné hraně.

 

zero

Je-li ICP=0 jsou data samplována na nástupné hraně.

Je-li ICP=1 jsou data samplována na sestupné hraně.

    AD2 (CSAS) Chip Select Active State

 

one

Aktivní stav CS je log. high.

 

zero

Aktivní stav CS je log. low

    AD3 (STE) Synchronization Transmission Enable

    Povolení generování synchronizačních bajtů AAh a 55h při přenosu adresy a řídícího slova.

    Vlastní přenos na SPI může být tvořen blokem bajtů o maximální délce 17. První bajt je adresa odkud budeme číst nebo zapisovat. Druhý bajt je řídícím slovem. Zbylých až 15 bajtů jsou data zapisovaná od zadané adresy směrem nahoru. Řídící slovo (Serial Control Byte) má tuto strukturu:

 

7 6 5 4 3 2 1 0
Dir Sync SDLC

    Pro čtení z CAN controlleru má Dir hodnotu 0, pro zápis pak 1.  Sync musí být vždy nastaveno na 000. SDLC (Serial Data Length Code) pak udává délku dat, jsou povoleny hodnoty 1-15. V okamžiku kdy CPU odesílá adresu, CAN controller vrací zpět hodnotu AAh,  při odesílání řídícího slova pak controller odesílá 55h. Tyto hodnoty by měl CPU kontrolovat. V případě že nejsou tyto hodnoty obdrženy, je nutno provést restart SPI interface zápisem dat FFh na SPI. FFh je adresa registru Serial Reset Address.

    Zde si dovolím malé odbočení. Pokud jste již někdo pracoval s CAN controllery od firmy Microchip (MCP2510/2515), jistě se vám bude zdát tento protokol na SPI trochu chudý. Controllery Microcipu mají interface na SPI daleko bohatější. Nedovolují jen prostý zápis a čtení, ale podporují celou skupinu mnohdy velice praktických příkazů:

Read Čtení
Write Zápis
Reset Softwarový reset
RTS - Request To Send Odeslání dat v zadaném bufferu
Read Status Rychlé zjištění stavu o tom zda byla přijata nějaká zpráva, zda bylo dokončeno odeslání zprávy
BitModify Modifikace bitů v registru pomocí masky (nepotřebujeme znát stav ostatních bitů)

Read RX buffer

(pouze MCP2515)

Čtení zadaného RX bufferu (ušetříme přenos 1 bajtu na rozdíl od Read)

Load TX buffer

(pouze MCP2515)

Zápis do zadaného TX bufferu (ušetříme přenos 1 bajtu na rozdíl od Write)

RX Status

(pouze MCP2515)

Rychle zjištění podrobnějšího stavu RX bufferů

    Maximální rychlost SPI rozhraní je 8Mhz. Minimální pak 0.5 MHz. Pro porovnání MCP2510 dovoluje maximální rychlost 5MHz, MCP2515 pak 10MHz.

Díl čtvrtý: Popis registrů

    Adresní prostor obvodů má velikost 256 bajtů. Následující obrázek uvádí strukturu pro obvod CC750. Odlišnosti u AN82527 a CC770 budou popsány vždy u konkrétní adresy.

Poznámka: Obrázek je klikací mapou, kliknutím na vybraný registr/adresu se přesunete na popis příslušné položky.

Reg CONTROL (00H)CONTROL (00H)

Bit 7 6 5 4 3 2 1 0
Název res CCE res Silent EIE SIE IE Init
Atributy rw rw r rw rw rw rw rw

 Aributy: r-jen pro čtení / w-jen pro zápis / rw-jen pro čtení

    Bity označené jako res (reserved) jsou čteny jako 0 a musí být zapisovány jako 0. Po hardwarovém resetu je registr nataven na hodnotu 01H.

CCE Change Configuration Enable
1 Nastavíme li tento bit na 1, můžeme zapisovat do Bit Timing registrů. Bit Init by měl být taktéž nastaven na 1.
0 Zápis do Bit Timing registrů není možný.

 

Silent Silent Mode
1 Silent mód je aktivní. V tomto režimu může obvod přijímat platné datové a rtr zprávy. Nemůže však zprávy odesílat, odesílá pouze recesivní bity.
0 Normální mód.

 

EIE Error Interrupt Enable
1 Povolení EIE. Ten je generován při nastavení příznaků BOff (Bus Off) nebo Warn ve Status registru, tzn. při abnormálním výskytu chyb při přenosu zpráv.
0 EIE zakázán. Interrupt není generován

 

SIE Status Change Interrupt Enable
1 Povoleni SIE. Interupt je generován při změně ve Status registru, tzn. je li detekována chyba na sběrnici (LEC) nebo při nastavení příznaků WakeUp (opuštění PowerDown nebo Sleep módu), TxOK (zpráva byla odeslána), RxOK(přijata zpráva). Pokud je SIE povolen, musíme počítat s tím, že při příjmu nebo odeslání zprávy dostaneme dvě přerušení na jednu zprávu.
0 Zápis do Bit Timing registrů není možný. 

 

IE Interrupt Output Enable
1 Interrupt pin je povolen.
0 Interrupt pin je zakázán.

 

Init Initialization
1 Softwarová inicializace povolena. Tento bit je nastaven z CPU pokud chceme nastavovat konfigurační registry CC750 nebo pokud obvod přejde do stavu Bus Off. Všechny přenosy na CAN nebo z CANu jsou zastaveny. Výstup Tx je v recesivním stavu.  Init by neměl být nastavován v pracovním režimu, pokud provádíme modifikaci dat pro odeslání některého  Message objektu (tzn. CPUUpd bit je nastaven).
0 Softwarová inicializace zakázána.

Reg STATUS (01H)STATUS (01H)

Bit 7 6 5 4 3 2 1 0
Název BOff Warn WakeUp RxOK TxOK LEC
Atributy r r r rw rw rw

Hodnota po HW resetu je 00H.

BOff Bus Off
1 Obvod je ve stavu Bus Off, tzn. TEC (Treansmit Error Counter) dosáhl hranice 256. V tomto stavu nemohou byt odesílány nebo přijímány. Je nastaven bit Init v Control registru. Z tohoto stavu se dostaneme resetem Init bitu. Poté jsou vynulovány registy TEC a REC, CC750 napočítá 128 paketů 11 nepřetržitých recesivních bitů na CAN sběrnici a Bus Off stav je opuštěn. 
0 Obvod není ve stavu Bus Off.

 

Warn Warning Status
1 Tento bit je nastaven pokud některý čítač TEC (Transmit Error Counter) nebo REC (Receive Error Counter) dosáhne hodnoty 96. 
0 Obvod není ve stavu Bus Off.

 

WakeUp Wake Up Status
1 Bit je nastaven po opuštění Power Down nebo Sleep módu. Nastavením bitu Sleep v registru CPU Interface přejde CC750 do Sleep módu. Dokud je obvod ve Sleep módu, je tento bit nastaven na 0. Ten je opuštěn pokud je detekována aktivita na CAN sběrnici nebo pokud CPU nastaví bit Sleep na 0. Následně je nastaven tento bit. Bit WakeUp je resetován čtením Status registru. 
0 Nenastala podmínka pro nastavení.

 

RxOK Receive Message Successfully
1 Tento bit je nastavován z CC750, resetován pak pouze z CPU. Bit je nastaven do 1 v případě, že od posledního nastavení do 0 z CPU byla přijata nepoškozená zpráva.
0 Nebyla přijata žádná zpráva.

 

TxOK Transmit Message Successfully
1  Tento bit je nastavován z CC750, resetován pak pouze z CPU. Bit je nastaven do 1 v případě, že od posledního nastavení do 0 z CPU byla bezchybně odeslána zpráva.
0 Nebyla odeslána žádná zpráva.

 

LEC Last Error Code
0 No error
1 Stuff Error - Detekována sekvence více než 5 stejných bitů na sběrnici
2 Form Error - Chyba v pevné části formátu zprávy (viz. CAN specifikace).
3 Acknowledgment Error - Odeslaná zpráva z tohoto zařízení nebyla potvrzena.
4 Bit 1 Error - Při odeslání zprávy generoval CC750 recesivní bit ale detekoval na sběrnici bit dominantní.
5 Bit 0 Error - Při odeslání zprávy generoval CC750 dominantní bit ale detekoval na sběrnici bit recesivní.
6 CRC Error - Chyba dat detekovaná z CRC kódu.
7 Unused

    Toto pole udává první chybu, která nastala při přenosu zprávy na CAN sběrnici. Jestliže byla zpráva přenesena (přijata/odeslána) bezchybně, je toto pole nastaveno na 0. Kód 7 může být použit pro kontrolu, zda nastal update dat.

Reg CPU INTERFACE (02H)CPU INTERFACE (02H)

Bit 7 6 5 4 3 2 1 0
Název OscSt res DMC PwD Sleep res res res
Atributy r r rw rw rw r r r

    Defaultní hodnota registru po HW resetu je 20h. Rezervované bity mají hodnotu při čtení 0.

OscSt Oscillator Stopped
1 Oscilátor je zastaven
0 Oscilátor běží.

    Jestliže dá CPU požadavek na Power Down nebo Sleep v okamžiku, kdy probíhá odeslání nebo příjem zprávy, je pozastaveno vypnutí oscilátoru dokud tento přenos není ukončen. CC750 indikuje Power Down nebo Sleep mód nastavením tohoto bitu.

DMC Divide Memory Clock
1 Memory clock MCLK je roven SCLK/2.
0 Memory clock MCLK je roven SCLK/2.

 

PwD Sleep Function
0 0 Power down mód ani Sleep mód nejsou aktivní.
0 1 Sleep mód je aktivní.
1 X Power Down mód není aktivní.

Reg: RESERVED (03H)RESERVED (03H)

    U obvodů CC750/CC770/AN82527 nemá žádnou funkci.

Reg: RESERVED (04H,05H)

RESERVED (04H,05H)

HIGH SPEED READ - CC770/AN82527

    U CC750 nemá žádnou funkci. U CC770 se používá v případech, kdy CPU nemůže čekat na ukončení čtení z pomalých registrů CC770 (Message Object) tzn.není možno použít signály READY a DSACK0. První čtení dáme požadavek na čtení, vrácená data jsou však neplatné. Druhé čtení z High Speed Read Registru nám vrátí požadovaná data. K podrobnějšímu studiu doporučuji datasheety těchto obvodů. 

Reg: GLOBAL MASK - STANDARD (06H, 07H)GLOBAL MASK - STANDARD (06H, 07H)

Bity - 06H 7 6 5 4 3 2 1 0
Název Msk28 Msk27 Msk26 Msk25 Msk24 Msk23 Msk22 Msk21
Atributy rw rw rw rw rw rw rw rw

 

Bit - 07H 7 6 5 4 3 2 1 0
Název Msk20 Msk19 Msk18 res res res res res
Atributy rw rw rw r r r r r

    Bity nejsou ovlivněny HW resetem. Rezervované bity jsou čteny jako 1. Maska je aplikována na zprávy se standardním 11 bitovým identifikátorem.

    Je-li bit v masce nastaven na 1, musí bit v příchozí zprávě odpovídat bitu v identifikátoru zprávy Message Objectu. Pokud je bit v masce nastaven na 0, je na této pozici akceptována jakákoliv hodnota bitu. Pokud je příchozí zpráva typu RTR a je použita globální maska, má zpráva s odpovědí identifikátor příslušného vyhovujícího Message Objektu.  To znamená že RTR zpráva může mít jiný identifikátor než vygenerovaná odpověď s daty.

Reg: GLOBAL MASK - EXTENDED (08H, 09H, 0AH, 0BH)GLOBAL MASK - EXTENDED (08H, 09H, 0AH, 0BH)

Bity - 08H 7 6 5 4 3 2 1 0
Název Msk28 Msk27 Msk26 Msk25 Msk24 Msk23 Msk22 Msk21
Atributy rw rw rw rw rw rw rw rw

 

Bity - 09H 7 6 5 4 3 2 1 0
Název Msk20 Msk19 Msk18 Msk17 Msk16 Msk15 Msk14 Msk13

Atributy

rw rw rw rw rw rw rw rw

 

Bity - 0AH 7 6 5 4 3 2 1 0
Název Msk12 Msk11 Msk10 Msk09 Msk08 Msk07 Msk06 Msk05
Atributy rw rw rw rw rw rw rw rw

 

Bity - 0BH 7 6 5 4 3 2 1 0
Název Msk04 Msk03 Msk02 Msk01 Msk00 res res res
Atributy rw rw rw rw rw r r r

    Bity nejsou ovlivněny HW resetem. Rezervované bity jsou čteny jako 0. Maska je aplikována na zprávy s rozšířeným 29 bitovým identifikátorem.

    Je-li bit v masce nastaven na 1, musí bit v příchozí zprávě odpovídat bitu v identifikátoru zprávy Message Objectu. Pokud je bit v masce nastaven na 0, je na této pozici akceptována jakákoliv hodnota bitu. Pokud je příchozí zpráva typu RTR a je použita globální maska, má zpráva s odpovědí identifikátor příslušného vyhovujícího Message Objektu.  To znamená že RTR zpráva může mít jiný identifikátor než vygenerovaná odpověď s daty.

Reg: MESSAGE 15 MASK (0CH, 0DH, 0EH, 0FH)MESSAGE 15 MASK (0CH, 0DH, 0EH, 0FH)

Bity - 0CH 7 6 5 4 3 2 1 0
Název Msk28 Msk27 Msk26 Msk25 Msk24 Msk23 Msk22 Msk21
Atributy rw rw rw rw rw rw rw rw

 

Bity - 0DH 7 6 5 4 3 2 1 0
Název Msk20 Msk19 Msk18 Msk17 Msk16 Msk15 Msk14 Msk13

Atributy

rw rw rw rw rw rw rw rw

 

Bity - 0EH 7 6 5 4 3 2 1 0
Název Msk12 Msk11 Msk10 Msk09 Msk08 Msk07 Msk06 Msk05
Atributy rw rw rw rw rw rw rw rw

 

Bity - 0FH 7 6 5 4 3 2 1 0
Název Msk04 Msk03 Msk02 Msk01 Msk00 MDir MXtd res
Atributy rw rw rw rw rw rw rw r

    Tato maska je určena pouze pro Message Object 15. Princip filtrování je schodný s globální maskou. Navíc obsahuje bity MDir a MXtd.

 

MXtd Mask Extended Bit
1 V příchozí zprávě se kontroluje zda souhlasí nastavení bitu Xtd v Message Objectu 15
0 Jsou přijímány standardní i rozšířené zprávy.

    Stejně tak funguje i bit MDir. Object 15 je sice určen pouze pro příjem zpráv, takže na první pohled se nám může zdát, že nastavení směru nemá význam. Nicméně nesmíme zapomenout na to že i Message Object určený pro odesílání zpráv kontroluje zda příchozí zpráva není typu RTR a nesouhlasí identifikátor a nemá náhodou odeslat odpověď. To znamená že tu například můžeme vymaskovat příjem pouze zpráv RTR. 

Reg: RECEIVE ERROR COUNTER (1FH)RECEIVE ERROR COUNTER (1FH)

Bity 7 6 5 4 3 2 1 0
Název RP REC6 REC5 REC4 REC3 REC2 REC1 REC0
Atributy r r r r r r r r

 

RP Receive Error Pasive
1 REC je nad hranicí Error Passive úrovně, která je definována v CAN specifikaci.
0 REC je pod hranicí Error Passive úrovně.

REC6-0 udávají aktuální hodnotu čítače REC (Receive Error Counter). Hodnoty jsou 127-0.

Reg: TRANSMIT ERROR COUNTER (2FH)TRANSMIT ERROR COUNTER (2FH)

Obsahuje 8-bitovou hodnotu TEC (Transimit Error Counter).

Reg: BIT TIMING 0 (3FH)BIT TIMING 0 (3FH)

Bity 7 6 5 4 3 2 1 0
Název SJW1 SJW0 BRP5 BRP4 BRP3 BRP2 BRP1 BRP0
Atributy rw rw rw rw rw rw rw rw

    Defaultní hodnota po HW resetu je 00h. SJW ( (Re) Synchronization Jump Width) udává maximální počet časových kvant o které může být kratší nebo delší než resynchronizace.Možné hodnoty jsou 0-3. BRP (Baud Rate Prescaler) slouží k nastavení délky časového kvanta: Tq = Tsclk*(BRP+1). 

    K výpočtu nastavení hodnot BIT TIMING registrů doporučuji použít nějaký program nebo webovou stránku, která výpočet nastavení udělá za nás. Protože tyto registry jsou shodné s obvodem 82527, můžete výpočet provést například zde.

Reg: BIT TIMING 1 (4FH)BIT TIMING 1 (4FH)

Bity 7 6 5 4 3 2 1 0
Název Spl TSeg22 TSeg21 TSeg20 TSeg13 TSeg12 TSeg11 TSeg10
Atributy rw rw rw rw rw rw rw rw

Defaultní hodnota po HW resetu je 00h.

Spl Sampling Mode
1 Každý bit je samplován 3x.
0 Bit je samplován 1x vzužívá se při vyšších přenosových rychlostech. .

 

TSeg2x Time Segment 2
0-7 Délka časového segmentu po samplovacím bodu.

 

TSeg1x Time Segment 1
0-15 Délka časového segmentu před samplovacím bodem.

    K výpočtu nastavení hodnot BIT TIMING registrů doporučuji použít nějaký program nebo webovou stránku, která výpočet nastavení udělá za nás. Protože tyto registry jsou shodné s obvodem 82527, můžete výpočet provést například zde.

Reg: INTERRUPT (5FH) INTERRUPT (5FH)

Bity 7 6 5 4 3 2 1 0
Název IntId
Atributy r

    Defaultní hodnota po H resetu je 00h. Registr je určen pouze pro čtení. Hodnota registru udává zdroj přerušení. Pokud žádný interrupt nečeká na vyřízení, je hodnota tohoto registru 0. Jestliže je nastaven bit SIE v Control registru a CC750 updatoval Status registr, je v tomto registru Interrupt hodnota 1.

Zdroj přerušení Hodnota Interrupt registru
None 00h
Status Register 01h
Message Object 15 02h
Message Object 1 03h
Message Object 2 04h
Message Object 3 05h
Message Object 4 06h
Message Object 5 07h
Message Object 6 08h
Message Object 7 09h
Message Object 8 0Ah
Message Object 9 0Bh
Message Object 10 0Ch
Message Object 11 0Dh
Message Object 12 0Eh
Message Object 13 0Fh
Message Object 14 10h

SERIAL RESET ADDRESS (FFH)
MESSAGE 1 (10H-1EH), MESSAGE 2 (20H-2EH)
MESSAGE 3 (30H-3EH), MESSAGE 4 (40H-4EH)
MESSAGE 5 (50H-5EH), MESSAGE 6 (60H-6EH)
MESSAGE 7 (70H-7EH), MESSAGE 8 (80H-8EH)
MESSAGE 9 (90H-9EH), MESSAGE 10 (A0H-AEH)
MESSAGE 11 (B0H-BEH), MESSAGE 12 (C0H-CEH)
MESSAGE 13 (D0H-DEH), MESSAGE 14 (E0H-EEH)

 

Každý Message Object je reprezentován pole dat s touto strukturou:

 

Address Function
Base Address + 0 Control 0
Base Address + 1 Control 1
Base Address + 2 Arbitration 0
Base Address + 3 Arbitration 1
Base Address + 4 Arbitration 2
Base Address + 5 Arbitration 3
Base Address + 6 Configuration
Base Address + 7 Data 0
Base Address + 8 Data 1
Base Address + 9 Data 2
Base Address + 10 Data 3
Base Address + 11 Data 4
Base Address + 12 Data 5
Base Address + 13 Data 6
Base Address + 14 Data 7

 

Control 0

Bity 7 6 5 4 3 2 1 0
Název MsgVal TxIE RxIE IntPnd
Atributy rw rw rw rw

Control 1

Bity 7 6 5 4 3 2 1 0
Název RmtPnd TxRqst MsgLst/CPUUpd NewData
Atributy rw rw rw rw

 

    Každý bit v tomto registru je uložen dvakrát. To umožňuje modifikovat bity registru bez znalosti hodnot ostatních bitech registru. Pro modifikaci těchto bitových párů se používají tyto párové variant:

 

Direction MSB LSB Příkaz
Write 0 0 Kombinace není nastavena
0 1 Reset (nastavení na 0)
1 0 Set (Nastavení na 1)
1 1 Neměnit -  bit zůstane nezměněn.
Read 0 1 Reset (bit má hodnotu 0)
1 0 Set (bit má hodnotu 1)

 

    V případě že například do registru Control 0 je zapsána hodnota 0b01111011, dává první párová dvojice bitů 01 příkaz k nastavení MsgVal na 0, druhá a čtvrtá párová dvojice obsahuje bity 11 a říká že nastavení TxIE a IntPnd má zůstat nezměněna. Třetí párová dvojice 10 pak dává požadavek na nastavení RxIE na 1.

 

MsgVal Message Valid
1 Příslušný Message Object je platný, tzn. že CC750 může k tomuto objektu přistupovat. Například v případě že měníme identifikátor zprávy, musíme nejprve příslušný objekt zneplatnit.
0 Message Objct není platný.

 

TxIE Transmit Interrupt Enable
1 Povolení přerušení (interruptu) při příchodu nové platné zprávy do tohoto Message Objectu. CPU musí tento bit smazat.
0 Přerušení je zakázáno.

 

RxIE Receive Interrupt Enable
1 Povolení přerušení po úspěšném odeslání z tohoto Message Objectu.  CPU musí tento bit smazat.
0 Přerušení je zakázáno.

 

lntPnd Interupt Pending
1 Bit je nastaven po úspěšném  příjmu nebo odeslání zprávy.
0 Od posledního smazání tohoto bitu nenastala žádná událost vyvolávající přerušení.

 

RmtPnd Remote Request Pending
1 Je požadováno odeslání tohoto objektu přijetím RTR zprávy. Bit má význam pouze při nastavení příslušného objektu pro odesílání zpráv (direction = transmit). Bit je smazán z CC750 automaticky po odeslání zprávy.
0 Žádný RTR požadavek nebyl přijat.

 

TxRqst Tranmit Request
1 Požadavek na odeslání tohoto objektu na sběrnici je požadován a nebyl ještě dokončen. Nastavením tohoto bitu je odeslána datová zpráva pokud je tento objekt nakonfigurován pro odeslání, v případě že je konfigurován pro příjem, je odeslána RTR zpráva. Bit je nastavován z CPU při požadavku na odeslání nebo při vyřizování požadavku RTR je-li objekt nakonfigurován pro odeslání. Je-li objekt konfigurován pro příjem, je nastavením tohoto bitu odeslán požadavek RTR.   Bit je smazán z CC750.
0 Objekt nečeká na odeslání.

 

MsgLst Message Lost - objekt konfigurován pro příjem z CAN sběrnice
1 Bit je nastaven pokud byla přijata nová zpráva a CPU ještě nestihl obsloužit předchozí.
0 Žádná zpráva nebyla ztracena.

 

CPUUpd CPU Updating - objekt konfigurován pro odesílání
1 Objekt nesmí být odeslán - CPU nastavením indikuje provádění změny dat.
0 Objekt může být odeslán.

 

 

NewData New Data
1 CPU nebo CC750 zapsal data do datové části zprávy.
0 Žádná nová data od posledního smazání bitu z CPU.

 

    Jestliže je objekt nastaven pro příjem, nastavuje CC750 bit NewData v okamžiku, kdy je přijata do tohoto objektu nová zpráva. CPU by měl tento bit vymazat před vyčtením této nové zprávy a po jejím vyčtení tento bit zkontrolovat, zda nebyl znovu nastaven a data nemohla být v průběhu čtení přepsána. Message object 15 obsahuje je na rozdíl od objektů 1 až 14 tvořen dvěma sadami registrů. Druhá shadow (stínová) sada slouží jako vyrovnávací paměť, čímž nám snižuje pravděpodobnost ztráty dat v případě, kdy by CPU nestihl předešlá data zpracovat. Zároveň nám tato sada zaručuje, že data ve viditelné sadě nebudou přepsána, tzn. že nemusíme kontrolovat bit NewData.  Naopak, u tohoto objektu provádíme čtení dat tak, že nejprve přečteme data a až následně resetujeme NewData a RmtPnd. Reset NewData a RmtPnd před resetováním IntPnd má za následek, že signál interrupt zůstane aktivní.

    Pokud je objekt nastaven pro odesílání zpráv, je nutno bit CPUUpd nastavit na 1 před započetím změny dat zprávy. Po nastavení dat je tento bit opět nastaven z CPU na 0. Tímto mechanismem je zabezpečeno, že zpráva nemůže být odeslána například RTR požadavkem v okamžiku, kdy provádíme změnu dat. Odeslání zprávy se provede nastavením NewData a TxRqst na 1.

    Jestliže čeká na odeslání několik objektů, je nejprve odeslána zpráva s nižším indexem objektu bez ohledu na prioritu identifikátoru (Při přístupu na CAN sběrnici má větší prioritu zpráva  nižším identifikátorem).

 

Arbitration 0

Bity 7 6 5 4 3 2 1 0
Název ID28 ID27 ID26 ID25 ID24 ID23 ID22 ID21
Atributy rw rw rw rw rw rw rw rw

 

Arbitration 1

Bity 7 6 5 4 3 2 1 0
Název ID20 ID19 ID18 ID17 ID16 ID15 ID14 ID13
Atributy rw rw rw rw rw rw rw rw

 

Arbitration 2

Bity 7 6 5 4 3 2 1 0
Název ID12 ID11 ID10 ID09 ID08 ID07 ID06 ID05
Atributy rw rw rw rw rw rw rw rw

 

Arbitration 3

Bity 7 6 5 4 3 2 1 0
Název ID04 ID03 ID02 ID01 ID00 reserved
Atributy rw rw rw rw rw r

 

Registry Arbitration 0-3 jsou obsahují identifikátor zprávy. V případě standardního identifikátoru je jeho 11 bitů uloženo v ID18-ID28.

 

Configuration Register

Bity 7 6 5 4 3 2 1 0
Název DLC Dir Xtd reserved
Atributy rw rw rw r

 

DLC Data Length Code
0-8 Počet datových bajtů ve zprávě. Platné hodnoty jsou 0-8

 

Dir Direction
1 Direction = transmit. Objekt je určen pro odeslání. Je li nastaven TxRqst je objekt s daty odeslán.
0 Direction = receive. Objekt je určen pro příjem. Je li nastaven TxRqst, je odeslána žádost o data (RTR). Je li zachycena zpráva jejíž identifikátor vyhovuje tomuto objektu, je zpráva do tohoto objektu uložena. 

 

Xtd Extended Identifier
1 Message object používá rozšířený 29 bitový identifikátor.
0 Message object používá standardní 11 bitový identifikátor. Nastavením tohoto bitu na 0 jsou bity 0-17 v registrech Arbitration nastaveny na 0.

 

    Po přijetí zprávy z CANu do tohoto objektu jsou bity identifikátoru, které jsou maskou nastaveny jako nekontrolované (bit v masce je nastaven na 0) nastaveny podle přijaté zprávy.

 

Reg: MESSAGE 15 (F0H-FEH) MESSAGE 15 (F0H-FEH)

 

    Tento objekt je určen pouze pro příjem zpráv. Bity TxRqst, TxIE a CPUUpd nemají význam. Objekt může aktuálně obsahovat až 2 zprávy, neboť obsahuje druhou sadu registrů do které je zapsána zpráva pokud není předchozí ještě z CPU zpracována. Tento objekt můžeme nastavit pro příjem standardních nebo rozšířených zpráv bite Xtd. Tento bit může být maskován a jsou přijímány oba typy zpráv.

 

RESERVED (6FH), RESERVED (7FH)
RESERVED (8FH), RESERVED (9FH)
RESERVED (AFH), RESERVED (BFH)
RESERVED (CFH), RESERVED (DFH)
RESERVED (EFH)

Registry nejsou využity.

Díl pátý: SPI prakticky

    Předchozí díly obsahovaly zatím jen teorii a data z datasheetu přeložené do češtiny. V tomto okamžiku se však již dostáváme k praktické realizaci. Protože však existuje spousta CPU ke kterým můžeme CAN controller CC750 připojit, pokusím se uváděné zdrojové kódy psát bez ohledu na cílový procesor. Proto vynechám například vlastní implementaci komunikace po SPI a budu používat obecné funkce SPI_Read a SPI_Write. Rovněž obsluha přerušení bude obsahovat pouze kód bezprostředně týkající se CC750 a ne obsluhu implementačně závislou jako je například mazání nejrůznějších "Flagů" v CPU. Může se ovšem stát, že část kódu bude přecejen ovlivněna mojí cílovou platformou (PIC 16F877 & překladač HiTech PICC v.7.8x). 

    Programování aplikací s jednočipy obvykle začíná dvěma kroky. Za prvé je třeba inicilizovat vstupy/výstupy a periferie. Za druhé je vhodné vytvořit si sadu maker typu eCAN_CS - signál enable CS obvodu CC750 do log 0, dCAN_CS - signál disable CS obvodu CC750 do log 1 a dále bitových masek pro nastavení registrů. První krok vynechám, je implementačně závislý  a přejdu  k druhému.

    V mém případě jsem si nachystal tato makra a definice:

//---------------------------------------------------------------
// Definice signalu

// e - Enable

// d - Disable

// i - Input

// o - Output
//---------------------------------------------------------------

#define oCAN_CS  RD0            // Signal CS na port D, bit 0
#define oCAN_RST RD4            // Signal RESET na port D, bit 4

#define iCAN_INT RB0            // Vstupni signal, INTERRUPT

#define eCAN_CS oCAN_CS   = 0   // Enable  CS
#define dCAN_CS oCAN_CS   = 1   // Disable CS

#define eCAN_RST oCAN_RST = 0   // Enable RESET
#define dCAN_RST oCAN_RST = 1   // Disagble RESET

 

//---------------------------------------------------------------
// Prikazy a konstanty pro SPI
//---------------------------------------------------------------

 

#define SPI_READ_CMD                0x00
#define SPI_WRITE_CMD               0x80

 

#define SPI_SYNC1                   0xAA   // Kontrola synchronizace (adresa)

#define SPI_SYNC2                   0x55   // Kontrola synchronizace (cmd)

 

//---------------------------------------------------------------
// Adresy registru
//---------------------------------------------------------------


#define CC750_CONTROL               0x00
#define CC750_STATUS                0x01
#define CC750_CPU_INTERFACE         0x02
#define CC750_GLOBAL_MASK_ST        0x06
#define CC750_GLOBAL_MASK_EXT       0x08
#define CC750_MSG15_MASK            0x0C
#define CC750_REC                   0x1F
#define CC750_TEC                   0x2F
#define CC750_BTR0                  0x3F
#define CC750_BTR1                  0x4F
#define CC750_INTERRUPT             0x5F
#define CC750_SERIAL_RESET_ADDRESS  0xFF

#define CC750_MSG1                  0x10
#define CC750_MSG2                  0x20
#define CC750_MSG3                  0x30
#define CC750_MSG4                  0x40
#define CC750_MSG5                  0x50
#define CC750_MSG6                  0x60
#define CC750_MSG7                  0x70
#define CC750_MSG8                  0x80
#define CC750_MSG9                  0x90
#define CC750_MSG10                 0xA0
#define CC750_MSG11                 0xB0
#define CC750_MSG12                 0xC0
#define CC750_MSG13                 0xD0
#define CC750_MSG14                 0xE0
#define CC750_MSG15                 0xF0
 

//---------------------------------------------------------------
// Bitove masky
//---------------------------------------------------------------


#define CC750_TRANSMIT_BUFFER       0b00000000    // 0x00
#define CC750_RECEIVE_BUFFER        0b00010000    // 0x10
#define CC750_STANDARD_IDENTIFIER   0b00000000    // 0x00
#define CC750_EXTENDED_IDENTIFIER   0b00100000    // 0x20

#define CC750_DLC0                  0b00000000    // 0x00
#define CC750_DLC1                  0b00010000    // 0x10
#define CC750_DLC2                  0b00100000    // 0x20
#define CC750_DLC3                  0b00110000    // 0x30
#define CC750_DLC4                  0b01000000    // 0x40
#define CC750_DLC5                  0b01010000    // 0x50
#define CC750_DLC6                  0b01100000    // 0x60
#define CC750_DLC7                  0b01110000    // 0x70
#define CC750_DLC8                  0b10000000    // 0x80

Poznámka: Překladač HiTech PICC dovoluje zadávat čísla v binárním tvaru, rozšiřuje tak definici jazyka C. Tvar je analogický zadání tvaru šestnástkového čísla, tzn.  takto  0bXXXXXXXX.

    Začneme komunikací prostřednictvím sběrnice SPI. Jak již bylo zmíněno, pro zápis a čtení z SPI budeme používat funkce SPI_Read a SPI_Write. Tyto funkce je třeba implementovat v závislosti na cílovém procesoru. Jejich hlavičky jsou definovány takto:

 

unsigned char SPI_Read(void);

void SPI_Write(unsigned char Data);

 

Pokud zasíláme adresu registru, musí být přijata zpět po SPI data  0xAA, v případě že zasíláme command, musíme obdržet zpět hodnotu 0x55. Pro kontrolu těchto hodnot budeme používat dvě globální proměnné:

 

unsigned char SPI_sync[2]

bool SPI_error = false;

 

Pro HiTech PICC: bit SPI_error;

  

 Zde následuje vlastní zdrojový kód s komentáři:

 

//---------------------------------------------------------------
// SPI_Read_Reg
// Cteni 1 bajtu ze zadane adresy obvodu CC750
//---------------------------------------------------------------
unsigned char SPI_Read_Reg(unsigned char Address)
{

    unsigned char Data;


    eCAN_CS;

    SPI_sync[0] = SPI_Write(Address);

    SPI_sync[1] = SPI_Write(SPI_READ_CMD | 0x01);

 

    if(SPI_sync[0]!=SPI_SYNC1 || SPI_sync[1]!=SPI_SYNC2)

        SPI_error = true;

 

    Data = SPI_Read();

    dCAN_CS;
    return Data;
}

//---------------------------------------------------------------
// SPI_Write_Reg
// Zapis 1 bajtu na zadanou adresu obvodu CC750
//---------------------------------------------------------------
void SPI_Write_Reg(unsigned char Address, unsigned char Data)
{
    eCAN_CS;

    SPI_sync[0] = SPI_Write(Address);

    SPI_sync[1] = SPI_Write(SPI_WRITE_CMD | 0x01);


    if(SPI_sync[0]!=SPI_SYNC1 || SPI_sync[1]!=SPI_SYNC2)

        SPI_error = true;


    SPI_Write(Data);


    dCAN_CS;

    return;
}

//---------------------------------------------------------------
// SPI_Read_Block
// Cteni bloku dat od zadane adresy z obvodu CC750, maximalni
// delka bloku je 15 bajtu
//---------------------------------------------------------------
void SPI_Read_Block(unsigned char Address, unsigned char Length, unsigned char *Data)
{
    unsigned char index;

    eCAN_CS;
 

    SPI_sync[0] = SPI_Write(Address);

    SPI_sync[1] = SPI_Write(SPI_READ_CMD | Length);

 

    if(SPI_sync[0]!=SPI_SYNC1 || SPI_sync[1]!=SPI_SYNC2)

        SPI_error = true;

 

    for(index=0; index<Length; index++)
    {

        *Data = SPI_Read();

        Data++;
    }
    dCAN_CS;

    return;
}

//---------------------------------------------------------------
// SPI_Write_Block
// Zapis bloku dat od zadane adresy do obvodu CC750, maximalni
// delka bloku je 15 bajtu
//---------------------------------------------------------------
void SPI_Write_Block(unsigned char Address, unsigned char Length, unsigned char *Data)
{
    unsigned char index;
    eCAN_CS;

    SPI_sync[0] = SPI_Write(Address);

    SPI_sync[1] = SPI_Write(SPI_READ_CMD | Length);

 

    if(SPI_sync[0]!=SPI_SYNC1 || SPI_sync[1]!=SPI_SYNC2)

        SPI_error = true;

 

    for(index=0; index<Length; index++)
    {

        SPI_Write(*Data);

        Data++;
    }
    dCAN_CS;

    return;
}

//---------------------------------------------------------------
// SPI_Reset
// Zaslani prikazu do obvodu CC750 k resetu jeho SPI rozhrani
//---------------------------------------------------------------
void SPI_Reset(void)
{

    unsigned char index;
    eCAN_CS;
    for(index=0;index<16;index++) SPI_Write(0xFF);
    dCAN_CS;
    return;
}
 

 

    Provádět kontrolu délky dat při přenosu bloku dat považuji na jednočipech za zbytečnou, každá tato kontrola zpomaluje program. Funkci SPI_Error používáme k resynchronzaci SPI rozhraní pokud dojde k nastavení SPI_error na hodnotu true.

 

Díl šestý: Inicializace

 

    V okamžiku, kdy máme hotovou komunikaci po SPI, včetně implementace funkcí SPI_Read a SPI_Write, můžeme začít pracovat s registry CAN řadiče. Pro práci s registry Control 0 a 1 jednotlivých Message objektů použijeme tyto funkce:

 

//---------------------------------------------------------------

// CAN_ReadMsgControl

// Cteni bitoveho paru registru Control1 a Control2 Message objektu
//---------------------------------------------------------------
unsigned char CAN_ReadMsgControl(unsigned char address, unsigned char pair)
{
    unsigned char temp;
        temp = SPI_Read_Byte(address);
        temp = temp >> (pair*2);
        temp = temp & 0b00000011;
        if(temp == 0b00000010) return 1;
    return 0;
}
 

//---------------------------------------------------------------

// CAN_WriteMsgControl

// Zapis do bitoveho paru registru Control1 a Control2 Message objektu
//---------------------------------------------------------------

void CAN_WriteMsgControl(unsigned char address, unsigned char pair, unsigned char value)
{
    unsigned char temp;
    if(value==0) //reset: 01
        temp = 0b00000010;
    else //set: 10
        temp = 0b00000001;
    temp = temp << (pair*2);
    temp = ~temp;
    SPI_Write_Byte(address,temp);
    temp = SPI_Read_Byte(address);
}

 

    Dále naimplemenujeme funkce pro nastavení pracovního a konfiguračního módu (registr CONTROL):

 

//---------------------------------------------------------------

// SetConfigMode

// Prepnuti do konfiguracniho modu

//---------------------------------------------------------------

void CAN_SetConfigMode(void)
{
    unsigned char data;
    data = SPI_Read_Byte(CC750_CONTROL);
    data = data | 0b01000001;
    SPI_Write_Byte(CC750_CONTROL,data);
}
 

//---------------------------------------------------------------

// CAN_SetNormalMode

// Prepnuti do pracovniho modu

// (lze komunikovat prostřednictvím CAN sbernice)

//---------------------------------------------------------------

void CAN_SetNormalMode(void)
{
    unsigned char data;
    data = SPI_Read_Byte(CC750_CONTROL);
    data = data & (~0b01000001);
    SPI_Write_Byte(CC750_CONTROL,data);
}

 

Další funkcí bude nastavení komunikační rychlosti:

 

//---------------------------------------------------------------

// CAN_SetBaudRate

// Nastaveni komunikacni rychlosti CAN sběrnice

// Parametr speed v KBaudech

//---------------------------------------------------------------

void CAN_SetBaudRate(unsigned int speed)
{
    switch(speed)
    {
    case 1000:
        SPI_Write_Byte(CC750_BTR0,0x00);
        SPI_Write_Byte(CC750_BTR1,0x16);
        break;
    case 500:
        SPI_Write_Byte(CC750_BTR0,0x80);
        SPI_Write_Byte(CC750_BTR1,0x7A);
        break;
    case 250:
        SPI_Write_Byte(CC750_BTR0,0x41);
        SPI_Write_Byte(CC750_BTR1,0x7A);
    break;
        case 100:
        SPI_Write_Byte(CC750_BTR0,0x44);
        SPI_Write_Byte(CC750_BTR1,0x7A);
        break;
    case 125:
    default:
        SPI_Write_Byte(CC750_BTR0,0x43);
        SPI_Write_Byte(CC750_BTR1,0x6b);
        break;
    }
}

 

Následují funkce pro nastavení globální masky zpráv:

 

//---------------------------------------------------------------

// CAN_ConfigureGlobalMaskSt

// Maska pro zpravy se standardnim (11 bitovym) identifikatorem

//---------------------------------------------------------------

void CAN_ConfigureGlobalMaskSt(unsigned int mask)
{
    unsigned char *p;
    mask = mask << 5;
    p = (unsigned char*)&mask;
    SPI_Write_Byte(0x06,*(p+1));
    SPI_Write_Byte(0x07,*(p+0));
}
 

//---------------------------------------------------------------

// CAN_ConfigureGlobalMaskExt

// Maska pro zpravy s rozsirenym (29 bitovym) identifikatorem

//---------------------------------------------------------------

void CAN_ConfigureGlobalMaskExt(unsigned long mask)
{
    unsigned char *p;
    mask = mask << 3;
    p = (unsigned char*)&mask;
    SPI_Write_Byte(0x08,*(p+3));
    SPI_Write_Byte(0x09,*(p+2));
    SPI_Write_Byte(0x0A,*(p+1));
    SPI_Write_Byte(0x0B,*(p+0));
}

 

Poslední funkcí v této kapitole bude funkce pro nastavení Message objektu:

 

//---------------------------------------------------------------

// CAN_ConfigureBuffer

// Zakladni konfigurace message objektu

//---------------------------------------------------------------

void CAN_ConfigureBuffer(unsigned char buffer, unsigned char status, unsigned long identifier)
{
    unsigned char temp;
    unsigned char *p;

    // Message object is invalid
    CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10), 3, 0);

    // Transmit Interrupt Disable
    CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10), 2, 0);

    // Receive Interrupt Disable
    CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10), 1, 0);

    // Interrupt Pending
    CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10), 0, 0);

    // Remote Transfer Pending
    CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10)+1, 3, 0);

    // Transmit Request
    CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10)+1, 2, 0);

    // Message Lost / CPU Updating
    CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10)+1, 1, 1);

    // New Data
    CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10)+1, 0, 0);

    //DLC
    temp = status | 0b00001111;
    if((status & CC750_RECEIVE_BUFFER)==CC750_RECEIVE_BUFFER)
    {
        bitclr(temp,3);
    }
    else
    {
        bitset(temp,3);
    }
    if((status & CC750_EXTENDED_IDENTIFIER)==CC750_EXTENDED_IDENTIFIER)
    {
        bitset(temp,2);
        identifier = identifier << 3;
        p = (unsigned char *)&identifier;
        SPI_Write_Byte(CC750_MSG1+(buffer*0x10)+2,*(p+3));
        SPI_Write_Byte(CC750_MSG1+(buffer*0x10)+3,*(p+2));
        SPI_Write_Byte(CC750_MSG1+(buffer*0x10)+4,*(p+1));
        SPI_Write_Byte(CC750_MSG1+(buffer*0x10)+5,*(p+0));
    }
    else
    {
        bitclr(temp,2);
        identifier = identifier << 5;
        p = (unsigned char *)&identifier;
        SPI_Write_Byte(CC750_MSG1+(buffer*0x10)+2,*(p+1));
        SPI_Write_Byte(CC750_MSG1+(buffer*0x10)+3,*(p+0));
        SPI_Write_Byte(CC750_MSG1+(buffer*0x10)+4,0);
        SPI_Write_Byte(CC750_MSG1+(buffer*0x10)+5,0);
    }
    SPI_Write_Byte(CC750_MSG1+(buffer*0x10)+6,temp);

    // Message object is valid
    CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10), 3, 1);
}

 

V další kapitole si probereme podrobně jak uvedené funkce pracují a ukážeme si jak odeslat zprávu.

 

Díl sedmý: Komunikace

 

     Hned na začátku začneme  funkcí pro elementární odeslání zprávy na CAN. Tato funkce CAN_SendMessage má tři parametry, číslo bufferu (message objektu), ukazatel na pole dat a délku dat. Maximální délka těchto dat je limitována délkou CANovské zprávy, tj. 8 bajtů. V případě, že chceme odesílat delší data, je třeba provést fragmentaci těchto dat na bloky s tuto maximální délkou.

 

//---------------------------------------------------------------

// CAN_SendMessage

// Odeslani zpravy na CAN
//---------------------------------------------------------------
 

void CAN_SendMessage(unsigned char buffer, unsigned char *data, unsigned char length)
{
    if(CAN_ReadMsgControl(CC750_MSG1+(buffer*0x10)+1, 2)==0)
    {
        // CPU Updating
        CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10)+1, 1, 1);

        // New Data
        CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10)+1, 0, 1);

        SPI_Write_Block(CC750_MSG1+(buffer*0x10)+7, length, data);

        // CPU Updating
        CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10)+1, 1, 0);

        // Transmit Request
        CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10)+1, 2, 1);
    }
}

 

    Uvedená funkce začíná testem, zda hodnota bitového páru TxRqst v registru CONTROL_1 má hodnotu reset, tzn. 01, tedy hodnotu reset. Pokud je tato hodnota nastavena na Reset, nečeká buffer na odeslání a je tedy možno jej použít. Nastavení CPU Updating zabezpečuje, že nemůže dojít k modifikaci obsahu objektu přijetím zprávy z CANu v průběhu jeho modifikace z CPU.  Pomocí funkce SPI_Write_Block jsou zapsány datové bajty zprávy. Transmit Request pak nastavuje požadavek na odeslání dat.

 

//---------------------------------------------------------------

// CAN_GetMessage

// Cteni zpravy
//---------------------------------------------------------------
 

unsigned char CAN_GetMessage(unsigned char buffer, unsigned char *data)
{
    unsigned char tmp;

    // New Data = 1 ?
    //if(CAN_ReadMsgControl(CC750_MSG1+(buffer*0x10)+1, 0)==0) return 0;

    tmp = CAN_ReadMsgControl(CC750_MSG1+(buffer*0x10)+1, 0);

    // New Data = 0
    CAN_WriteMsgControl(CC750_MSG1+(buffer*0x10)+1, 0, 0);

    SPI_Read_Block(CC750_MSG1+(buffer*0x10)+7, 8, data);

    if(tmp==0) return 0;
    return buffer;
}