STM32F4XX - CAN设置

can协议部分

- 逻辑信号和电平信号

先贴上CAN信号在物理信号线上的查分信号表示形式
在这里插入图片描述显性电平: 电压差范围为1.5-2.5v。 对应的逻辑电平是0
隐性电平: 其他 对应的逻辑电平是1

为什么显性电平对应的逻辑电平值为0,而隐性电平对应的逻辑电平是1?
因为在总线上,需要令显性位具有“覆盖”隐性位的能力。
在线与逻辑关系下,0才具有这种能力(1·1·1·……·1·1·0 = 0)。
所以才会将0定义为dominant,而将1定义为recessive。例如总线上10个节点发隐性位而1个节点发显性位的时候,总线上呈现出的是显性位。

电气连接图如下:(显性电平时逻辑电平为0,隐性电平时逻辑电平为1.具备线与的能力)
在这里插入图片描述
- 报文协议
CAN的协议报文由上面的逻辑电平组成;(如1111101111011101111101111)
在这里插入图片描述灰色为显性,白色为隐性,浅蓝色表示可以是显性也可以是隐性。
起始帧(SOF) : 起始的一个显性位
仲裁段(Identify SRR IDE RTR):

  • canid填充位
  • RTR 区分数据帧和远程帧 显性为数据帧,隐性为远程帧
  • SRR 区分仲裁遥控帧的标准格式与扩展格式的优先级,比较标准格式的RTR位与扩展格式的SRR位,标准格式的RTR位恒为显性,扩展格式的SRR位恒为隐性。故前11位ID号相同时,标准数据帧优先级高于扩展数据帧。
  • IDE 区分仲裁数据帧的标准格式与扩展格式的优先级,看IDE位,扩展格式的IDE位恒为隐性,标准格式的IDE位在控制段,恒为显性。故前11位ID号相同时,标准遥控帧优先级高于扩展遥控帧。
    控制段(r1 r0 DLC):r1和r0保留,DLC控制数据段的长度。
    数据段(Data): 数据段可包含0-8个字节的数据,从MSB(最高位)开始输出。遥控帧没有此段。
    CRC段:由15个位的CRC序列和1个位的CRC界定符(用于分隔位)构成。CRC界定符恒为隐性。
    ACK段: 由ACK槽(ACK Slot)和ACK界定符2个位构成。 发送端两个呈现隐性电平。

- 位时序设置
在这里插入图片描述举一个具体的寄存器说明:
在这里插入图片描述需要设置的值有四个:SJW TS2 TS1 BRP

计算方式参考:
在这里插入图片描述SJW必须小于PBS1和PBS2的最小值。
这个寄存器中这些值使用的单位为tq。
brp :波特率分频器
tq=(brp)*tpclk1
baud rate=Fpclk1/((tbs1+tbs2+1)*brp)
=42M/((7+6+1)*3)
=1Mbps

上面对CAN协议相关进行说明,后面针对具体STM32F4XX的例子进行分析说明。

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;
}   

上面为一段CAN的初始化代码,下面具体分析:

if(tsjw0||tbs20||tbs10||brp0)return 1;
tsjw-=1; //Subtract 1 before setting //先减去1.再用于设置
tbs2-=1;
tbs1-=1;
brp-=1;
因为寄存器中的每个变量都进行了加一,所以我们这里我们基于给定值做-1处理。

//使能相关时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//使能PORTB时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟
使能GPIO时钟及CAN外设时钟。GPIO由AHB总线管理,CAN控制器由APB总线管理。

//初始化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
将CAN引脚设置为功能复用模式,类型为推挽输出,上拉电阻为100MHz,最后将引脚映射为can功能引脚。

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;
上面是对MCR寄存器进行设置,MCR是CAN 主控制寄存器。
在这里插入图片描述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 //进入初始化模>式失败
}
INRQ: 进入初始化模式,在初始化模式下对CAN的寄存器进行配置。并等待进入初始化模式完成。
SLEEP: 这里是退出休眠模式。所以置0
TXFP: 一般发送优先级都是消息标识符确定。所以置0
RFLM: 当接收FIFO满后,选择覆盖消息而不是丢弃。所以置0.
NART: 无论发送结果如何消息只会发送一次,不会一直发送直到发送成功。所以置1.
AWUM: 需要在SLEEP位置0后,就退出休眠模式。所以置0
ABOM: 当节点busoff后,等待128次11个隐性位后,置0可以让控制器先进入到初始化状态然后进入正常状态。所以置0.
TTCM: 不用使能CAN控制器内部的时间计数器(用于生成时间戳)。所以置0

//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;
这里就是设置波特率以及分频系数,在位时序中已经说明。
//请求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);
在这里插入图片描述
一共有28个筛选器,选择激活哪个筛选器。
//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;
可以选择筛选器是屏蔽模式还是列表模式,屏蔽模式表示屏蔽哪些CANID,列表模式表示哪些列表可以通过。一般选屏蔽模式。
//Filter 0 is associated with FIFO0
//过滤器0关联到FIFO0
CAN1->FFA1R|=0<<0;
关联到哪个FIFO,有FIFO0和FIFO1可以选择。
//32 bit ID
//32位ID
CAN1->sFilterRegister[0].FR1=0X00000000;
//32-bit MASK
//32位MASK
CAN1->sFilterRegister[0].FR2=0X00000000;
//Activation filter 0
设置过滤ID
//激活过滤器0
CAN1->FA1R|=1<<0;
激活过滤器0
//Filter group enters normal mode
//过滤器组进入正常模式
CAN1->FMR&=0<<0;
过滤器进入到正常状态。
//FIFO0消息挂号中断允许
CAN1->IER|=1<<1;
FIFO 开始时处于空状态,在接收的第一条有效消息存储在其中后,变为 Pending_1 状态。
硬件通过将 CAN_RFR 寄存器的 FMP[1:0] 位置为 01b 来指示该事件。消息将在 FIFO 输出
邮箱中供读取。软件将读取邮箱内容,并通过将 CAN_RFR 寄存器的 RFOM 位置 1,来将
邮箱释放。FIFO 随即恢复空状态。如果同时接收到新的有效消息,FIFO 将保持 Pending_1
状态,新消息将在输出邮箱中供读取。

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/0b6d3a23af4e4d989a7a571230dffbaf.png#pic_center
允许有新消息挂起时产生中断。
//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);
上面是设置CAN的中断通道,及中断抢占和响应优先级,最后使能中断。

接收部分主要代码:

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邮箱      
}

上面函数入参有FIFO号,上面设置了FIFO为FIFO0.其他的都是出参。
ide 用来区分是正常帧还是扩展帧。寄存器为RIR。
RDTR寄存器可以获取数据大小,大小为0-8.
RDLR寄存器可以获取实际的数据。
RF0R 寄存器可以释放FIFO,以供下次填充。
在这里插入图片描述
发送部分主要代码:

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 //发送成功                                                                     
}

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;
}


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 //发送失败
上面两行比较简单,发送,并且等待发送完成。

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;
}
发送一共有三个邮箱,判断哪个邮箱有空,就选择哪个邮箱进行发送,根据ide判断是标准帧还是扩展帧。然后进行位填充。

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//请求发送邮箱数据
填充仲裁段,控制端,数据段数据。最后请求发送邮箱中的数据。

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值