can 工作模式
唤醒 CAN 有两种方式
设置 CAN_INTE.WKUITE 位 唤醒中断
发送三个邮箱消息的顺序是可以由发送调度器根据消息的优先级决定的,优先级可以由消息的标识符决定,也可以由发送请求的顺序决定
每个 CAN 有两个接收 FIFO,每个 FIFO 可以存储三个完整的报文
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个邮箱
同步段(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
#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);
}