#include
#include "sys.h"
#include "delay.h"
#include "CAN.h"
CAN_msg CAN_TxMsg; //发送邮箱
CAN_msg CAN_RxMsg; //接收邮箱
u8 CAN_TxRdy=0; //发送就绪标志
u8 CAN_RxRdy=0; //接收就绪标志
u8CAN_TDTxR_DLC; //数据长度,最高为1111
/////////////////CAN设置/////////////////////////////////////
void CAN_setup(void)
{
u8 brp=20; //获取主时钟频率 APB1ENR时钟频率为36M
RCC->APB1ENR|=1<25; //RCC_APB1ENR_CANEN; //开启CAN使能时钟
RCC->APB2ENR|=1<0; //RCC_APB2ENR_AFIOEN; //开启辅助时钟
AFIO->MAPR&=0XFFFF9FFF;//清除复用重映射配置寄存器13,14位,
AFIO->MAPR|=0X00004000;//配置为10;IO口重映射至PB8.PB9
RCC->APB2ENR|=1<3; //RCC_APB2ENR_IOPBEN;//开启IO口B时钟
GPIOB->CRH&=~(0X0F<0);//清除PB8状态寄存器~(1111<0)
GPIOB->CRH|=(0X08<0);//设定pb8上下拉输入1000
GPIOB->CRH&=~(0XF<4);//清空pb9状态寄存器
GPIOB->CRH|=(0X0B<4);//设定PB9推挽输出
MY_NVIC_Init(1,1,USB_HP_CAN_TX_IRQChannel,2);//发送中断使能
MY_NVIC_Init(1,1,USB_LP_CAN_RX0_IRQChannel,2);//接收中断使能
CAN->MCR|=1<4;//置NART位为1,禁止自动重传 403
CAN->MCR|=1<0; //置INRQ位为1,请求初始化 403 (CAN_MCR_NART|CAN_MCR_INRQ);//初始化模式,禁止重传
CAN->IER|=1<0;//发送邮箱空中断允许 409
CAN->IER|=1<1; //FIFO0消息挂号中断允许 409 (CAN_IER_FMPIE0|CAN_IER_TMEIE);
//brp=(brp/18)/500000;//波特率设置500Kb/s,计算波特率分频器值
CAN->BTR&=~(((0X03)<24)|((0x07)<20)|((0x0f)<16)|(0x1ff)); //清空BTR寄存器相关位 410 400
CAN->BTR|=(((1&0X03)<24)|((7&0X07)<20)|((8&0X0F)<16)|(brp-1));//设置BTR寄存器 410 400
}
//////////////从初始化模式进入正常工作模式/////////////////////////////////////////////
void CAN_start(void)
{
CAN->MCR&=0xfffffffe;
while(CAN->MSR&(0x01));
CAN->MCR&=0xfffffffd; //清零INRQ位,进入正常模式
//while(~(CAN->MSR&0x01)); //等待硬件对INAK位清零,确认退出初始化
}
//////////////设置工作模式///////////////////////////////////////////
void CAN_testmode(void)
{
CAN->BTR&=0x3fffffff;//清空BTR 的SILM LBKM位410
CAN->BTR|=0XC0000000;//设置BTR 的LBKM位为高,环回模式 410
}
///////////////检测发送邮箱为空////////////////////////////////////////////////
void CAN_waitReady(void)
{
while((CAN->TSR&(1<26))==0); //检测发送邮箱0标志位,为1则为空,为0不为空
CAN_TxRdy=1; //置发送就绪标志位为1
}
///////////////发送数据//////////////////////////////////////
void CAN_wrMsg(CAN_msg *msg)
{
CAN->sTxMailBox[0].TIR=(u8)0; //发送邮箱标示符寄存器复位 清零
if(msg->format ==STANDARD_FORMAT)//如果是标准11位标示符帧
{msg->id=33 ;
CAN->sTxMailBox[0].TIR|=0x4200000;//(msg->id<21)|CAN_ID_STD; //则标示符左移21位,高11位为标准标示符,标示符选择位置0 411
}
else //如果是29位扩展标示符帧
{
CAN->sTxMailBox[0].TIR|=(u8)(msg->id<3)|CAN_ID_EXT; //标示符左移3位,高29位为标示符(扩展标示符)标示符选择位置1 411
}
if(msg->type==DATA_FRAME) //如果消息为数据帧
{
CAN->sTxMailBox[0].TIR|=CAN_RTR_DATA;//标示符寄存器RTR位置0,数据帧
}
else //如果为远程帧
{
CAN->sTxMailBox[0].TIR|=CAN_RTR_REMOTE;//标示符寄存器RTR置1,远程帧
}
CAN->sTxMailBox[0].TDLR=(((u8)msg->data[3]<24)|((u8)msg->data[2]<16)|((u8)msg->data[1]<8)|((u8)msg->data[0])); //数据位低4字节写入发送邮箱0
CAN->sTxMailBox[0].TDHR=(((u8)msg->data[7]<24)|((u8)msg->data[6]<16)|((u8)msg->data[5]<8)|((u8)msg->data[4])); //数据位高4字节写入发送邮箱0
CAN->sTxMailBox[0].TDTR&=0xfffffff0;//设置消息长度DLC清0
CAN->sTxMailBox[0].TDTR|=0x00000004;//设置消息长度为4个字节
CAN->IER|=1<0; //发送邮箱空中断使能 409
CAN->sTxMailBox[0].TIR|=1<0; //发送消息411
}
///////////////读取邮箱数据并释放//////////////////////////////////////////////////////////////
void CAN_rdMsg(CAN_msg *msg)
{
if((CAN->sFIFOMailBox[0].RIR&CAN_ID_EXT)==0) //如果是11位标准标识符
{
msg->format=STANDARD_FORMAT; //消息为标准格式
msg->id=(u32)0x000007ff&(CAN->sFIFOMailBox[0].RIR>>21); //标示符等于标示符位右移21位与0x7ff
}
else //如果是29位扩展标识符
{
msg->format=EXTENDED_FORMAT; //消息格式为扩展标示符格式
msg->id=(u32)0x0003ffff&(CAN->sFIFOMailBox[0].RIR>>3);//标示符等于标示符位右移3位与上0x3ffff
}
if((CAN->sFIFOMailBox[0].RIR&CAN_RTR_REMOTE)==0) //如果消息为数据帧
{
msg->type=DATA_FRAME;
}
else //数据位远程帧
{
msg->type=REMOTE_FRAME;
}
msg->len = (unsigned char)0x0000000F & CAN->sFIFOMailBox[0].RDTR; //读取数据长度
msg->data[0] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR); //读取数据低4字节
msg->data[1] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 8);
msg->data[2] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 16);
msg->data[3] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 24);
msg->data[4] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR); //读取数据高4字节
msg->data[5] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 8);
msg->data[6] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 16);
msg->data[7] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 24);