Hi everyone,
I want to develop my CAN driver for the UT32M0R500 micrcontroller. I send a CAN frame on the principal bus. I should get the the send frame signal on the Tx pin.
However, when I tested it, it produced the the following result.
The green signal is the generated signal on the Tx pin.
I tried to modify my code and I tried to add a transciever to look at the CAN HIGH, but nothing has changed (the transciever return a 0 signal... It seems that it does not understand the Tx input)
So I decided to inspire my code from the example provided by CAES : it produces the same thing.
I directly tested the exemple provided by CAES : it produces the same thing.
Then, I wrote the simpliest test as possible that follows :
MAIN.C
#include "typesGeneral.h" #include "canRegisterTypes.h" #define C_CAN_MODE_RESET 0x01 #define C_CAN_ACCEPTANCE_CODE_RESET_VALUE 0x00 #define C_CAN_ACCEPTANCE_MASK_RESET_VALUE 0x00 #define C_CAN_COMMAND_START_TRANSMIT 0x01 #define C_CAN_SJW_SHIFT_LEFT (6) #define C_CAN_SAM_SHIFT_LEFT (7) #define C_CAN_TSEG2_SHIFT_LEFT (4) #define C_CAN_TXID_1_ID_SHIFT_RIGHT (3) #define C_CAN_TXID_2_ID_SHIFT_LEFT (5) #define C_CAN_SFF_ID_1_TX_SHIFT_RIGHT (3) #define C_CAN_SFF_ID_2_TX_SHIFT_LEFT (5) /* ------------------------------------------------------------------------- */ // Nominal CAN base /* ------------------------------------------------------------------------- */ volatile static t_canRegisters *s_canNominal = (t_canRegisters *) 0x40023000; typedef struct { // Bus timing 1 t_int8u syncJumpWidth : 2; t_int8u baudRatePreScalar : 6; // Bus timing 2 t_int8u sampleMode : 1; t_int8u timeSegment2 : 3; t_int8u timeSegment1 : 4; // Hardware Address t_int8u hardwareAddress; } t_canInitData; /* ------------------------------------------------------------------------- */ // MAIN /* ------------------------------------------------------------------------- */ int main() { volatile t_canRegisters *l_can; t_canInitData l_canInitData; /* Init of the timings */ l_canInitData.syncJumpWidth = 0; l_canInitData.baudRatePreScalar= 24; l_canInitData.sampleMode = 0; l_canInitData.timeSegment1 = 4; l_canInitData.timeSegment2 = 3; l_canInitData.hardwareAddress = 0xAA; /* Choose the nominal CAN*/ l_can = s_canNominal; /* Enter reset mode */ l_can->can.control = C_CAN_MODE_RESET; l_can->can.command = 0x00; /* Init acceptance masks */ l_can->can.acceptCode = C_CAN_ACCEPTANCE_CODE_RESET_VALUE; l_can->can.acceptMask = C_CAN_ACCEPTANCE_MASK_RESET_VALUE; /* Init of the timings */ l_can->can.busTiming_0 = (l_canInitData.syncJumpWidth<<C_CAN_SJW_SHIFT_LEFT) | (l_canInitData.baudRatePreScalar); l_can->can.busTiming_1 = (l_canInitData.sampleMode<<C_CAN_SAM_SHIFT_LEFT) | (l_canInitData.timeSegment2<<C_CAN_TSEG2_SHIFT_LEFT) |(l_canInitData.timeSegment1); // Set operating mode l_can->can.control &= (~C_CAN_MODE_RESET); /* Set ID, RTR and DLC in the register */ l_can->can.TX_ID_1 = 0x00; l_can->can.TX_ID_2 = 0x08; /* Change the data in the TX buffer */ l_can->can.TX_data[0] = 1; l_can->can.TX_data[1] = 2; l_can->can.TX_data[2] = 3; l_can->can.TX_data[3] = 4; l_can->can.TX_data[4] = 5; l_can->can.TX_data[5] = 6; l_can->can.TX_data[6] = 7; l_can->can.TX_data[7] = 8; while(1) { // Set operating mode l_can->can.control &= (~C_CAN_MODE_RESET); /* Start can transmission*/ l_can->can.command = C_CAN_COMMAND_START_TRANSMIT; } return(0); }
TYPESGENERAL.H
/** * @file typesGeneral.h * * @brief Native types and main constants redefinition * * @details This file redefines the CPU architecture native types and the main constants * (True / False / Null pointer) to be used in the whole project. * * @addtogroup generalities * @{ */ #ifndef INC_TYPES_GENERAL_H #define INC_TYPES_GENERAL_H /* ------------------------------------------------------------------------- */ // CONSTANTS DEFINITION /* ------------------------------------------------------------------------- */ /** * @brief Definition of the TRUE value */ #ifndef C_TRUE #define C_TRUE (1 == 1) #endif /** * @brief Definition of the FALSE value */ #ifndef C_FALSE #define C_FALSE (!C_TRUE) #endif /** * @brief Definition of the NULL-pointer value */ #ifndef C_NULL #define C_NULL ((void*) 0L) #endif /* ------------------------------------------------------------------------- */ // TYPES DEFINITION /* ------------------------------------------------------------------------- */ /** * @brief 8-bit signed integer */ typedef signed char t_int8; /** * @brief 8-bit unsigned integer */ typedef unsigned char t_int8u; /** * @brief 16-bit signed integer */ typedef signed short t_int16; /** * @brief 16-bit unsigned integer */ typedef unsigned short t_int16u; /** * @brief 32-bit signed integer */ typedef signed long t_int32; /** * @brief 32-bit unsigned integer */ typedef unsigned long t_int32u; /** * @brief 64-bit unsigned integer */ typedef unsigned long long t_int64u; /** * @brief Boolean type */ typedef unsigned short t_bool; #endif /* INC_TYPES_GENERAL_H */ /** @}*/
CANREGISTERTYPES.H
/** * @file canRegisterTypes.h * * @brief Define all the registers used by the CAN peripheral. * * @addtogroup can * @{ */ #ifndef INC_CAN_TYPES_DEF_H #define INC_CAN_TYPES_DEF_H /* ------------------------------------------------------------------------- */ // FILE INCLUSION /* ------------------------------------------------------------------------- */ #include "typesGeneral.h" /* ------------------------------------------------------------------------- */ // PRIVATE CONSTANTS DEFINITION /* ------------------------------------------------------------------------- */ #define C_CAN_BUF_SIZE 8 /* ------------------------------------------------------------------------- */ // TYPES DEFINITION /* ------------------------------------------------------------------------- */ /*------------------------ BASI-CAN -----------------------*/ typedef struct { t_int8u control; /*!< Offset: 0x00: Control Register (R/W) */ t_int8u command; /*!< 0x01: Command ( /W) */ t_int8u status; /*!< 0x02: Status (R/ ) */ t_int8u interrupt; /*!< 0x03: Interrupt (reset on read, except bit0) (R/ ) */ t_int8u acceptCode; /*!< 0x04: Acceptance Code: RESET MODE ONLY (R/W) */ t_int8u acceptMask; /*!< 0x05: Acceptance Mask: RESET MODE ONLY (R/W) */ t_int8u busTiming_0; /*!< 0x06: Bus Timing 0: RESET MODE ONLY (R/W) */ t_int8u busTiming_1; /*!< 0x07: Bus Timing 1: RESET MODE ONLY (R/W) */ t_int8u reserved_0; /*!< 0x08: reserved (R/ ) */ t_int8u reserved_1; /*!< 0x09: reserved (R/ ) */ t_int8u TX_ID_1; /*!< 0x0A: Transmit ID 1: OPERATE MODE ONLY (R/W) */ t_int8u TX_ID_2; /*!< 0x0B: Transmit ID 2: OPERATE MODE ONLY (R/W) */ t_int8u TX_data[C_CAN_BUF_SIZE]; /*!< 0x0C..0x13: Transmit Data Regs: OPERATE MODE ONLY (R/W) */ t_int8u RX_ID_1; /*!< 0x14: Receive ID 1 (R/ ) */ t_int8u RX_ID_2; /*!< 0x15: Receive ID 2 (R/ ) */ t_int8u RX_data[C_CAN_BUF_SIZE]; /*!< 0x16..0x1D: Receive Data Regs (R/ ) */ t_int8u reserved_2; /*!< 0x1E: reserved (R/ ) */ t_int8u clockDivider; /*!< 0x1F: Clock Divider (R/W) */ } t_basiCan; /*------------------------ PELI-CAN -----------------------*/ typedef struct { t_int8u frameInfo; /*!< Offset: 0x10: Frame Info Register: RX=R/O, TX=W/O (R/W) */ t_int8u ID_1; /*!< 0x11: Transmit ID 1: RX=R/O, TX=W/O (R/W) */ t_int8u ID_2; /*!< 0x12: Transmit ID 2: RX=R/O, TX=W/O (R/W) */ t_int8u data[C_CAN_BUF_SIZE]; /*!< 0x13..0x1A: Data: RX=R/O, TX=W/O (R/W) */ t_int8u nextFrameInfo; /*!< 0x1B: Next Frame Info: RECEIVE-PATH ONLY (R/ ) */ t_int8u nextId1; /*!< 0x1C: Next Frame ID1: RECEIVE-PATH ONLY (R/ ) */ } t_peliCanSff; typedef struct { t_int8u frameInfo; /*!< Offset: 0x10: Frame Info Register: RX=R/O, TX=W/O (R/W) */ t_int8u ID_1; /*!< 0x11: Transmit ID 1: RX=R/O, TX=W/O (R/W) */ t_int8u ID_2; /*!< 0x12: Transmit ID 2: RX=R/O, TX=W/O (R/W) */ t_int8u ID_3; /*!< 0x13: Transmit ID 3: RX=R/O, TX=W/O (R/W) */ t_int8u ID_4; /*!< 0x14: Transmit ID 4: RX=R/O, TX=W/O (R/W) */ t_int8u data[C_CAN_BUF_SIZE]; /*!< 0x15..0x1C: Data: RX=R/O, TX=W/O (R/W) */ } t_peliCanEff; typedef struct { t_int8u acceptCode_0; /*!< Offset: 0x10: Acceptance Code 0 Register (R/W) */ t_int8u acceptCode_1; /*!< 0x11: Acceptance Code 1 (R/W) */ t_int8u acceptCode_2; /*!< 0x12: Acceptance Code 2 (R/W) */ t_int8u acceptCode_3; /*!< 0x13: Acceptance Code 3 (R/W) */ t_int8u acceptMask_0; /*!< 0x14: Acceptance Mask 0 (R/W) */ t_int8u acceptMask_1; /*!< 0x15: Acceptance Mask 1 (R/W) */ t_int8u acceptMask_2; /*!< 0x16: Acceptance Mask 2 (R/W) */ t_int8u acceptMask_3; /*!< 0x17: Acceptance Mask 3 (R/W) */ t_int8u reserved_0; /*!< 0x18: reserved (R/ ) */ t_int8u reserved_1; /*!< 0x19: reserved (R/ ) */ t_int8u reserved_2; /*!< 0x1A: reserved (R/ ) */ t_int8u reserved_3; /*!< 0x1B: reserved (R/ ) */ t_int8u reserved_4; /*!< 0x1C: reserved (R/ ) */ } t_peliCanAccept; typedef struct { t_int8u mode; /*!< Offset: 0x00: Mode Register (R/W) */ t_int8u command; /*!< 0x01: Command ( /W) */ t_int8u status; /*!< 0x02: Status (R/ ) */ t_int8u interrupt; /*!< 0x03: Interrupt (reset on read, except bit0) (R/ ) */ t_int8u interruptEnable; /*!< 0x04: Interrupt Enable (R/W) */ t_int8u reserved_0; /*!< 0x05: reserved (R/ ) */ t_int8u busTiming_0; /*!< 0x06: Bus Timing 0 (see "** note" below) (R/W) */ t_int8u busTiming_1; /*!< 0x07: Bus Timing 1 ("** note") (R/W) */ t_int8u reserved_1; /*!< 0x08: reserved (R/ ) */ t_int8u reserved_2; /*!< 0x09: reserved (R/ ) */ t_int8u reserved_3; /*!< 0x0A: reserved (R/ ) */ t_int8u arbitrationLostCapture; /*!< 0x0B: Arbitration Lost Capture (R/ ) */ t_int8u errorCodeCapture; /*!< 0x0C: Error Code Capture (R/ ) */ t_int8u errorWarningLimit; /*!< 0x0D: Error Warning Limit ("** note") (R/W) */ t_int8u receiveErrorCounter; /*!< 0x0E: Receive Error Counter ("** note") (R/W) */ t_int8u transmitErrorCounter; /*!< 0x0F: Transmit Error Counter ("** note") (R/W) */ union { t_peliCanSff SFF_Frame; /*!< 0x10..0x1C: SFF Frame: OPERATE MODE ONLY */ t_peliCanEff EFF_Frame; /*!< 0x10..0x1C: EFF Frame: OPERATE MODE ONLY */ t_peliCanAccept AcceptCodeMask; /*!< 0x10..0x1C: Acceptance Code/Mask: RESET MODE ONLY */ }; t_int8u RXMessageCounter; /*!< 0x1D: Receive Message Counter (R/ ) */ t_int8u reserved_4; /*!< 0x1E: reserved (R/ ) */ t_int8u ClockDivider; /*!< 0x1F: Clock Divider (R/W) */ } t_peliCan; // ** note: writeable in RESET MODE only /*------------------------ BASIC-CAN vs PELI-CAN Determination ------------------------ */ // used to set/determine (a) "BasiCAN vs PeliCAN" and (b) "SFF vs EFF" (EFF available in PeliCAN only) typedef struct { t_int8u reset; /*!< 0x00: SET bit0 to reset (R/W) */ t_int8u reserved_0[15]; /*!< 0x01..0x0F: reserved (R/ ) */ t_int8u FrameInfo; /*!< 0x10: Frame Info Register (check bit7 for EFF) (R/W) */ t_int8u reserved_1[14]; /*!< 0x11..0x1E: reserved (R/ ) */ t_int8u canMode; /*!< 0x1F: Clock Divider (check bit7 for PeliCAN) (R/W) */ } t_genericCanAccess; /*------------------------ BASIC-CAN / PELI-CAN ------------------------ */ typedef struct { //union //{ t_basiCan can; //t_peliCan can; //t_genericCanAccess GenericCAN_Access; //}; } t_canRegisters; #endif /** @}*/
....... And the result whas exactly the same !!!
Do you see any clear error that could generate this strange behaviour ?
According to tou, what could be the origin of the problem ?
I thank you for your help by advance.
Best regards.
Rémi G
Thank you, I didn't know about that ! I connected the Tx and the Rx together and it works !