2、STM32F407ZGT6 CAN总线

一、CAN通信初始化

1、开时钟

	//开时钟 APB1是42MHz时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

2、引脚复用

	GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1);

3、配置GPIO

	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

4、CAN单元配置

CAN_InitTypeDef CAN_InitStructure;

//软件自动离线管理
CAN_InitStructure.CAN_ABOM = DISABLE;
//睡眠模式通过软件唤醒(清除CAN -> MCR 的 SLEEP位)			
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_BS1 = CAN_BS1_5tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_6tq;

//模式设置:mode:0,普通模式;1,回环模式
CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;
//禁止报文自动传送	
CAN_InitStructure.CAN_NART = ENABLE;
//分频系数 (0—1023)+ 1			
CAN_InitStructure.CAN_Prescaler = 6;
//报文不锁定,新的覆盖旧的				
CAN_InitStructure.CAN_RFLM = DISABLE;			
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;

//非时间触发通信模式
CAN_InitStructure.CAN_TTCM = DISABLE;

//优先级由报文标识符决定			
CAN_InitStructure.CAN_TXFP = DISABLE;			
CAN_Init(CAN1, &CAN_InitStructure);

5、配置过滤器

CAN_FilterInitTypeDef CAN_FilterInitStructure;

//激活过滤器0
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
//过滤器0关联到 FIFO 0					
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
//32位ID	
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;						
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;

//32位MASk:不过滤任何ID,收到的所有ID都有效
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x00;					
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x00;

//屏蔽位模式
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
//过滤器0
CAN_FilterInitStructure.CAN_FilterNumber = 0;
//32位宽						
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;		
CAN_FilterInit(&CAN_FilterInitStructure);

6、配置NVIC

//FIFO 0 消息挂号中断允许	
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);	
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStructure);

二、发送一个数组

//CAN发送一个数组(固定格式:ID为0x12,标准帧,数据帧)
void CanSendData(uint8_t *Array, uint8_t Length)
{
    //发送邮箱ID
	uint8_t MboxId;	
	uint16_t i = 0;
	uint32_t TimeOut = 0xffff;
	CanTxMsg TxMessage;
	TxMessage.StdId = 0x12;
	TxMessage.ExtId = 0x12;
	TxMessage.IDE = CAN_Id_Standard;
	TxMessage.RTR = CAN_RTR_DATA;
	TxMessage.DLC = Length;
	for(i = 0 ; i < Length; i++)
	{
		TxMessage.Data[i] = Array[i];
	}
	MboxId = CAN_Transmit(CAN1, &TxMessage);
	
	i = 0 ;
	while((CAN_TransmitStatus(CAN1, MboxId) == CAN_TxStatus_Failed) && (TimeOut == 0))
	{
//		i++;
//		if(i > 0xfff)
//			return;
		TimeOut--;
	}
}

三、查询接收

这里提供查询接收和中断接收两种方式

void CanReceiveData(void)
{
	uint16_t i = 0;
	uint32_t TimeOut = 0xffff;
	CanRxMsg RxMessage;
	if(CAN_MessagePending(CAN1, CAN_FIFO0) == 0)
		return;
	CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
	for(i = 0; i < 8; i++)
	{
		Rxdata[i] = RxMessage.Data[i];
	}
}

四、中断接收

void CAN1_RX0_IRQHandler(void)
{
	CanRxMsg RxMessage;
	uint8_t i = 0;
	if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) == SET)
	{
		CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
		CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
		for(i = 0; i < 8; i++)
		{
			Rxdata[i] = RxMessage.Data[i];
		}
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值