分类: 嵌入式
2013-10-28 09:27:04
can总线的初始化,是can总线程序的基础,也是难点,因为初始化需要完成各个寄存器的设置,这就需要对can协议的扎实掌握和对can术语的深刻理解。
can总线的初始化主要包括模式寄存器的设置,中断方式的设置,波特率的设置,还有错误警告,发送优先级模式寄存器的设置等。can总线的初始化程序如下所示:
void InitCAN(eCANNUM CanNum)
{
HwEnCAN(CanNum); //硬件使螚can控制器,包括引脚初始化,外部。具体分析如下HwEnCAN函数。
SoftRstCAN(CanNum); //通过在can控制器的某位写入1,来达到软件复位的目的。具体分析如下SoftRstCAN函数。
CANEWL(CanNum).Bits.EWL_BIT = USE_EWL_CAN[CanNum];//设置错误警告寄存器,错误警告默认计数为96. 在CAN 操作过程中,该值与Tx 和Rx 错误计数器的计数器相比较,如果其中一个计数值与该值相等,CANSR 的错误状态(ES)位置位。ES为1时-错误状态:发送和接收错误计数器的计数值或其中一个的计数值已经达到出错警告界限寄存器中设置的阈值。
CANBTR(CanNum).Word = USE_BTR_CAN[CanNum];// 初始化波特率。
//初始化中断为非向量中断
VICDefVectAddr =(UINT32)CANIntPrg;
VICIntEnable |=(1<<19)|(1<<(20+ CanNum))|(1<<(26+ CanNum));//每个CAN 控制器可产生3 种中断请求:接收、发送和“其它状态”,这里分别使能这3个中断。
CANIER(CanNum).Word= USE_INT_CAN[CanNum];//CAN模块的中断使能方式.
//配置验收滤波器(旁路状态)
CANAFMR.Bits.AccBP_BIT =1;
//初始化模式
CANMOD(CanNum).Bits.TPM_BIT = USE_TPM_CAN[CanNum];//设置发送优先模式寄存器。TPM位设置为1时---3 个发送缓冲区的优先级由各自的Tx 优先级域决定。
CANMOD(CanNum).Bits. LOM_BIT = USE_MOD_CAN[CanNum];//设置只听模式寄存器。LOM为设置为0时---当CAN 总线成功接收到信息时,CAN 控制器产生应答。
//初始化接收环形缓冲区
CANRcvBufApp.FullFlag1=CANRcvBufApp.FullFlag2=CANRcvBufApp.FullFlag3=CANRcvBufApp.FullFlag4=0;
CANRcvBufApp.ReadPoint1=CANRcvBufApp.ReadPoint2=CANRcvBufApp.ReadPoint3=CANRcvBufApp.ReadPoint4=0;
CANRcvBufApp.WritePoint1=CANRcvBufApp.WritePoint2=CANRcvBufApp.WritePoint3=CANRcvBufApp.WritePoint4=0;
//启动CAN,通过在can模式寄存器的一位写入‘1’,来软件启动。详细的请看SoftEnCAN函数,函数如下。
SoftEnCAN(CanNum);
}
void HwEnCAN(eCANNUM CanNum)
{
CANAFMR.Bits.AccBP_BIT =1;//旁路滤波,不管什么样的ID报文,一律接受。
PCONP |= ((UINT32)0x01 << (13+CanNum));
switch(CanNum)
{
case CAN1://can控制器1引脚初始化
PINSEL1 &= ~((UINT32)0x03 << 18);
PINSEL1 |= ((UINT32)0x01 << 18);
break;
case CAN2://can控制器2引脚初始化
PINSEL1 &= ~((UINT32)0x0F << 14);
PINSEL1 |= ((UINT32)0x05 << 14);
break;
case CAN3://can控制器3引脚初始化
PINSEL1 &= ~((UINT32)0x0F << 10);
PINSEL1 |= ((UINT32)0x06 << 10);
break;
case CAN4:can控制器4引脚初始化
PINSEL0 |= ((UINT32)0x0F << 24);
break;
default:
break;
}
}
UINT32 SoftRstCAN(eCANNUM CanNum)
{
CANMOD(CanNum).Bits.RM_BIT =1;//这里看到对相应can控制器的RM位进行置位,现在can处于复位模式。
return(!CANMOD(CanNum).Bits.RM_BIT );//确保的确是职位了RM位,如果返回值为‘1’的话,说明错误。所以main函数中我们可以用while来等待这个位设置为1位置。
}
UINT32 SoftEnCAN(eCANNUM CanNum)
{
CANMOD(CanNum).Bits.RM_BIT =0;//把RM位设置为0时---CAN 控制器正常工作,某些寄存器不能写入。
return(CANMOD(CanNum).Bits.RM_BIT );
}
最后,我要介绍一下模式寄存器,关于模式寄存器的各个位的功能
typedef union _canmod_
{
UINT32 Word;
struct {
UINT32 RM_BIT :1; //定义RM位,它是复位位。
UINT32 LOM_BIT :1; //定义LOM位,也就是只听模式位。
UINT32 STM_BIT :1; //定义STM位,当该位为‘0’的时候,发送的信息必须被答应才被认可,当该位为‘1’的时候,自测试模式,cancmr的srr位一起使用,可以达到自发自收的效果。
UINT32 TPM_BIT :1; //定义TPM位,位‘0’时3个发送缓冲区的优先级由各自的can id决定,位‘1’时,3个发送缓冲区的优先级由各自的Tx优先级域决定。
UINT32 SM_BIT :1; //定义SM位,睡眠模式。
UINT32 RPM_BIT :1; //定义RPM位,为‘0’
UINT32 RSV_BIT1 :1; //保留位
UINT32 TM_BIT :1; //定义TM位,测试模式
UINT32 RSV_BIT24 :24; //保留位
}Bits;
}uCANMod,*P_uCANMod;