u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{
u16 i=0;
if(tsjw==0||tbs2==0||tbs1==0||brp==0)
return 1;
tsjw-=1;//先减去1.再用于设置
tbs2-=1;
tbs1-=1;
brp-=1;
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOB->CRH&=0XFFFFFF00;
GPIOB->CRH|=0X000000B8; //PB8 RX上拉输入,PB9 TX推挽输出
GPIOB->ODR|=3<<8;
RCC->APB1ENR|=1<<25; //使能CAN时钟 CAN使用的是APB1的时钟(max:36M)
CAN->MCR=0x00000000; //退出睡眠模式(同时设置所有位为0)
CAN->MCR|=1<<0; //请求CAN进入初始化模式
while((CAN->MSR&1<<0)==0)
{
i++;
if(i>100)
return 2;//进入初始化模式失败
}
CAN->MCR|=0<<7; //非时间触发通信模式
CAN->MCR|=0<<6; //软件自动离线管理
CAN->MCR|=0<<5; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
CAN->MCR|=1<<4; //禁止报文自动传送
CAN->MCR|=0<<3; //报文不锁定,新的覆盖旧的
CAN->MCR|=0<<2; //优先级由报文标识符决定
CAN->BTR=0x00000000;//清除原来的设置.
CAN->BTR|=mode<<30; //模式设置 0,普通模式;1,回环模式;
CAN->BTR|=tsjw<<24; //重新同步跳跃宽度(Tsjw)为tsjw+1 个时间单位
CAN->BTR|=tbs2<<20; //Tbs2=tbs2+1个时间单位
CAN->BTR|=tbs1<<16; //Tbs1=tbs1+1 个时间单位
CAN->BTR|=brp<<0; //分频系数(Fdiv)为brp+1,设置tq
//波特率:Fpclk1/((Tbs1+Tbs2+1)*Fdiv) = 36000000/(1+TS1+1+TS2+1)(BRP+1)
CAN->MCR&=~(1<<0); //请求CAN退出初始化模式
while((CAN->MSR&1<<0)==1)
{
i++;
if(i>0XFFF0)
return 3;//退出初始化模式失败
}
CAN->MSR 最低位不清零,程序总是等待超时就返回了。
|