我的第一个问题。我根本不是专业的程序员。只是为了在家里玩得开心所以我真的不知道我要问的正确的术语。
我想创建一个CAN总线网关,我有NXP DEVKIT-MPC5748G。所有CAN总线都设置好并适用于tx和rx。现在我想创建一个操作不同CAN控制器的功能。其中8个,所以我希望不要写8个相同的功能只有使用CAN控制器不同。
您可以像这样设置控制器:
CAN_1.CTRL1.B.CLKSRC = 0;
只是设置时钟源的示例。
CAN_1有一个像这样的宏:
#define CAN_1 (*(volatile struct CAN_1_7_tag *) 0xFBEC0000UL)
在那个结构中,有许多联合用于访问所有寄存器。现在我想写一个函数,我可以传递一个参数来告诉使用什么CAN控制器。我可以使用开关/案例样式的方式来做这件事,但代码会很长很难看。
我想做这样的事情:
void Tx_Msg("type???" gwport, int mb, uint32_t id) {
gwport.[mb].CS.B.CODE = 0x8; }
但我无法弄清楚如何做到这一点。可以吗?
感谢正确方向的所有帮助。 :)
最好的问候,Joakim
编辑澄清
CAN_1_7_tag结构:
struct CAN_1_7_tag {
CAN_MCR_tag MCR; /* Module Configuration Register */
CAN_CTRL1_tag CTRL1; /* Control 1 register */
CAN_TIMER_tag TIMER; /* Free Running Timer */
uint8_t CAN_reserved0[4];
CAN_RXMGMASK_tag RXMGMASK; /* Rx Mailboxes Global Mask Register */
CAN_RX14MASK_tag RX14MASK; /* Rx 14 Mask register */
CAN_RX15MASK_tag RX15MASK; /* Rx 15 Mask register */
CAN_ECR_tag ECR; /* Error Counter */
CAN_ESR1_tag ESR1; /* Error and Status 1 register */
CAN_IMASK2_tag IMASK2; /* Interrupt Masks 2 register */
CAN_IMASK1_tag IMASK1; /* Interrupt Masks 1 register */
CAN_IFLAG2_tag IFLAG2; /* Interrupt Flags 2 register */
CAN_IFLAG1_tag IFLAG1; /* Interrupt Flags 1 register */
CAN_CTRL2_tag CTRL2; /* Control 2 register */
CAN_ESR2_tag ESR2; /* Error and Status 2 register */
uint8_t CAN_reserved1[8];
CAN_CRCR_tag CRCR; /* CRC Register */
CAN_RXFGMASK_tag RXFGMASK; /* Rx FIFO Global Mask register */
CAN_RXFIR_tag RXFIR; /* Rx FIFO Information Register */
CAN_CBT_tag CBT; /* CAN Bit Timing Register */
uint8_t CAN_reserved2[24];
CAN_IMASK3_tag IMASK3; /* Interrupt Masks 3 Register */
uint8_t CAN_reserved3[4];
CAN_IFLAG3_tag IFLAG3; /* Interrupt Flags 3 Register */
uint8_t CAN_reserved4[8];
CAN_MB_tag MB[64];
uint8_t CAN_reserved5[1024];
CAN_RXIMR_tag RXIMR[96]; /* Rx Individual Mask Registers */
uint8_t CAN_reserved6[512];
CAN_FDCTRL_tag FDCTRL; /* CAN FD Control Register */
CAN_FDCBT_tag FDCBT; /* CAN FD Bit Timing Register */
CAN_FDCRC_tag FDCRC; /* CAN FD CRC Register */
};
MCR寄存器的示例。所有寄存器的工作方式相同。
typedef union CAN_MCR_union_tag { /* Module Configuration Register */
vuint32_t R;
struct {
vuint32_t MDIS:1; /* Module Disable */
vuint32_t FRZ:1; /* Freeze Enable */
vuint32_t RFEN:1; /* Rx FIFO Enable */
vuint32_t HALT:1; /* Halt FlexCAN */
vuint32_t NOTRDY:1; /* FlexCAN Not Ready */
vuint32_t WAKMSK:1; /* Wake Up Interrupt Mask */
vuint32_t SOFTRST:1; /* Soft Reset */
vuint32_t FRZACK:1; /* Freeze Mode Acknowledge */
vuint32_t SUPV:1; /* Supervisor Mode */
vuint32_t SLFWAK:1; /* Self Wake Up */
vuint32_t WRNEN:1; /* Warning Interrupt Enable */
vuint32_t LPMACK:1; /* Low-Power Mode Acknowledge */
vuint32_t WAKSRC:1; /* Wake Up Source */
vuint32_t _unused_18:1;
vuint32_t SRXDIS:1; /* Self Reception Disable */
vuint32_t IRMQ:1; /* Individual Rx Masking And Queue Enable */
vuint32_t DMA:1; /* DMA Enable */
vuint32_t _unused_14:1;
vuint32_t LPRIOEN:1; /* Local Priority Enable */
vuint32_t AEN:1; /* Abort Enable */
vuint32_t FDEN:1; /* CAN FD operation enable */
vuint32_t _unused_10:1;
vuint32_t IDAM:2; /* ID Acceptance Mode */
vuint32_t _unused_7:1;
vuint32_t MAXMB:7; /* Number Of The Last Message Buffer */
} B;
} CAN_MCR_tag;
希望这是你要求的。
如果CAN_1定义为:
#define CAN_1 (*(volatile struct CAN_1_7_tag *) 0xFBEC0000UL)
然后CAN_1是CAN_1_7_tag类型的结构,位于0xFBEC0000UL。 volatile
限定符用于向编译器指示不应优化CAN_1的任何相关内容,因为它可能被其他线程更改。
您可以将CAN控制器作为指针传递:
void Tx_Msg(volatile struct CAN_1_7_tag *p_gwport, int mb, uint32_t id)
{
p_gwport->CTRL1.B.CLKSRC = 0;
p_gwport->MB[mb].CS.B.CODE = 0x8;
}
然后,当调用此函数从特定的CAN控制器发送消息时,您可以使用:
Tx_Msg(&CAN_1, 12, 25);
Tx_Msg(&CAN_4, 21, 45);
再次感谢您的帮助。 CAN网关作为原型启动并运行。这是我的“最终”代码。
/********************************************************************************/
/* Tx function for FlexCAN 1-7 */
/********************************************************************************/
void Tx_Msg_1_7(volatile struct CAN_1_7_tag *port, uint32_t mb, uint32_t dlc, uint32_t id, uint8_t txData[])
{
int i = 0; // Used in for loops
port->MB[mb].CS.B.CODE = 0x8; // MB TX inactive
port->MB[mb].CS.B.DLC = dlc; // Message length max 8 bytes
port->MB[mb].CS.B.RTR = 0; // Remote frame disable
port->MB[mb].CS.B.SRR = 1; // Not used with standard id
if (id > 0x7FF) // CAN id 29 bits
{
port->MB[mb].CS.B.IDE = 1; // EXT CAN id
port->MB[mb].ID.B.ID_STD = id >> 18 & 0x7FF; // CAN id (11 bits)
port->MB[mb].ID.B.ID_EXT = id & 0x3FFFF; // CAN id (18 bits)
}
else // CAN id 11 bits
{
port->MB[mb].CS.B.IDE = 0; // STD CAN id
port->MB[mb].ID.B.ID_STD = id; // CAN id (11 bits)
port->MB[mb].ID.B.ID_EXT = 0; // CAN id (18 bits), always 0
}
for(i = 0; i < dlc; i++)
{
port->MB[mb].DATA.B[i] = txData[i];
}
port->MB[mb].CS.B.CODE = 0xC; // MB once transmit data
}