414 lines
15 KiB
C
414 lines
15 KiB
C
#include "can.h"
|
||
#include "system.h"
|
||
/**************************************************************************
|
||
Function: CAN1 initialization
|
||
Input : tsjw:Resynchronize the jump time unit, Scope: 1 ~ 3;
|
||
tbs2:Time unit of time period 2, range :1~8;
|
||
tbs1:Time unit of time period 1, range :1~16;
|
||
brp :Baud rate divider, range :1 to 1024;(We're actually going to add 1, which is 1 to 1024) tq=(brp)*tpclk1
|
||
mode:0, normal mode;1. Loop mode;
|
||
Output : 0- Initialization successful;Other - initialization failed
|
||
Note: none of the entry parameters (except mode) can be 0
|
||
函数功能:CAN1初始化
|
||
入口参数:tsjw:重新同步跳跃时间单元,范围:1~3;
|
||
tbs2:时间段2的时间单元,范围:1~8;
|
||
tbs1:时间段1的时间单元,范围:1~16;
|
||
brp :波特率分频器,范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1
|
||
mode:0,普通模式;1,回环模式;
|
||
返回 值:0-初始化成功; 其他-初始化失败
|
||
注意:入口参数(除了mode)均不能为0
|
||
波特率/Baud rate=Fpclk1/((tbs1+tbs2+1)*brp),Fpclk1为36M
|
||
=42M/((3+2+1)*6)
|
||
=1M
|
||
**************************************************************************/
|
||
u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
|
||
{
|
||
GPIO_InitTypeDef GPIO_InitStructure;
|
||
NVIC_InitTypeDef NVIC_InitStructure;
|
||
u16 i=0;
|
||
if(tsjw==0||tbs2==0||tbs1==0||brp==0)return 1;
|
||
tsjw-=1; //Subtract 1 before setting //先减去1.再用于设置
|
||
tbs2-=1;
|
||
tbs1-=1;
|
||
brp-=1;
|
||
|
||
//使能相关时钟
|
||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//使能PORTB时钟
|
||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟
|
||
//初始化GPIO
|
||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0| GPIO_Pin_1;
|
||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
|
||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
|
||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
|
||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
|
||
GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化PB8 PB9
|
||
// //引脚复用映射配置
|
||
GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_CAN1); //GPIOB8复用为CAN1
|
||
GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_CAN1); //GPIOB9复用为CAN1
|
||
|
||
CAN1->MCR=0x0000; //Exit sleep mode (setting all bits to 0 at the same time) //退出睡眠模式(同时设置所有位为0)
|
||
CAN1->MCR|=1<<0; //Request CAN1 to enter initialization mode //请求CAN1进入初始化模式
|
||
while((CAN1->MSR&1<<0)==0)
|
||
{
|
||
i++;
|
||
if(i>100)return 2; //Failed to enter initialization mode //进入初始化模式失败
|
||
}
|
||
//Non-time triggered communication mode
|
||
//非时间触发通信模式
|
||
CAN1->MCR|=0<<7;
|
||
//Software automatic offline management
|
||
//软件自动离线管理
|
||
CAN1->MCR|=0<<6;
|
||
//Sleep mode is awakened by software (clear CAN1- >;
|
||
//睡眠模式通过软件唤醒(清除CAN1->MCR的SLEEP位)
|
||
CAN1->MCR|=0<<5;
|
||
//Disallow automatic message transmission
|
||
//禁止报文自动传送
|
||
CAN1->MCR|=1<<4;
|
||
//Messages are not locked, the new overwrites the old
|
||
//报文不锁定,新的覆盖旧的
|
||
CAN1->MCR|=0<<3;
|
||
//The priority is determined by the message identifier
|
||
//优先级由报文标识符决定
|
||
CAN1->MCR|=0<<2;
|
||
//Clear the original Settings
|
||
//清除原来的设置
|
||
CAN1->BTR=0x00000000;
|
||
//Mode set to 0, normal mode;1. Loop mode;
|
||
//模式设置 0,普通模式;1,回环模式;
|
||
CAN1->BTR|=mode<<30;
|
||
//Resynchronization jump width (TSJW) is TSJW +1 time unit
|
||
//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位
|
||
CAN1->BTR|=tsjw<<24;
|
||
//Tbs2= Tbs2 +1 time unit
|
||
//Tbs2=tbs2+1个时间单位
|
||
CAN1->BTR|=tbs2<<20;
|
||
//Tbs1= Tbs1 +1 time unit
|
||
//Tbs1=tbs1+1个时间单位
|
||
CAN1->BTR|=tbs1<<16;
|
||
//Frequency division coefficient (Fdiv) is brp +1, boulder rate: Fpclk1/((Tbs1+Tbs2+1)*Fdiv)
|
||
//分频系数(Fdiv)为brp+1,波特率:Fpclk1/((Tbs1+Tbs2+1)*Fdiv)
|
||
CAN1->BTR|=brp<<0;
|
||
//Request CAN1 to exit initialization mode
|
||
//请求CAN1退出初始化模式
|
||
CAN1->MCR&=~(1<<0);
|
||
while((CAN1->MSR&1<<0)==1)
|
||
{
|
||
i++;
|
||
if(i>0XFFF0)return 3; //Failed to exit initialization mode //退出初始化模式失败
|
||
}
|
||
/*** Filter initialization || 过滤器初始化 ***/
|
||
//Filter groups work in initialization mode
|
||
//过滤器组工作在初始化模式
|
||
CAN1->FMR|=1<<0;
|
||
//Filter 0 is not active
|
||
//过滤器0不激活
|
||
CAN1->FA1R&=~(1<<0);
|
||
//The filter bit width is 32 bits
|
||
//过滤器位宽为32位
|
||
CAN1->FS1R|=1<<0;
|
||
//Filter 0 works in identifier masking bit mode
|
||
//过滤器0工作在标识符屏蔽位模式
|
||
CAN1->FM1R|=0<<0;
|
||
//Filter 0 is associated with FIFO0
|
||
//过滤器0关联到FIFO0
|
||
CAN1->FFA1R|=0<<0;
|
||
//32 bit ID
|
||
//32位ID
|
||
CAN1->sFilterRegister[0].FR1=0X00000000;
|
||
//32-bit MASK
|
||
//32位MASK
|
||
CAN1->sFilterRegister[0].FR2=0X00000000;
|
||
//Activation filter 0
|
||
//激活过滤器0
|
||
CAN1->FA1R|=1<<0;
|
||
//Filter group enters normal mode
|
||
//过滤器组进入正常模式
|
||
CAN1->FMR&=0<<0;
|
||
|
||
#if CAN1_RX0_INT_ENABLE
|
||
//Enable to interrupt reception //使能中断接收
|
||
|
||
//FIFO0消息挂号中断允许
|
||
CAN1->IER|=1<<1;
|
||
|
||
//Configure CAN to receive interrupts
|
||
//配置CAN接收中断
|
||
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
|
||
//Preemption priority
|
||
//抢占优先级
|
||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;
|
||
//Son priority
|
||
//子优先级
|
||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
|
||
//IRQ channel enablement
|
||
//IRQ通道使能
|
||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||
//Initializes the VIC register according to the specified parameters
|
||
//根据指定的参数初始化VIC寄存器
|
||
NVIC_Init(&NVIC_InitStructure);
|
||
|
||
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
|
||
|
||
#endif
|
||
return 0;
|
||
}
|
||
/**************************************************************************
|
||
Function: CAN sends data
|
||
Input : id:Standard ID(11 bits)/ Extended ID(11 bits +18 bits)
|
||
ide:0, standard frame;1, extension frames
|
||
rtr:0, data frame;1, remote frame
|
||
len:Length of data to be sent (fixed at 8 bytes, valid data is 6 bytes in time-triggered mode)
|
||
*dat:Pointer to the data
|
||
Output : 0~3, mailbox number. 0xFF, no valid mailbox
|
||
函数功能:CAN发送数据
|
||
入口参数:id:标准ID(11位)/扩展ID(11位+18位)
|
||
ide:0,标准帧;1,扩展帧
|
||
rtr:0,数据帧;1,远程帧
|
||
len:要发送的数据长度(固定为8个字节,在时间触发模式下,有效数据为6个字节)
|
||
*dat:数据指针.
|
||
返回 值:0~3,邮箱编号.0XFF,无有效邮箱
|
||
**************************************************************************/
|
||
u8 CAN1_Tx_Msg(u32 id,u8 ide,u8 rtr,u8 len,u8 *dat)
|
||
{
|
||
u8 mbox;
|
||
if(CAN1->TSR&(1<<26))mbox=0; //Mailbox 0 is empty //邮箱0为空
|
||
else if(CAN1->TSR&(1<<27))mbox=1; //Mailbox 1 is empty //邮箱1为空
|
||
else if(CAN1->TSR&(1<<28))mbox=2; //Mailbox 2 is empty //邮箱2为空
|
||
else return 0XFF; //No empty mailbox, cannot send //无空邮箱,无法发送
|
||
|
||
CAN1->sTxMailBox[mbox].TIR=0; //Clear the previous Settings //清除之前的设置
|
||
if(ide==0) //The standard frame //标准帧
|
||
{
|
||
id&=0x7ff; //Take the low 11 bit STDID //取低11位stdid
|
||
id<<=21;
|
||
}else //Extend the frame //扩展帧
|
||
{
|
||
id&=0X1FFFFFFF; //Take a low 32-bit extid //取低32位extid
|
||
id<<=3;
|
||
}
|
||
CAN1->sTxMailBox[mbox].TIR|=id;
|
||
CAN1->sTxMailBox[mbox].TIR|=ide<<2;
|
||
CAN1->sTxMailBox[mbox].TIR|=rtr<<1;
|
||
len&=0X0F; //Get lower 4 bits //得到低四位
|
||
CAN1->sTxMailBox[mbox].TDTR&=~(0X0000000F);
|
||
CAN1->sTxMailBox[mbox].TDTR|=len; //Set the DLC //设置DLC
|
||
//The data to be sent is stored in the mailbox
|
||
//待发送数据存入邮箱
|
||
CAN1->sTxMailBox[mbox].TDHR=(((u32)dat[7]<<24)|
|
||
((u32)dat[6]<<16)|
|
||
((u32)dat[5]<<8)|
|
||
((u32)dat[4]));
|
||
CAN1->sTxMailBox[mbox].TDLR=(((u32)dat[3]<<24)|
|
||
((u32)dat[2]<<16)|
|
||
((u32)dat[1]<<8)|
|
||
((u32)dat[0]));
|
||
CAN1->sTxMailBox[mbox].TIR|=1<<0; //Request to send mailbox data//请求发送邮箱数据
|
||
return mbox;
|
||
}
|
||
/**************************************************************************
|
||
Function: Get the send status
|
||
Input : Mbox: mailbox number
|
||
Output : 0, hang;0X05, send failed;0X07, successful transmission
|
||
函数功能:获得发送状态
|
||
入口参数:mbox:邮箱编号
|
||
返回 值:0,挂起;0X05,发送失败;0X07,发送成功
|
||
**************************************************************************/
|
||
u8 CAN1_Tx_Staus(u8 mbox)
|
||
{
|
||
u8 sta=0;
|
||
switch (mbox)
|
||
{
|
||
case 0:
|
||
sta |= CAN1->TSR&(1<<0); //RQCP0
|
||
sta |= CAN1->TSR&(1<<1); //TXOK0
|
||
sta |=((CAN1->TSR&(1<<26))>>24); //TME0
|
||
break;
|
||
case 1:
|
||
sta |= CAN1->TSR&(1<<8)>>8; //RQCP1
|
||
sta |= CAN1->TSR&(1<<9)>>8; //TXOK1
|
||
sta |=((CAN1->TSR&(1<<27))>>25); //TME1
|
||
break;
|
||
case 2:
|
||
sta |= CAN1->TSR&(1<<16)>>16; //RQCP2
|
||
sta |= CAN1->TSR&(1<<17)>>16; //TXOK2
|
||
sta |=((CAN1->TSR&(1<<28))>>26); //TME2
|
||
break;
|
||
default:
|
||
sta=0X05; //Wrong email number, failed //邮箱号不对,失败
|
||
break;
|
||
}
|
||
return sta;
|
||
}
|
||
/**************************************************************************
|
||
Function: Returns the number of packets received in FIFO0/FIFO1
|
||
Input : Fifox: FIFO number (0, 1)
|
||
Output : Number of packets in FIFO0/FIFO1
|
||
函数功能:得到在FIFO0/FIFO1中接收到的报文个数
|
||
入口参数:fifox:FIFO编号(0、1)
|
||
返回 值:FIFO0/FIFO1中的报文个数
|
||
**************************************************************************/
|
||
u8 CAN1_Msg_Pend(u8 fifox)
|
||
{
|
||
if(fifox==0)return CAN1->RF0R&0x03;
|
||
else if(fifox==1)return CAN1->RF1R&0x03;
|
||
else return 0;
|
||
}
|
||
/**************************************************************************
|
||
Function: Receive data
|
||
Input : fifox:Email
|
||
id:Standard ID(11 bits)/ Extended ID(11 bits +18 bits)
|
||
ide:0, standard frame;1, extension frames
|
||
rtr:0, data frame;1, remote frame
|
||
len:Length of data received (fixed at 8 bytes, valid at 6 bytes in time-triggered mode)
|
||
dat:Data cache
|
||
Output : none
|
||
函数功能:接收数据
|
||
入口参数:fifox:邮箱号
|
||
id:标准ID(11位)/扩展ID(11位+18位)
|
||
ide:0,标准帧;1,扩展帧
|
||
rtr:0,数据帧;1,远程帧
|
||
len:接收到的数据长度(固定为8个字节,在时间触发模式下,有效数据为6个字节)
|
||
dat:数据缓存区
|
||
返回 值:无
|
||
**************************************************************************/
|
||
void CAN1_Rx_Msg(u8 fifox,u32 *id,u8 *ide,u8 *rtr,u8 *len,u8 *dat)
|
||
{
|
||
*ide=CAN1->sFIFOMailBox[fifox].RIR&0x04; //Gets the value of the identifier selection bit //得到标识符选择位的值
|
||
if(*ide==0) //Standard identifier //标准标识符
|
||
{
|
||
*id=CAN1->sFIFOMailBox[fifox].RIR>>21;
|
||
}else //Extended identifier //扩展标识符
|
||
{
|
||
*id=CAN1->sFIFOMailBox[fifox].RIR>>3;
|
||
}
|
||
*rtr=CAN1->sFIFOMailBox[fifox].RIR&0x02; //Gets the remote send request value //得到远程发送请求值
|
||
*len=CAN1->sFIFOMailBox[fifox].RDTR&0x0F; //Get the DLC //得到DLC
|
||
//*fmi=(CAN1->sFIFOMailBox[FIFONumber].RDTR>>8)&0xFF; //Get the FMI //得到FMI
|
||
//Receive data //接收数据
|
||
dat[0]=CAN1->sFIFOMailBox[fifox].RDLR&0XFF;
|
||
dat[1]=(CAN1->sFIFOMailBox[fifox].RDLR>>8)&0XFF;
|
||
dat[2]=(CAN1->sFIFOMailBox[fifox].RDLR>>16)&0XFF;
|
||
dat[3]=(CAN1->sFIFOMailBox[fifox].RDLR>>24)&0XFF;
|
||
dat[4]=CAN1->sFIFOMailBox[fifox].RDHR&0XFF;
|
||
dat[5]=(CAN1->sFIFOMailBox[fifox].RDHR>>8)&0XFF;
|
||
dat[6]=(CAN1->sFIFOMailBox[fifox].RDHR>>16)&0XFF;
|
||
dat[7]=(CAN1->sFIFOMailBox[fifox].RDHR>>24)&0XFF;
|
||
if(fifox==0)CAN1->RF0R|=0X20; //Free the FIFO0 mailbox //释放FIFO0邮箱
|
||
else if(fifox==1)CAN1->RF1R|=0X20; //Free the FIFO1 mailbox //释放FIFO1邮箱
|
||
}
|
||
/**************************************************************************
|
||
Function: CAN receives interrupt service function, conditional compilation
|
||
Input : none
|
||
Output : none
|
||
函数功能:CAN接收中断服务函数,条件编译
|
||
入口参数:无
|
||
返回 值:无
|
||
**************************************************************************/
|
||
#if CAN1_RX0_INT_ENABLE //Enable RX0 interrupt //使能RX0中断
|
||
void CAN1_RX0_IRQHandler(void)
|
||
{
|
||
u32 id;
|
||
u8 ide,rtr,len;
|
||
|
||
u8 temp_rxbuf[8];
|
||
|
||
CAN1_Rx_Msg(0,&id,&ide,&rtr,&len,temp_rxbuf);
|
||
if(id==0x181)
|
||
{
|
||
float Vz;
|
||
CAN_ON_Flag=1, PS2_ON_Flag=0,Remote_ON_Flag=0,APP_ON_Flag=0,Usart1_ON_Flag=0,Usart5_ON_Flag=0;
|
||
command_lost_count=0; //CAN/串口控制命令丢失计数清零
|
||
|
||
//Calculate the three-axis target velocity, unit: m/s
|
||
//计算三轴目标速度,单位:m/s
|
||
Move_X=((float)((short)((temp_rxbuf[0]<<8)+(temp_rxbuf[1]))))/1000;
|
||
Move_Y=((float)((short)((temp_rxbuf[2]<<8)+(temp_rxbuf[3]))))/1000;
|
||
Vz =((float)((short)((temp_rxbuf[4]<<8)+(temp_rxbuf[5]))))/1000;
|
||
if(Car_Mode==Akm_Car)
|
||
{
|
||
Move_Z=Vz_to_Akm_Angle(Move_X, Vz);
|
||
}
|
||
else
|
||
{
|
||
Move_Z=((float)((short)((temp_rxbuf[4]<<8)+(temp_rxbuf[5]))))/1000;
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/**************************************************************************
|
||
Function: CAN1 sends a set of data (fixed format :ID 0X601, standard frame, data frame)
|
||
Input : msg:Pointer to the data
|
||
len:Data length (up to 8)
|
||
Output : 0, success, others, failure;
|
||
函数功能:CAN1发送一组数据(固定格式:ID为0X601,标准帧,数据帧)
|
||
入口参数:msg:数据指针
|
||
len:数据长度(最大为8)
|
||
返回 值:0,成功,其他,失败;
|
||
**************************************************************************/
|
||
u8 CAN1_Send_Msg(u8* msg,u8 len)
|
||
{
|
||
u8 mbox;
|
||
u16 i=0;
|
||
mbox=CAN1_Tx_Msg(0X601,0,0,len,msg);
|
||
while((CAN1_Tx_Staus(mbox)!=0X07)&&(i<0XFFF))i++; //Waiting for the end of sending //等待发送结束
|
||
if(i>=0XFFF)return 1; //Send failure //发送失败
|
||
return 0; //Send a success //发送成功
|
||
}
|
||
/**************************************************************************
|
||
Function: The CAN1 port receives data queries
|
||
Input : Buf: The data cache
|
||
Output : 0, number of data received, other, length of data received
|
||
函数功能:CAN1口接收数据查询
|
||
入口参数:buf:数据缓存区
|
||
返回 值:0,无数据被收到,其他,接收的数据长度
|
||
**************************************************************************/
|
||
u8 CAN1_Receive_Msg(u8 *buf)
|
||
{
|
||
u32 id;
|
||
u8 ide,rtr,len;
|
||
if(CAN1_Msg_Pend(0)==0)return 0; //No data received, exit directly //没有接收到数据,直接退出
|
||
CAN1_Rx_Msg(0,&id,&ide,&rtr,&len,buf); //Read the data //读取数据
|
||
if(id!=0x12||ide!=0||rtr!=0)len=0; //Receive error //接收错误
|
||
return len;
|
||
}
|
||
/**************************************************************************
|
||
Function: Can1 sends a set of data tests
|
||
Input : msg:Pointer to the data
|
||
len:Data length (up to 8)
|
||
Output : 0, success, 1, failure
|
||
函数功能:CAN1发送一组数据测试
|
||
入口参数:msg:数据指针
|
||
len:数据长度(最大为8)
|
||
返回 值:0,成功,1,失败
|
||
**************************************************************************/
|
||
u8 CAN1_Send_MsgTEST(u8* msg,u8 len)
|
||
{
|
||
u8 mbox;
|
||
u16 i=0;
|
||
mbox=CAN1_Tx_Msg(0X701,0,0,len,msg);
|
||
while((CAN1_Tx_Staus(mbox)!=0X07)&&(i<0XFFF))i++; //Waiting for the end of sending //等待发送结束
|
||
if(i>=0XFFF)return 1; //Send failure //发送失败
|
||
return 0; //Send a success //发送成功
|
||
}
|
||
/**************************************************************************
|
||
Function: Sends an array to the given ID
|
||
Input : id:ID no.
|
||
msg:The transmitted data pointer
|
||
Output : 0, success, 1, failure
|
||
函数功能:给给定的id发送一个数组的命令
|
||
入口参数:id:ID号
|
||
msg:被输送数据指针
|
||
返回 值:0,成功,1,失败
|
||
**************************************************************************/
|
||
u8 CAN1_Send_Num(u32 id,u8* msg)
|
||
{
|
||
u8 mbox;
|
||
u16 i=0;
|
||
mbox=CAN1_Tx_Msg(id,0,0,8,msg);
|
||
while((CAN1_Tx_Staus(mbox)!=0X07)&&(i<0XFFF))i++; //Waiting for the end of sending //等待发送结束
|
||
if(i>=0XFFF)return 1; //Send failure //发送失败
|
||
return 0;
|
||
}
|