Files
origincar_controller/HARDWARE/can.c
MobKBK 460e0e9e73 init
2026-06-20 21:22:34 +08:00

414 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "can.h"
#include "system.h"
/**************************************************************************
Function: CAN1 initialization
Input : tsjwResynchronize the jump time unit, Scope: 1 ~ 3;
tbs2Time unit of time period 2, range :1~8;
tbs1Time 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
mode0, 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
mode0,普通模式;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中接收到的报文个数
入口参数fifoxFIFO编号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 : fifoxEmail
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 : idID no.
msgThe transmitted data pointer
Output : 0, success, 1, failure
函数功能给给定的id发送一个数组的命令
入口参数idID号
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;
}