STM32F072-CAN通信,CAN通信的数据收发

CAN.C

#include "stm32f0xx.h"

#include "stm32f0xx_can.h"

#include "can.h"

void can_init(void)
{
    GPIO_InitTypeDef       GPIO_InitStructure;
    NVIC_InitTypeDef       NVIC_InitStructure;
    CAN_InitTypeDef        CAN_InitStructure;
    CAN_FilterInitTypeDef  CAN_FilterInitStructure;
    
    //初始化GPIO PB8(CANRX) PB9(CANTX)
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);
    
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_4);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_4); 
    
    //配置GPIO
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;//RX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//TX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    //中断优先级
    NVIC_InitStructure.NVIC_IRQChannel = CEC_CAN_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    //初始化CAN:设置波特率1Mbps
    CAN_DeInit(CAN);
    CAN_StructInit(&CAN_InitStructure);
    
    /*< 时间触发通信模式 DISABLE:禁止时间触发通信模式 ENABLE:使能时间触发通信模式*/
    CAN_InitStructure.CAN_TTCM = DISABLE;
    
    /*< 自动的总线关闭管理 此位控制 CAN 硬件在退出总线关闭状态时的行为
            DISABLE: 在软件发出请求后,一旦监测到 128 次连续 11 个隐性位,
            并且软件将 CAN_MCR 寄存器的 INRQ 位先置 1 再清零,即退出总线关闭状态
            ENABLE: 一旦监测到 128 次连续 11 个隐性位,即通过硬件自动退出总线关闭状态 */        
    CAN_InitStructure.CAN_ABOM = ENABLE;
    
    /*< 自动唤醒模式 此位控制 CAN 硬件在睡眠模式下接收到消息时的行为
            DISABLE: 在软件通过将 CAN_MCR 寄存器的 SLEEP 位清零发出请求后,退出睡眠模式
            ENABLE: 一旦监测到 CAN 消息,即通过硬件自动退出睡眠模式 */
    CAN_InitStructure.CAN_AWUM = ENABLE;
    
    /*< 自动重发送
            DISABLE: 无论发送结果如何(成功、错误或仲裁丢失),消息均只发送一次
            ENABLE: CAN 硬件将自动重发送消息,直到根据 CAN 标准消息发送成功 */
    CAN_InitStructure.CAN_NART = ENABLE;//DISABLE;
    
    /*< 接收 FIFO 锁定模式
            DISABLE: 接收 FIFO 上溢后不锁定。接收 FIFO 装满后,下一条传入消息将覆盖前一条消息
            ENABLE: 接收 FIFO 上溢后锁定。接收 FIFO 装满后,下一条传入消息将被丢弃*/
    CAN_InitStructure.CAN_RFLM = DISABLE;
    
    /*< 发送 FIFO 优先级 
            DISABLE: 优先级由消息标识符确定 
            ENABLE: 优先级由请求顺序(时间顺序)确定*/ 
    CAN_InitStructure.CAN_TXFP = DISABLE;
    
    /*< CAN工作模式 CAN_Mode_Normal:正常模式 CAN_Mode_LoopBack:回环模式 
            CAN_Mode_Silent:静默模式 CAN_Mode_Silent_LoopBack:静默回环模式*/
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
    
    //APB1时钟48M,预分频16,CAN时钟3M,500K
    CAN_InitStructure.CAN_Prescaler = 16;//设置CAN波特率分频系数
    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;//重新同步跳跃宽度
    CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;//时间段1占用时间单元
    CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq;//时间段2占用时间单元
    
    CAN_Init(CAN, &CAN_InitStructure);
    
    //使用筛选器组0,32位掩码模式,即可过滤一个ID
    //ID号存放在CAN_F0R1中,即CAN_FilterIdHigh和CAN_FilterIdLow分别存高低16位
    //掩码存放在CAN_F0R2中,即CAN_FilterMaskIdHigh和CAN_FilterMaskIdLow分别存高低16位
    //掩码全都为0时,则表明不过滤任何ID,接收总线上的所有报文
    //初始化筛选器
    CAN_FilterInitStructure.CAN_FilterNumber = 0;//过滤器0
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;//32位宽 
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;//屏蔽位(掩码)模式
    //32位掩码标准ID模式:筛选器只筛选接收标准ID为0x1的报文
    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x000 << 5;//(((uint32_t)0X01<<21|CAN_Id_Standard|CAN_RTR_Data)&0xFFFF0000)>>16;//筛选ID
    CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;//((uint32_t)0X01<<21|CAN_Id_Standard|CAN_RTR_Data)&0x0000FFFF;//筛选ID
    //(想要发送远程帧 修改对应掩码位为0)
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;//掩码
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;//掩码
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;//选中过滤器FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;//激活过滤器0
    
    CAN_FilterInit(&CAN_FilterInitStructure);
    //在CAN_FilterInit函数体中:
    /*在初始化之前,会设置 CAN_FMR 寄存器的 INRQ 为 INIT 让其进入初始化模式,
    然后初始化 CAN 滤波器相关的寄存器之后,会设置 CAN_FMR 寄存器的 FINIT 为 0 让其退出
    初始化模式。*/
    
    
    /* CAN FIFO0 接收中断使能 */ 
    CAN_ITConfig(CAN, CAN_IT_FMP0, ENABLE);
    
    CAN_ClearFlag(CAN,CAN_FLAG_RQCP0);
}

void CAN_SendData(uint8_t* data,uint8_t length)
{
    uint8_t mailbox;
    uint16_t i=0;
    CanTxMsg tx_msg;
    
    tx_msg.StdId=0x12;            // 标准标识符
    tx_msg.ExtId=0x12;            // 设置扩展标识符
    tx_msg.IDE=CAN_Id_Extended;    // 扩展帧
    tx_msg.RTR=CAN_RTR_Data;    // 数据帧
    tx_msg.DLC = length;
    
    for(i=0;i<length;i++)
    {
        tx_msg.Data[i] = data[i];
    }
    
    //CAN_Transmit(CAN1, &tx_msg);
    
    mailbox = CAN_Transmit(CAN,&tx_msg);
    i=0;
    while (CAN_TransmitStatus(CAN, mailbox) ==CAN_TxStatus_Failed && (i < 0xFFF));
//    while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF));    //等待发送结束
//    while( ( CAN_TransmitStatus( CAN1, mbox ) != CAN_TxStatus_Ok ) && (i < 0xFFF) ) 
}

uint8_t buf1[8];
void CAN1_Receive(void)
{
    CanRxMsg can_rx_msg;
    
    // 检查是否有CAN消息接收
    if (CAN_MessagePending(CAN,CAN_FIFO0) > 0)
    {
        // 接收CAN消息
        CAN_Receive(CAN,CAN_FIFO0,&can_rx_msg);
        /* 处理接收到的CAN消息 */
        for(int i=0;i<can_rx_msg.DLC;i++)
        {
            buf1[i]=can_rx_msg.Data[i];
        }
//        CAN_SendData(buf1,8);//发送CAN接收到的数据
//        can_rx_msg.DLC=0;
    }
}

CAN.h

#ifndef __CAN_H_
#define __CAN_H_
#include "stm32f0xx.h"  

#define CAN_RX0_INT_ENABLE        0   //不使用中断

void can_init(void);
void CAN_SendData(uint8_t* data, uint8_t length);
void CAN1_Receive(void);
void CAN_SendMessage(uint8_t data);

#endif

  • 21
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值