N32G45x学习笔记-can使用教程,连续发送数据

说明

  1. 代码中使用了can中断
  2. can连续发送数据
  3. can的过滤器学习https://blog.csdn.net/u010261063/article/details/129965848

can基本概述

can 工作模式

  • 初始化
  • 正常
  • 睡眠模式

唤醒 CAN 有两种方式

  • 使能硬件自动唤醒
  • 使能软件唤醒

  • 设置 CAN_INTE.WKUITE 位 唤醒中断

  • 发送三个邮箱消息的顺序是可以由发送调度器根据消息的优先级决定的,优先级可以由消息的标识符决定,也可以由发送请求的顺序决定

  • 每个 CAN 有两个接收 FIFO,每个 FIFO 可以存储三个完整的报文

发送消息的流程如下:

  • 应用程序选择一个空的发送邮箱
  • 标识符、数据长度和要发送的数据写入发送邮箱寄存器;
  • 设置 CAN_TMIx.TXRQ 位请求发送(设置 CAN_TMIx.TXRQ 后邮箱不再是空邮箱,软件无权写入邮箱寄存器);
  • 邮箱进入 pending 状态,等待成为最高优先级
  • 邮箱成为最高优先级邮箱后,转为就绪状态
  • CAN 总线一进入空闲状态就发送就绪邮箱中的消息,然后进入发送状态
  • 邮箱中的消息发送成功后变为空邮箱
  • 硬件设置 CAN_TSTS 寄存器中对应邮箱的 RQCPM 和 TXOKM 置位,表示发送成功

发送错误

  • CAN_TSTS.ALSTM 位被设置表 示失败是由仲 裁引起的

  • CAN_TSTS.TERRM 位被设置表示是传输错误引起的

发送优先级

CAN_MCTRL.TXFP =1位,,发送的优先级由发送请求的顺序决定

CAN_MCTRL.TXFP =1位,,发送的优先级id,id越小越优先决定

时间触发通信模式

CAN 在

收发帧起始位的采样点位置对内部定时器的值进行采样,采样值即为收发邮箱的时间戳。内部定时器生成的时间戳将分别存储在 CAN_RMDTx/CAN_TMDTx 寄存器中

非自动重传模式

非自动重传模式下,发送操作只会执行一次

数据接收

can的接收有2个FIRO,每个FIFO有3个邮箱

相关中断

  1. 挂起中断请求 当消息存储在接收 FIFO 中时
  2. FIFO 满中断请求
  3. 溢出中断请求

过滤器

  1. 位宽
    1. 16位
    2. 32位
  2. 过滤模式的问题
    1. 列表模式
    2. 掩码模式

位时序

同步段(SYNC_SEG)、时间段 1(BS1)和时间段 2(BS2)

BS1 : 1~16 个时间单位–正向漂移,

BS2:1~8个时间单位----负向漂移

RSJW :重新同步跳转宽度 ,值可以编程为 1 到 4 个时间单位

波特率计算方法

波特率计算方法:APB1时钟主频 / 分频 / (tq1 + tq2 + rswj)

假设需要500K的波特率,can在APB1总线上=36MHz

CAN_InitStructure.RSJW = CAN_RSJW_1tq;

CAN_InitStructure.TBS1 = CAN_TBS1_14tq;

CAN_InitStructure.TBS2 = CAN_TBS2_3tq;

CAN_InitStructure.BaudRatePrescaler = 4;

bate = 36000000/18/4 = 500K

can使用步骤:

  1. can gpio初始化
  2. can外设初始化
  3. 过滤器初始化
  4. can发送函数编写
  5. can中断函数实现


#include 
#include "n32g45x.h"
#include "bsp_can.h"
#include "string.h"

static uint8_t recv_flag=0;
#define BUFF_SIZE 8


CanTxMessage CAN_TxMessage;

CanRxMessage CAN_RxMessage;
uint8_t CAN_RxMessage_Write_Cursor=0;
uint8_t CAN_RxMessage_Read_Cursor=0;

/**
 * @brief  Configures CAN GPIOs
 */
static void bsp_can_gpio_init(void)
{
    GPIO_InitType GPIO_InitStructure;
    GPIO_InitStruct(&GPIO_InitStructure);
    /* 配置时钟 */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
    /* 配置 CAN1 RX 引脚 */
    GPIO_InitStructure.Pin       = GPIO_PIN_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
    /* 配置 CAN1 TX 引脚 */
    GPIO_InitStructure.Pin        = GPIO_PIN_12;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
    /* 重映射 CAN1 GPIO */
    //GPIO_ConfigPinRemap(GPIO_RMP1_CAN1, ENABLE);
}

/**
 * @brief  配置can过滤器.
 * @param CAN_BaudRate 10Kbit/s ~ 1Mbit/s
 */
static void bsp_can_filter_config(void)
{
    CAN_FilterInitType CAN_FilterInitStructure;
    /* CAN filter init */
    CAN_FilterInitStructure.Filter_Num            = 0;
    CAN_FilterInitStructure.Filter_Mode           = CAN_Filter_IdMaskMode;
    CAN_FilterInitStructure.Filter_Scale          = CAN_Filter_32bitScale;

    CAN_FilterInitStructure.Filter_HighId         = 0;
    CAN_FilterInitStructure.Filter_LowId          = 0;

    CAN_FilterInitStructure.FilterMask_HighId     = 0;
    CAN_FilterInitStructure.FilterMask_LowId      = 0;
    CAN_FilterInitStructure.Filter_FIFOAssignment = CAN_FIFO0;
    CAN_FilterInitStructure.Filter_Act            = ENABLE;
    CAN1_InitFilter(&CAN_FilterInitStructure);

}


/**
 * @brief  CAN 中断配置 .
 */
static void bsp_can_nvic_config(void)
{
    NVIC_InitType NVIC_InitStructure;
    /* Configure the NVIC Preemption Priority Bits */
    // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    NVIC_InitStructure.NVIC_IRQChannel                   = USB_LP_CAN1_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0x0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    //使能can中断
    CAN_INTConfig(CAN1, CAN_INT_FMP0, ENABLE);
}


/**
 * @brief  配置外设 CAN.
 * @param CAN_BaudRate 10Kbit/s ~ 1Mbit/s
 */
void bsp_can_init(void)
{
    CAN_InitType CAN_InitStructure;
    /* 时钟配置 CAN */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_CAN1, ENABLE);
    /* CAN register init */
    CAN_DeInit(CAN1);
    /* can 结构初始化 init*/
    CAN_InitStruct(&CAN_InitStructure);
    /* CAN 外设init */
    CAN_InitStructure.TTCM              = DISABLE;
    CAN_InitStructure.ABOM              = DISABLE;
    CAN_InitStructure.AWKUM             = DISABLE;
    CAN_InitStructure.NART              = DISABLE;
    CAN_InitStructure.RFLM              = DISABLE;
    CAN_InitStructure.TXFP              = ENABLE;
    CAN_InitStructure.OperatingMode     = CAN_Normal_Mode;
    CAN_InitStructure.RSJW              = CAN_RSJW_1tq;
    CAN_InitStructure.TBS1              = CAN_TBS1_14tq;
    CAN_InitStructure.TBS2              = CAN_TBS2_3tq;
    CAN_InitStructure.BaudRatePrescaler = 4;
    /*初始化 the CAN */
    CAN_Init(CAN1, &CAN_InitStructure);
    //配置gpio
    bsp_can_gpio_init();
    //配置过滤器
    bsp_can_filter_config();
    //配置中断
    bsp_can_nvic_config();
}



/**
 can 发送数据
*/
uint8_t can_send_data(uint8_t *data,int  len)
{
    CanTxMessage CAN_TxMessages;
    uint8_t fram = 0,remain=0,i;
    /* 初始化发送数据结构*/
    CAN_TxMessages.StdId   = 12;
    CAN_TxMessages.IDE     = CAN_ID_STD;
    CAN_TxMessages.RTR     = CAN_RTRQ_DATA;

    fram = len/8;
    remain = len%8;
    for(i=0; i<fram; i++)
    {
        CAN_TxMessages.DLC     = 8;
        memcpy(CAN_TxMessages.Data, data+i*8,8);


        //发送数据
        CAN_TransmitMessage(CAN1, &CAN_TxMessages);
        //等待数据发送完成
        while(!CAN_GetFlagSTS(CAN1,CAN_FLAG_RQCPM0)			&&
                !CAN_GetFlagSTS(CAN1,CAN_FLAG_RQCPM1)&&
                !CAN_GetFlagSTS(CAN1,CAN_FLAG_RQCPM2));

    }

    CAN_TxMessages.DLC     = remain;
    memcpy(CAN_TxMessages.Data, data+i*8,remain);



    CAN_TransmitMessage(CAN1, &CAN_TxMessages);
    while(!CAN_GetFlagSTS(CAN1,CAN_FLAG_RQCPM0)			&&
            !CAN_GetFlagSTS(CAN1,CAN_FLAG_RQCPM1)&&
            !CAN_GetFlagSTS(CAN1,CAN_FLAG_RQCPM2));

    return 0;
}



/*
	can中断函数
*/
void USB_LP_CAN1_RX0_IRQHandler(void)
{
    CAN_ReceiveMessage(CAN1, CAN_FIFO0, &CAN_RxMessage);
    recv_flag=1;
    can_send_data("123456789012345678901234567890",30);
}

你可能感兴趣的:(N32G45x,N32G45X,CAN,连续发送,中断)