Hey guys,
I have a problem with initialization of the FlexCAN registers. I'm using a MCF52235 with a system clock of 60MHz and an external oscillator clock of 25 MHz.
I want to set the FlexCAN baudrate to 1 Mbit/s but I'm not sure if I understand the meaning of the registers PRESDIV, PROPSEG, PSEG1 and PSEG2.
Is there an easy algorithm with which I can calculate the register values or is it more complicated.
Thx
Solved! Go to Solution.
Ok, I think the code below is the right solution for a clock source with 25 MHz.
Baudrate = Clock source / (PRESDIV * (PROPSEG + PSEG1 + PSEG2 +1))
PRESDIV = 1..256
PROPSEG = 1..8
PSEG1 = 1..8
PSEG2 = 1..8
Based on MQX FlexCAN initialization
uint_32 FLEXCAN_Initialize( /* FlexCAN base address */ pointer can_ptr, /* Bit rate in Kbps */ uint_32 frequency){ /* Body */ volatile FLEXCAN_REG_STRUCT_PTR can_reg_ptr; volatile FLEXCAN_MSGBUF_STRUCT_PTR can_bufstruct_ptr; can_reg_ptr = (FLEXCAN_REG_STRUCT_PTR)can_ptr; /* ** Select the clock source ** Default: external oscillator: 25MHz. ** used because of tighter tolerance */ can_reg_ptr->CANCTRL &= FFFFDFFF; //delets SYS_CLK bit /* ** Baud rate = System clock / (PRESDIV + PROPSEG + PSEG1 + PSEG2 +1) ** ** Register values: Value -1 e.g.: ** PRESDIV should be 1 so the register value must be 0x00 ** */ switch (frequency) { case (20): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x2, PSEG1 = 0x8, PSEG2 = 0x8, PRESDIV = 50 ** ** sampling point @ 68% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) |MCF_FlexCAN_CANCTRL_RJW(1) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(7) | MCF_FlexCAN_CANCTRL_PRESDIV(49)); break; case (50): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x2, PSEG1 = 0x8, PSEG2 = 0x3, PRESDIV = 25 ** ** sampling point @ 85% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(1) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(2) | MCF_FlexCAN_CANCTRL_PRESDIV(24)); break; case (100): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x2, PSEG1 = 0x8, PSEG2 = 0x8, PRESDIV = 10 ** ** sampling point @ 68% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(1) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(7) | MCF_FlexCAN_CANCTRL_PRESDIV(9)); break; case (125): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x2, PSEG1 = 0x8, PSEG2 = 0x3, PRESDIV = 10 ** ** sampling point @ 85% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(1) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(2) | MCF_FlexCAN_CANCTRL_PRESDIV(9)); break; case (250): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x2, PSEG1 = 0x8, PSEG2 = 0x3, PRESDIV = 5 ** ** sampling point @ 85% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(1) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(2) | MCF_FlexCAN_CANCTRL_PRESDIV(4)); break; case (500): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x4, PSEG1 = 0x8, PSEG2 = 0x8, PRESDIV = 2 ** ** sampling point @ 68% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(3) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(7) | MCF_FlexCAN_CANCTRL_PRESDIV(1)); break; case (1000): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x1 ** RJW = 0x4, PSEG1 = 0x8, PSEG2 = 0x8, PRESDIV = 1 ** ** sampling point @ 68% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(3) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(7) | MCF_FlexCAN_CANCTRL_PRESDIV(0)); break; default: return (FLEXCAN_INVALID_FREQUENCY); return (FLEXCAN_OK);} /* Endbody */
Ok, I think the code below is the right solution for a clock source with 25 MHz.
Baudrate = Clock source / (PRESDIV * (PROPSEG + PSEG1 + PSEG2 +1))
PRESDIV = 1..256
PROPSEG = 1..8
PSEG1 = 1..8
PSEG2 = 1..8
Based on MQX FlexCAN initialization
uint_32 FLEXCAN_Initialize( /* FlexCAN base address */ pointer can_ptr, /* Bit rate in Kbps */ uint_32 frequency){ /* Body */ volatile FLEXCAN_REG_STRUCT_PTR can_reg_ptr; volatile FLEXCAN_MSGBUF_STRUCT_PTR can_bufstruct_ptr; can_reg_ptr = (FLEXCAN_REG_STRUCT_PTR)can_ptr; /* ** Select the clock source ** Default: external oscillator: 25MHz. ** used because of tighter tolerance */ can_reg_ptr->CANCTRL &= FFFFDFFF; //delets SYS_CLK bit /* ** Baud rate = System clock / (PRESDIV + PROPSEG + PSEG1 + PSEG2 +1) ** ** Register values: Value -1 e.g.: ** PRESDIV should be 1 so the register value must be 0x00 ** */ switch (frequency) { case (20): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x2, PSEG1 = 0x8, PSEG2 = 0x8, PRESDIV = 50 ** ** sampling point @ 68% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) |MCF_FlexCAN_CANCTRL_RJW(1) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(7) | MCF_FlexCAN_CANCTRL_PRESDIV(49)); break; case (50): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x2, PSEG1 = 0x8, PSEG2 = 0x3, PRESDIV = 25 ** ** sampling point @ 85% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(1) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(2) | MCF_FlexCAN_CANCTRL_PRESDIV(24)); break; case (100): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x2, PSEG1 = 0x8, PSEG2 = 0x8, PRESDIV = 10 ** ** sampling point @ 68% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(1) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(7) | MCF_FlexCAN_CANCTRL_PRESDIV(9)); break; case (125): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x2, PSEG1 = 0x8, PSEG2 = 0x3, PRESDIV = 10 ** ** sampling point @ 85% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(1) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(2) | MCF_FlexCAN_CANCTRL_PRESDIV(9)); break; case (250): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x2, PSEG1 = 0x8, PSEG2 = 0x3, PRESDIV = 5 ** ** sampling point @ 85% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(1) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(2) | MCF_FlexCAN_CANCTRL_PRESDIV(4)); break; case (500): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x0 ** RJW = 0x4, PSEG1 = 0x8, PSEG2 = 0x8, PRESDIV = 2 ** ** sampling point @ 68% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(3) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(7) | MCF_FlexCAN_CANCTRL_PRESDIV(1)); break; case (1000): /* ** PROPSEG = 0x8, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 0x1 ** RJW = 0x4, PSEG1 = 0x8, PSEG2 = 0x8, PRESDIV = 1 ** ** sampling point @ 68% */ can_reg_ptr->CANCTRL |= (0 | MCF_FlexCAN_CANCTRL_PROPSEG(7) | MCF_FlexCAN_CANCTRL_RJW(3) | MCF_FlexCAN_CANCTRL_PSEG1(7) | MCF_FlexCAN_CANCTRL_PSEG2(7) | MCF_FlexCAN_CANCTRL_PRESDIV(0)); break; default: return (FLEXCAN_INVALID_FREQUENCY); return (FLEXCAN_OK);} /* Endbody */