发新帖我要提问
12
返回列表
打印
[应用相关]

我也上传一些自己收藏的 can 总线方面的资料!

[复制链接]
楼主: wangjiahao88
手机看帖
扫描二维码
随时随地手机跟帖
21
wangjiahao88|  楼主 | 2018-8-22 15:12 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
#include "sys.h"
#include "delay.h"

#include "can.h"
#include "led.h"

#include "nvic.h"


#include "stdio.h"

#include "usart.h"
#include "hmi_driver.h"

#include "subfunction.h"




u8 can1_rec_flag = 0;
u8 can1_buf[100];
u8 can1_num;
u16 CAN1_ID;
u8 CAN1_DATA[8];//={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x01};
u8 CAN2_DATA[8]= {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x02};
u8 CAN3_DATA[8]= {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x03};
u8 CAN4_DATA[8]= {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x04};
u8 CAN5_DATA[8]= {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x05};
u8 CAN6_DATA[8]= {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x06};



int main(void)
{

    u8 j;
    u8 t=0;
    u8 i=0;




    NVIC_Configuration();
    delay_init(168);                //延时初始化
    uart_init();            //串口初始化

    CAN_Mode_Init();




    ////用于wq125
//        if(W25QXX_ReadID()!=W25Q128) SetTextValue(0,9,"119");//检测不到W25Q128
//        else SetTextValue(0,10,"110");
//        W25QXX_Write((u8*)TEXT_Buffer,FLASH_SIZE-200,6);                //从倒数第100个地址处开始,写入SIZE长度的数据
//        W25QXX_Read(datatemp,FLASH_SIZE-200,6);                                        //从倒数第100个地址处开始,读出SIZE个字节
//        SetTextValue(0,13,&datatemp[0]);
//




    while(1)
    {


        CAN1_Send_Msg(CAN2_DATA,8,0x0111);//扫描从机CAN1
        delay_ms(10);
        if(can1_num>0)
        {
            printf("%d",can1_num);//从串口1打印从can1接受了6帧数据
            RS232_1_Send_Data(can1_buf,48);
            can1_num=0;

        }
        delay_ms(1);//两次扫描之间要加延时,要不然会出错

        CAN1_Send_Msg(CAN3_DATA,8,0x0112);//扫描从机CAN2
        delay_ms(1);
        if(can1_num>0)
        {
            printf("%d",can1_num);//从串口1打印从can1接受了3帧数据
            RS232_1_Send_Data(can1_buf,24);
            can1_num=0;

        }


        //指示系统正在运行
        t++;
        delay_ms(100);
        if(t==2)
        {
            LED0=!LED0;
            t=0;

        }
        //指示系统正在运行

    }

}

使用特权

评论回复
22
wangjiahao88|  楼主 | 2018-8-22 15:12 | 只看该作者
/***********************************************************************
文件名称:can.c
功    能:
编写时间:2015.10.13
编 写 人:
注    意:
***********************************************************************/
#include "stm32f4xx.h"
#include "can.h"


//////////////////////////////////////////////////////////////////////////////////          

//CAN初始化
//tsjw:重新同步跳跃时间单元. @ref CAN_synchronisation_jump_width   范围: ; CAN_SJW_1tq~ CAN_SJW_4tq
//tbs2:时间段2的时间单元.   @ref CAN_time_quantum_in_bit_segment_2 范围:CAN_BS2_1tq~CAN_BS2_8tq;
//tbs1:时间段1的时间单元.   @refCAN_time_quantum_in_bit_segment_1  范围: ;          CAN_BS1_1tq ~CAN_BS1_16tq
//brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1
//波特率=Fpclk1/((tsjw+tbs1+tbs2+3)*brp);
//mode: @ref CAN_operating_mode 范围:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);
//则波特率为:42M/((1+6+7)*6)=500Kbps
//返回值:0,初始化OK;
//    其他,初始化失败;

void CAN_Mode_Init(void)
{

          GPIO_InitTypeDef GPIO_InitStructure;
        CAN_InitTypeDef        CAN_InitStructure;
          CAN_FilterInitTypeDef  CAN_FilterInitStructure;

           NVIC_InitTypeDef  NVIC_InitStructure;
       
    //************初始化CAN1***************
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能PORTA时钟                                                                                                                    

          RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟       
       
    //初始化GPIO
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;
    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(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12
       
          //引脚复用映射配置
          GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1
          GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1); //GPIOA12复用为CAN1
          
          //CAN单元设置
           CAN_InitStructure.CAN_TTCM=DISABLE;        //非时间触发通信模式   
          CAN_InitStructure.CAN_ABOM=DISABLE;        //软件自动离线管理          
          CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
          CAN_InitStructure.CAN_NART=ENABLE;        //禁止报文自动传送
          CAN_InitStructure.CAN_RFLM=DISABLE;        //报文不锁定,新的覆盖旧的  
          CAN_InitStructure.CAN_TXFP=ENABLE;        //发送优先级  0---由标识符决定  1---由发送请求顺序决定        */
          //CAN_InitStructure.CAN_Mode= CAN_Mode_LoopBack;         //初始化为环回模式
                CAN_InitStructure.CAN_Mode= CAN_Mode_Normal;         //初始化为普通模式
                //初始化波特率为500K
          CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;        //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
          CAN_InitStructure.CAN_BS1=CAN_BS1_7tq; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
          CAN_InitStructure.CAN_BS2=CAN_BS2_6tq;//Tbs2范围CAN_BS2_1tq ~        CAN_BS2_8tq
          CAN_InitStructure.CAN_Prescaler=6;  //分频系数(Fdiv)为brp+1       
          CAN_Init(CAN1, &CAN_InitStructure);   // 初始化CAN1
   
        //配置过滤器
        CAN_FilterInitStructure.CAN_FilterNumber=0;          //过滤器0
          CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask ;
          CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
          CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;////32位ID
          CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
          CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
          CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
           CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
          CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
          CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
               
#if CAN1_RX0_INT_ENABLE
       
          CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.                    

          NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
          NVIC_Init(&NVIC_InitStructure);
#endif
  //************初始化CAN2***************
       
}   

//#if CAN1_RX0_INT_ENABLE        //使能RX0中断
////中断服务函数                            
//void CAN1_RX0_IRQHandler(void)
//{
//          CanRxMsg RxMessage;
//        int i=0;
//    CAN_Receive(CAN1, 0, &RxMessage);
//        for(i=0;i<8;i++)
//        {
//                CAN1_DATA = RxMessage.Data;
//        }
//        CAN1_ID=RxMessage.StdId;
//        can1_rec_flag = 1;
////        printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data);
//}
//#endif


#if CAN1_RX0_INT_ENABLE        //使能RX0中断
//中断服务函数                            
void CAN1_RX0_IRQHandler(void)
{
          CanRxMsg RxMessage;
       
        u8 i=0;
        can1_num++;
       
    CAN_Receive(CAN1, 0, &RxMessage);
        for(i=0;i<8;i++)
        {
                can1_buf[(can1_num-1)*8+i] = RxMessage.Data;
        }
        CAN1_ID=RxMessage.StdId;
        can1_rec_flag = 1;
        CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);  /* 清除挂起中断 */
//        CAN_FIFORelease(CAN1,CAN_FIFO0 );
//        printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data);
}
#endif

//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)       
//len:数据长度(最大为8)                                     
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
//                 其他,失败;
u8 CAN1_Send_Msg(u8* msg,u8 len,u16 ID)
{       
  u8 mbox;
  u16 i=0;
  CanTxMsg TxMessage;
  TxMessage.StdId=ID;         // 标准标识符11位
  TxMessage.ExtId=0x12;         // 设置扩展标示符(29位)
  TxMessage.IDE=0;                  // 1使用扩展标识符,0使用标准标识符
  TxMessage.RTR=0;                  // 消息类型为数据帧,一帧8位
  TxMessage.DLC=len;                                                         // 发送两帧信息
  for(i=0;i<len;i++)
  TxMessage.Data=msg;                                 // 第一帧信息         
  mbox= CAN_Transmit(CAN1, &TxMessage);   
  i=0;
  while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;        //等待发送结束
  if(i>=0XFFF)return 1;
  return 0;               

}
//can口接收数据查询
//buf:数据缓存区;         
//返回值:0,无数据被收到;
//                 其他,接收的数据长度;
u8 CAN1_Receive_Msg(u8 *buf)
{                                     
        u32 i;
        CanRxMsg RxMessage;
    if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;                //没有接收到数据,直接退出
    CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据       
    for(i=0;i<RxMessage.DLC;i++)
    buf=RxMessage.Data;  
        return RxMessage.DLC;       
}

使用特权

评论回复
23
wangjiahao88|  楼主 | 2018-8-22 15:13 | 只看该作者
STM32之CAN ---CAN ID过滤器分析
在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的。因此,发送者以广播的形式把报文发送给所有的接收者。节点在接收报文时,根据标识符(CAN ID)的值决定软件是否需要该报文;如果需要,就拷贝到SRAM里;如果不需要,报文就被丢弃且无需软件的干预。
         为满足这一需求,bxCAN为应用程序提供了14个位宽可变的、可配置的过滤器组(13~0),以便只接收那些软件需要的报文。硬件过滤的做法节省了CPU开销,否则就必须由软件过滤从而占用一定的CPU开销。每个过滤器组x由2个32位寄存器,CAN_FxR0和CAN_FxR1组成。

        为了让大家了解STM32的bxCAN的接收过滤机制,首先大家需要了解几个概念。

使用特权

评论回复
24
wangjiahao88|  楼主 | 2018-8-22 15:14 | 只看该作者
2.1 过滤器组

        STM32总共提供14个过滤器组来处理CAN接收过滤问题,每个过滤器组包含两个32位寄存器CAN_FxR0和CAN_FxR1组成,在设置为屏蔽位模式下,其中一个作为标识符寄存器,另一个作为屏蔽码寄存器。过滤器组中的每个过滤器,编号(叫做过滤器号)从0开始,到某个最大数值(这时最大值并非13,而是取决于14个过滤器组的模式和位宽的设置,当全部配置为位宽为16,且为标识符列表模式时,最大编号为14*4-1=55)。

使用特权

评论回复
25
wangjiahao88|  楼主 | 2018-8-22 15:14 | 只看该作者
2.2 过滤器的过滤模式

        STM32提供两种过滤模式供用户设置:屏蔽位模式和标识符列表模式。

2.2.1 屏蔽位模式

为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式。
        在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照“必须匹配”或“不用关心”处理。

2.2.2 标识符列表模式

为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。
        在标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一个屏蔽位的方式,而是使用2个标识符寄存器。接收报文标识符的每一位都必须跟过滤器标识符相同。

2.3 过滤器的位宽

        每个过滤器组的位宽都可以独立配置,以满足应用程序的不同需求。根据位宽的不同,每个过滤器组可提供:
        ●1个32位过滤器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位
        ●2个16位过滤器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位

2.3 过滤器组的过滤模式和位宽设置

        过滤器组可以通过相应的CAN_FMR寄存器(CAN过滤器主控寄存器)配置。但是不是什么时候都可以直接配置,在配置一个过滤器组前,必须通过清除CAN_FAR寄存器(CAN过滤器激活寄存器)的FACT位,把它设置为禁用状态。然后才能设置或设置过滤器组的配置。

通过设置CAN_FS1R(CAN过滤器位宽寄存器)的相应FSCx位,可以配置一个过滤器组的位宽。
通过CAN_FM1R(CAN过滤器模式寄存器)的FBMx位,可以配置对应的屏蔽/标识符寄存器的标识符列表模式或屏蔽位模式。

使用特权

评论回复
26
wangjiahao88|  楼主 | 2018-8-22 15:15 | 只看该作者

使用特权

评论回复
27
city520boy| | 2019-3-5 10:22 | 只看该作者
[em:3:][em:3:][em:3:][em:3:][em:3:][em:3:][em:3:][em:3:][em:3:]

使用特权

评论回复
28
wangjiahao88|  楼主 | 2019-3-11 16:43 | 只看该作者
希望 大家共同交流。。。

使用特权

评论回复
29
xtge1| | 2019-3-15 01:08 | 只看该作者
不错,讲解的非常详细,代码也全。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则