STM32 CAN初始化详解

CAN是控制器域网 (Controller Area Network, CAN) 的简称,是由研发和生产汽车电子产品著称的德国BOSCH公司开发了的,并最终成为国际标准(ISO11898)。是国际上应用最广泛的现场总线之一。 在北美和西欧,CAN总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以CAN为底层协议专为大型货车和重工机械车辆设计的J1939协议。近年来,其所具有的高可靠性和良好的错误检测能力受到重视,被广泛应用于汽车计算机控制系统和环境温度恶劣、电磁辐射强和振动大的工业环境。

u8 CAN1_Mode_Init(u8 tsjw, u8 tbs2,u8 tbs1, u16 brp, u8 mode)

{

    /* gpio结构体 */

    GPIO_InitTypeDef GPIO_InitStructure;

    /* can 初始化结构体 */

    CAN_InitTypeDef        CAN_InitStructure;

    /* can过滤器结构体 */

    CAN_FilterInitTypeDef  CAN_FilterInitStructure;

    /* 使能时钟 */

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);                                    

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

 

    /* 初始化gpio

        设置引脚

        复用模式

        推挽

        速率100

        上拉

    */

    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;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* 复用pa11 pa12can功能 */

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN1);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1);

    /* 初始化can结构体 */

    /*事件触发消息传输机制

    TTCAN模式下,CAN硬件的内部定时器被激活,并且被用于产生发送与接收邮箱的)时间戳

    为了使can满足,适合实时性和可靠性要求特别高或有安全性要求的场合

    路上各节点取得同步后, 消息只能根据调度表在规定的时间隙传输, 避免了消息传输的冲突、仲裁,消息传输时延短, 且可预知

    */

    CAN_InitStructure.CAN_TTCM=DISABLE;

    /* 软件自动离线管理

    ENABLE:一旦硬件检测到128 11位连续的隐性位,则自动退出离线状态

    ABOM1后,一旦检测到条件会自动恢复的,不需要人工干预

    如果ABOM位为’1’bxCAN进入离线状态后,就自动开启恢复过程。

    如果ABOM位为’0’,软件必须先请求bxCAN进入然后再退出初始化模式,随后恢复过程才被开启

    */

    CAN_InitStructure.CAN_ABOM=DISABLE;

    /* 睡眠模式禁用

    软件通过对CAN_MCR寄存器的SLEEP位置’1’,来请求进入这一模式。在该模式下,bxCAN的时钟停止了,但软件仍然可以访问邮箱寄存器。

    bxCAN处于睡眠模式,软件必须对CAN_MCR寄存器的INRQ位置’1’并且同时对SLEEP位清’0’,才能进入初始化模式。

    2种方式可以唤醒(退出睡眠模式)bxCAN:通过软件对SLEEP位清’1’,或硬件检测到CAN总线的活动。

    如果CAN_MCR寄存器的AWUM位为’1’,一旦检测到CAN总线的活动,硬件就自动对SLEEP位清’0’来唤醒bxCAN。如果CAN_MCR寄存器的AWUM位为’0’,软件必须在唤醒中断里对SLEEP位清’0’才能退出睡眠状态。

    注: 如果唤醒中断被允许(CAN_IER寄存器的WKUIE位为’1’),那么一旦检测到CAN总线活动就会产生唤醒中断,而不管硬件是否会自动唤醒bxCAN

    在对SLEEP位清’0’后,睡眠模式的退出必须与CAN总线同步,当硬件对SLAK位清’0’时,就确认了睡眠模式的退出。

    */

    CAN_InitStructure.CAN_AWUM=DISABLE;

    /* 自动重传使能

    该模式主要用于满足CAN标准中,时间触发通信选项的需求。通过对CAN_MCR寄存器的NART位置’1’,来让硬件工作在该模式。

    在该模式下,发送操作只会执行一次。如果发送操作失败了,不管是由于仲裁丢失或出错,硬件都不会再自动发送该报文。

    */

    CAN_InitStructure.CAN_NART=ENABLE;

    /*

    报文不锁定,新报文覆盖旧报文

    */

    CAN_InitStructure.CAN_RFLM=DISABLE;

    /* 优先级由报文标识符决定

    本成员用于选择CAN报文发送优先级判定方法

    用于选择CAN报文发送优先级判定方法

    */

    CAN_InitStructure.CAN_TXFP=DISABLE;

    /*

        #define CAN_Mode_Normal   正常模式

        #define CAN_Mode_LoopBack 回环模式 自己发,自己收

        回环模式下,它自己的输出端的所有内容都直接传输到自己的输入端,输出端的内容同时也会被传输到总线上,

        即也可使用总线监测它的发送内容。输入端只接收自己发送端的内容,不接收来自总线上的内容。使用回环模式可以进行自检。

        #define CAN_Mode_Silent   静默模式

        静默模式下,它自己的输出端的逻辑 0 数据会直接传输到它自己的输入端,逻辑1

        可以被发送到总线,所以它不能向总线发送显性位(逻辑 0),只能发送隐性位(逻辑 1)

        输入端可以从总线接收内容。由于它只可发送的隐性位不会强制影响总线的状态,

        所以把它称为静默模式。这种模式一般用于监测,它可以用于分析总线上的流量,但又不会因为发送显性位而影响总线

        #define CAN_Mode_Silent_LoopBack    静默回环模式

        回环静默模式是以上两种模式的结合,自己的输出端的所有内容都直接传输到自己的输入端,并且不会向总线发送显性位影响总线,

        不能通过总线监测它的发送内容。输入端只接收自己发送端的内容,不接收来自总线上的内容。

        这种方式可以在热自检时使用,即自我检查的时候,不会干扰总线

    */

    CAN_InitStructure.CAN_Mode= mode;

    /*

        重新同步跳跃宽度(SJW) 。定义了在每位中可以延长或缩短多少个时间单元的上限。其值可以编程为14个时间单元

    */

    CAN_InitStructure.CAN_SJW=tsjw;

    /*

        时间段1(BS1):定义采样点的位置。其值可以编程为116个时间单元,但也可以被自动延长,

        以补偿因为网络中不同节点的频率差异所造成的相位的正向漂移。

    */

    CAN_InitStructure.CAN_BS1=tbs1;

    /*

        时间段2(BS2):定义发送点的位置。其值可以编程为18个时间单元,但也可以被自动缩短以补偿相位的负向漂移。

    */

    CAN_InitStructure.CAN_BS2=tbs2;

    /*

        分频率

    */

    CAN_InitStructure.CAN_Prescaler=brp;

    /* 初始化结构体 */

    CAN_Init(CAN1, &CAN_InitStructure);

   

    /* 初始化过滤器 */

    /*

      选择过滤器0~13 for one can register

    */

    CAN_FilterInitStructure.CAN_FilterNumber = 0;

    /*

        屏蔽位模式和标识符列表模式

        #define CAN_FilterMode_IdMask       ((uint8_t)0x00)  

        #define CAN_FilterMode_IdList       ((uint8_t)0x01)

    */

    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;

    /*  过滤器的位数

        #define CAN_FilterScale_16bit       ((uint8_t)0x00)

        #define CAN_FilterScale_32bit       ((uint8_t)0x01)

    */

    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;

    /*

        32ID 高位

    */

    CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32??ID

    /*

        32ID 低位

    */

    CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;

    /* 屏蔽位高字节 */

    CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;

    /* 屏蔽位低字节 */

    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;

    /* 设定接收FIFO */

    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;

    /* 激活过滤组 */

    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;

    /* 初始化过滤器 */

    CAN_FilterInit(&CAN_FilterInitStructure);

   

    /* 配置can中断*/

    NVIC_InitTypeDef  NVIC_InitStructure;

    CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    return 0;

}  

你可能感兴趣的:(stm32,单片机,stm32,嵌入式硬件,mcu,物联网)