#include "F2837xD_device.h"
#include "F2837xD_Examples.h"
#include "C2373.h"
#include "hw_can.h"
static const uint16_t g_ui16CANBitValues[] =
{
0x1100, // TSEG2 2, TSEG1 2, SJW 1, Divide 5
0x1200, // TSEG2 2, TSEG1 3, SJW 1, Divide 6
0x2240, // TSEG2 3, TSEG1 3, SJW 2, Divide 7
0x2340, // TSEG2 3, TSEG1 4, SJW 2, Divide 8
0x3340, // TSEG2 4, TSEG1 4, SJW 2, Divide 9
0x3440, // TSEG2 4, TSEG1 5, SJW 2, Divide 10
0x3540, // TSEG2 4, TSEG1 6, SJW 2, Divide 11
0x3640, // TSEG2 4, TSEG1 7, SJW 2, Divide 12
0x3740 // TSEG2 4, TSEG1 8, SJW 2, Divide 13
};
void InitCan_C2373(void)
{
InitCan_commom_C2373(CANA_BASE);
InitCan_commom_C2373(CANB_BASE);
// InitCana_C2373();
// InitCanb_C2373();
}
void InitCan_commom_C2373(Uint32 regbase)
{
int i;
HWREG(regbase + CAN_O_CTL) = CAN_CTL_INIT;
// HWREG(regbase + CAN_O_CTL) = CAN_CTL_SWR;
while(HWREG(regbase + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY);
/*设置寄存器写方向,将arb和mctl写入消息对象*/
HWREGH(regbase + CAN_O_IF1CMD + 2) = (CAN_IF1CMD_DIR | CAN_IF1CMD_MASK | CAN_IF1CMD_ARB | CAN_IF1CMD_CONTROL) >> 16;
HWREG(regbase + CAN_O_IF1MSK) = 0;//|CAN_IF1MSK_MXTD;
HWREG(regbase + CAN_O_IF1ARB) = CAN_IF1ARB_MSGVAL;
HWREG(regbase + CAN_O_IF1MCTL) = CAN_IF1MCTL_UMASK;
while(HWREG(regbase + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY);
HWREGH(regbase + CAN_O_IF2CMD + 2) = (CAN_IF2CMD_DIR | CAN_IF2CMD_MASK | CAN_IF2CMD_ARB | CAN_IF2CMD_CONTROL) >> 16;
HWREG(regbase + CAN_O_IF2MSK) = 0;//CAN_IF2MSK_MSK_M|CAN_IF2MSK_MXTD;
HWREG(regbase + CAN_O_IF2ARB) = CAN_IF2ARB_MSGVAL | CAN_IF2ARB_DIR;
HWREG(regbase + CAN_O_IF2MCTL) = CAN_IF2MCTL_UMASK | CAN_IF2MCTL_RMTEN;
/*1-16是接收,17-32是发送*/
for(i=1;i<=15;i++)
{
HWREGH(regbase + CAN_O_IF1CMD) =i;
while(HWREG(regbase + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY);
HWREGH(regbase + CAN_O_IF2CMD) =i+16;
while(HWREG(regbase + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY);
}
/*最后一个设置为EOB,表示fifo的末尾*/
HWREG(regbase + CAN_O_IF1MCTL) = CAN_IF1MCTL_EOB;
HWREG(regbase + CAN_O_IF2MCTL) = CAN_IF2MCTL_EOB;
HWREGH(regbase + CAN_O_IF1CMD) =16;
while(HWREG(regbase + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY);
HWREGH(regbase + CAN_O_IF2CMD) =32;
while(HWREG(regbase + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY);
/*设置寄存器读方向,清除mctl的intpnd和newdat位*/
HWREGH(regbase + CAN_O_IF1CMD + 2) = (CAN_IF1CMD_TXRQST | CAN_IF1CMD_CLRINTPND) >> 16;
HWREGH(regbase + CAN_O_IF2CMD + 2) = (CAN_IF2CMD_TXRQST | CAN_IF2CMD_CLRINTPND) >> 16;
for(i=1;i<=16;i++)
{
HWREGH(regbase + CAN_O_IF1CMD) =i;
while(HWREG(regbase + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY);
HWREGH(regbase + CAN_O_IF2CMD) =i+16;
while(HWREG(regbase + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY);
}
HWREG(regbase + CAN_O_ES);
/*使能if3的自动更新功能*/
// HWREG(regbase + CAN_O_IF3UPD) = 0x0000FFFF;
/*波特率设置500k*/
// CANBitRateSet(regbase, 200000000, 500000);
HWREG(regbase + CAN_O_CTL) |= CAN_CTL_DAR;//CAN_CTL_TEST;
HWREG(regbase + CAN_O_CTL) |= CAN_CTL_ABO;
// HWREG(CANA_BASE + CAN_O_TEST) = CAN_TEST_EXL;
HWREG(regbase + CAN_O_CTL) = HWREG(regbase + CAN_O_CTL)&(~CAN_CTL_INIT);
}
uint32_t CANBitRateSet(uint32_t ui32Base, uint32_t ui32SourceClock, uint32_t ui32BitRate)
{
uint32_t ui32DesiredRatio;
uint32_t ui32CANBits;
uint32_t ui32PreDivide;
uint32_t ui32RegValue;
uint16_t ui16CANCTL;
// ASSERT(ui32BitRate != 0);
// Calculate the desired clock rate.
ui32DesiredRatio = ui32SourceClock / ui32BitRate;
// If the ratio of CAN bit rate to processor clock is too small or too
// large then return 0 indicating that no bit rate was set.
// ASSERT(ui32DesiredRatio <= (CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR));
// ASSERT(ui32DesiredRatio >= (CAN_MIN_PRE_DIVISOR * CAN_MIN_BIT_DIVISOR));
// Make sure that the Desired Ratio is not too large. This enforces the
// requirement that the bit rate is larger than requested.
if((ui32SourceClock / ui32DesiredRatio) > ui32BitRate)
{
ui32DesiredRatio += 1;
}
// Check all possible values to find a matching value.
while(ui32DesiredRatio <= CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR)
{
// Loop through all possible CAN bit divisors.
for(ui32CANBits = CAN_MAX_BIT_DIVISOR;
ui32CANBits >= CAN_MIN_BIT_DIVISOR;
ui32CANBits--)
{
// For a given CAN bit divisor save the pre divisor.
ui32PreDivide = ui32DesiredRatio / ui32CANBits;
// If the calculated divisors match the desired clock ratio then
// return these bit rate and set the CAN bit timing.
if((ui32PreDivide * ui32CANBits) == ui32DesiredRatio)
{
// Start building the bit timing value by adding the bit timing
// in time quanta.
ui32RegValue =
g_ui16CANBitValues[ui32CANBits - CAN_MIN_BIT_DIVISOR];
// To set the bit timing register, the controller must be
// placed
// in init mode (if not already), and also configuration change
// bit enabled. The state of the register should be saved
// so it can be restored.
ui16CANCTL = HWREG(ui32Base + CAN_O_CTL);
HWREG(ui32Base + CAN_O_CTL) = ui16CANCTL | CAN_CTL_INIT |
CAN_CTL_CCE;
// Now add in the pre-scalar on the bit rate.
ui32RegValue |=
((ui32PreDivide - 1) & CAN_BTR_BPR_M) |
(((ui32PreDivide - 1) << 10) & CAN_BTR_BRPE_M) ;
// Set the clock bits in the and the bits of the
// pre-scalar.
HWREG(ui32Base + CAN_O_BTR) = ui32RegValue;
// Restore the saved CAN Control register.
HWREG(ui32Base + CAN_O_CTL) = ui16CANCTL;
// Return the computed bit rate.
return(ui32SourceClock / ( ui32PreDivide * ui32CANBits));
}
}
// Move the divisor up one and look again. Only in rare cases are
// more than 2 loops required to find the value.
ui32DesiredRatio++;
}
return(0);
}
int CanAppTx(int no,CanFrame *tx_frame)
{
Uint32 regbase;
Uint32 cmd_regdata=0;
Uint32 arb_regdata=0;
Uint32 mctl_regdata=0;
Uint32 dataA=0,dataB=0;
int i,j;
if(no==0)
{
regbase = CANA_BASE;
}
else
{
regbase = CANB_BASE;
}
if(HWREG(regbase + CAN_O_ES) & CAN_ES_EWARN)
{
HWREG(regbase + CAN_O_CTL) = CAN_CTL_INIT;
HWREG(regbase + CAN_O_CTL) |= CAN_CTL_SWR;
HWREG(regbase + CAN_O_CTL) |= CAN_CTL_DAR;
HWREG(regbase + CAN_O_CTL) |= CAN_CTL_ABO;
HWREG(regbase + CAN_O_CTL) = HWREG(regbase + CAN_O_CTL)&(~CAN_CTL_INIT);
return(0);
}
while(HWREG(regbase + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY);
cmd_regdata = CAN_IF1CMD_ARB | CAN_IF1CMD_MASK | CAN_IF1CMD_CONTROL;
HWREGH(regbase + CAN_O_IF1CMD + 2) = cmd_regdata>>16;
/*从17-32中寻找可以发送的邮箱*/
for(i=17;i<=32;i++)
{
HWREGH(regbase + CAN_O_IF1CMD) =i;
while(HWREG(regbase + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY);
if((HWREG(regbase + CAN_O_IF1MCTL)&CAN_IF1MCTL_TXRQST)==0)
{
break;
}
}
if(i>=33)
{
return(-1);
}
/*读取当前邮箱配置信息*/
cmd_regdata = CAN_IF1CMD_CONTROL;// | CAN_IF1CMD_ARB | CAN_IF1CMD_MASK;
HWREGH(regbase + CAN_O_IF1CMD + 2) = cmd_regdata>>16;
HWREGH(regbase + CAN_O_IF1CMD) =i;
while(HWREG(regbase + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY);
// arb_regdata = HWREG(regbase + CAN_O_IF1ARB);
mctl_regdata = HWREG(regbase + CAN_O_IF1MCTL);
/*写信息到邮箱配置*/
cmd_regdata = CAN_IF1CMD_DIR | CAN_IF1CMD_ARB | CAN_IF1CMD_CONTROL |C