bsp_can.c
#include "bsp_can.h"
static void CAN_GPIO_Config(void)
{
/* GPIO Init Struct */
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable CAN GPIO clock */
RCC_AHB1PeriphClockCmd(CAN_TX_GPIO_CLK | CAN_RX_GPIO_CLK, ENABLE);
/* Connect CAN pins to AF9 */
GPIO_PinAFConfig(CAN_TX_GPIO_PORT, CAN_RX_SOURCE, CAN_AF_PORT);
GPIO_PinAFConfig(CAN_RX_GPIO_PORT, CAN_TX_SOURCE, CAN_AF_PORT);
/* Configure CAN TX pins */
GPIO_InitStructure.GPIO_Pin = CAN_TX_PIN;
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_UP;
GPIO_Init(CAN_TX_GPIO_PORT, &GPIO_InitStructure);
/* Configure CAN RX pins */
GPIO_InitStructure.GPIO_Pin = CAN_RX_PIN ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
/* Init GPIO */
GPIO_Init(CAN_RX_GPIO_PORT, &GPIO_InitStructure);
}
static void CAN_NVIC_Config(void)
{
/* CAN NVIC Struct */
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/*NVIC Set*/
NVIC_InitStructure.NVIC_IRQChannel = CAN_RX_IRQ; /* 中断通道 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; /* 抢占优先级0 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* 子优先级为0 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /* 中断使能 */
/* Init NVIC */
NVIC_Init(&NVIC_InitStructure);
}
static void CAN_Mode_Config(void)
{
/* CAN Init Struct */
CAN_InitTypeDef CAN_InitStructure;
/* Enable CAN clock */
RCC_APB1PeriphClockCmd(CAN_CLK, ENABLE);
CAN_InitStructure.CAN_TTCM = DISABLE; /* MCR-TTCM 关闭时间触发通信模式使能 */
CAN_InitStructure.CAN_ABOM = ENABLE; /* MCR-ABOM 使能自动离线管理 */
CAN_InitStructure.CAN_AWUM = ENABLE; /* MCR-AWUM 使能自动唤醒模式 */
CAN_InitStructure.CAN_NART = DISABLE; /* MCR-NART 禁止报文自动重 */
CAN_InitStructure.CAN_RFLM = DISABLE; /* MCR-RFLM 接收FIFO 锁定模式 */
CAN_InitStructure.CAN_TXFP = DISABLE; /* MCR-TXFP 发送FIFO优先级 DISABLE-优先级取决于报文标示符 */
CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack; /* 回环工作模式 */
CAN_InitStructure.CAN_SJW = CAN_SJW_2tq; /* BTR-SJW 重新同步跳跃宽度 2个时间单元 */
/* ss=1 bs1=5 bs2=3 位时间宽度为(1+5+3) 波特率即为时钟周期tq*(1+5+3) */
CAN_InitStructure.CAN_BS1 = CAN_BS1_5tq; /* BTR-TS1 时间段1 占用了5个时间单元 */
CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq; /* BTR-TS1 时间段2 占用了3个时间单元 */
/* CAN Baudrate = 1 MBps (1MBps已为stm32的CAN最高速率) (CAN 时钟频率为 APB1 = 45 MHz) */
CAN_InitStructure.CAN_Prescaler = 5; /* BTR-BRP 波特率分频器 定义了时间单元的时间长度 45/(1+5+3)/5=1 Mbps */
/* CAN Init */
CAN_Init(CANx, &CAN_InitStructure);
}
static void CAN_Filter_Config(void)
{
uint32_t filter_id = 0;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/*CAN筛选器初始化*/
CAN_FilterInitStructure.CAN_FilterNumber = 13; /* 筛选器组 F4 0-13 */
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; /* 工作在掩码模式 */
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; /* 筛选器位宽为单个32位。 */
/* 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO。 */
filter_id = ((uint32_t)TEST_ID << 3) | CAN_ID_EXT | CAN_RTR_DATA;
CAN_FilterInitStructure.CAN_FilterIdHigh = (filter_id & 0xFFFF0000) >> 16; /* 要筛选的ID高位 */
CAN_FilterInitStructure.CAN_FilterIdLow = filter_id & 0xFFFF; /* 要筛选的ID低位 */
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = ((u32)0x1230 << 3) >> 16; /* 筛选出的 ID 为0x123x x表示不用关心 */
CAN_FilterInitStructure.CAN_FilterMaskIdLow = ((u32)0x1230 << 3) & 0xFFFF; /* 筛选出的 ID 为0x123x */
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO1 ; /* 筛选器被关联到FIFO1 */
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; /* 使能筛选器 */
CAN_FilterInit(&CAN_FilterInitStructure);
/*CAN通信中断使能*/
CAN_ITConfig(CANx, CAN_IT_FMP1, ENABLE);
}
void CAN_Config(void)
{
CAN_GPIO_Config(); /* GPIO Init */
CAN_NVIC_Config(); /* NVIC Init */
CAN_Mode_Config(); /* CAN Init */
CAN_Filter_Config(); /* Filter Init */
}
void CAN_SetMsg(CanTxMsg *TxMessage)
{
uint8_t ubCounter = 0;
TxMessage->StdId = 0x00;
TxMessage->ExtId = 0x1231; /* 使用的扩展ID */
TxMessage->IDE = CAN_ID_EXT; /* 扩展模式 */
TxMessage->RTR = CAN_RTR_DATA; /* 发送的是数据 */
TxMessage->DLC = 8; /* 数据长度为8字节 */
/*设置要发送的数据0-7*/
for (ubCounter = 0; ubCounter < 8; ubCounter++)
{
TxMessage->Data[ubCounter] = ubCounter;
}
}
extern __IO uint32_t flag ; /* 用于标志是否接收到数据,在中断函数中赋值 */
extern CanRxMsg RxMessage; /* 接收缓冲区 */
void CAN_RX_IRQHandler(void)
{
/* 从邮箱中读出报文 */
CAN_Receive(CANx, CAN_FIFO1, &RxMessage);
if((RxMessage.IDE == CAN_ID_EXT) && (RxMessage.DLC == 8) )
{
flag = 1;
}
else
{
flag = 0;
}
}
/************************** end of file ************************************/
bsp_can.h
#ifndef __BSP_CAN_H
#define __BSP_CAN_H
#include "stm32f4xx.h"
#include <stdio.h>
#define CANx CAN1
#define CAN_CLK RCC_APB1Periph_CAN1
#define CAN_RX_IRQ CAN1_RX1_IRQn
#define CAN_RX_IRQHandler CAN1_RX1_IRQHandler
#define CAN_RX_PIN GPIO_Pin_8
#define CAN_TX_PIN GPIO_Pin_9
#define CAN_TX_GPIO_PORT GPIOB
#define CAN_RX_GPIO_PORT GPIOB
#define CAN_TX_GPIO_CLK RCC_AHB1Periph_GPIOB
#define CAN_RX_GPIO_CLK RCC_AHB1Periph_GPIOB
#define CAN_AF_PORT GPIO_AF_CAN1
#define CAN_RX_SOURCE GPIO_PinSource8
#define CAN_TX_SOURCE GPIO_PinSource9
#define TEST_ID 0x1234
void CAN_Config(void);
void CAN_SetMsg(CanTxMsg *TxMessage);
#endif /* __BSP_CAN_H */
/************************** end of file ************************************/
main.c
#include "stm32f4xx.h"
#include "bsp_can.h"
volatile uint32_t flag = 0; /* 用于标志是否接收到数据,在中断函数中赋值 */
CanTxMsg TxMessage; /* 发送缓冲区 */
CanRxMsg RxMessage; /* 接收缓冲区 */
int main(int argc, char *argv[])
{
Debug_USART_Config();
CAN_Config();
printf("can loopback test project\r\n");
CAN_SetMsg(&TxMessage);
CAN_Transmit(CANx, &TxMessage);
printf("sendid %x \r\n", TxMessage.ExtId);
printf("send data:\r\n");
for (char i = 0; i < 8; i++)
{
printf("%x ", TxMessage.Data[i]);
}
printf("\r\n");
if(flag == 1)
{
printf("received id = %x\r\n", RxMessage.ExtId);
printf("received data :\r\n");
for (char i = 0; i < 8; i++)
{
printf("%x ", RxMessage.Data[i]);
}
printf("\r\n");
}
}
/********************************************* end of file **********************/
测试平台:野火F429开发
输出结果
can loopback test project
sendid 1231
send data:
0 1 2 3 4 5 6 7
received id = 1231
received data :
0 1 2 3 4 5 6 7