stm32f103 学习笔记 —— 07 CAN通讯协议

1.报文种类

  1. 数据帧 :用于节点向外传送数据

  2. 遥控帧 :用于向远端节点请求数据

  3. 错误帧 :用于向远端节点通知校验错误,请求重新发送上一个数据

  4. 过载帧 :用于通知远端节点本节点尚未做好接受准备

  5. 帧间隔 :用于将数据帧及遥控帧与前面的帧分离开来

2.报文结构(以数据帧为例)

  1. 以一个显性位(逻辑0)开始,以7个连续的隐性位(逻辑1)结束
  2. 帧起始(Start Of Frame):只有一个数据位(显性电平,逻辑0)
  3. 仲裁段 :决定发送优先级(通过“线与”的方式,即同时出现显性和隐形电平时总线状态被置为显性);CAN控制器根据ID过滤报文
  4. 远程传输请求位(Remote Transmission Request Bit):数据帧为显性,遥控帧为隐性
  5. 标识符扩展位(Identifier Extension Bit):显性表示标准格式,隐性表示扩展格式
  6. SRR :只存在于扩展格式,它用于替代标准格式中的RTR位(由于扩展帧中的SRR位为隐性位,RTR在数据帧为显性位,所以在两  个ID相同的标准格式报文与扩展格式报文中,标准格式的优先级较高)
  7. 数据长度码(Data Length Code):由4个数据位组成,但只能表示0~8个字节,用于表示报文中的数据段包含多少个字节
  8. CRC :为了保证报文的正确传输,CAN的报文包含了一段15位的CRC校验码,一旦接收节点算出的CRC码跟接收到的CRC码不同,则它会向发送节点反馈出错信息,利用错误帧请求它重新发送。CRC部分的计算一般由CAN控制器硬件完成,出错时的处理则由软件控制最大重发数。CRC校验码之后,有一个CRC界定符,它为隐性位,主要作用是把CRC校验码与后面的ACK段间隔起来。
  9. ACK段 :包括一个ACK槽位,和ACK界定符位。ACK槽位中,发送节点发送的是隐性位,而接收节点则在这一位中发送显性位以示应答。在ACK槽和帧结束之间由ACK界定符间隔开。

  10. 帧结束(End Of Frame):7个连续的隐性位

3.CAN的相关配置

1.main.c


#include "stm32f10x.h"
#include "./usart/bsp_usart.h"
#include "./led/bsp_led.h"
#include "./can/bsp_can.h"
#include "./key/bsp_key.h"  

CanRxMsg  CAN_Rece_Data;
CanTxMsg  CAN_Tran_Data;

uint8_t flag = 0;
 
 
void Delay(__IO uint32_t nCount); 


int main(void)
{ 	
	
	
	CAN_Config()	;   
	
	Key_GPIO_Config();
	
	while(1)
	{
		if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON  )
		
		{
			uint8_t box;
			
			CAN_Tran_Data.StdId = 0;
			CAN_Tran_Data.ExtId = PASS_ID;
			CAN_Tran_Data.RTR = CAN_RTR_Data;
			CAN_Tran_Data.IDE = CAN_Id_Extended ;
			CAN_Tran_Data.DLC = 1;
			CAN_Tran_Data.Data[0] = 10;
			
			box = CAN_Transmit(CAN1,&CAN_Tran_Data);
			
			while(CAN_TransmitStatus(CAN1,box) == CAN_TxStatus_Failed);
						
					
			
		} 		
		
		
		if(flag == 1)
		{
			
			  flag = 0;
		}
		else
		{
		
		}
	}
}


2.bsp_can.c

#include "./can/bsp_can.h"

//1.初始化CAN外设、波特率,位的组成
//2.配置筛选器,方便接收数据
//3.发送数据,并接收,使用回环模式测试

void CAN_GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
	
	/* 使能CAN时钟 */
	RCC_APB1PeriphClockCmd (RCC_APB1Periph_CAN1 , ENABLE );
	
	/* 使能CAN引脚相关的时钟 */
 	RCC_APB2PeriphClockCmd ( CAN_GPIO_CLK|RCC_APB2Periph_AFIO, ENABLE );
	
	//使用PA8 9引脚的第二功能
	GPIO_PinRemapConfig (GPIO_Remap1_CAN1 ,ENABLE);
	
  /* 配置CAN的 引脚,普通IO即可 */
  GPIO_InitStructure.GPIO_Pin = CAN_TX_GPIO_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(CAN_TX_GPIO_PROT, &GPIO_InitStructure);
	
	  /* 配置CAN的 引脚,普通IO即可 */
  GPIO_InitStructure.GPIO_Pin = CAN_RX_GPIO_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(CAN_RX_GPIO_PORT, &GPIO_InitStructure);
	
}


void CAN_Mode_Config(void)	
{

	CAN_InitTypeDef CAN_InitTypeStruct;
	
	CAN_InitTypeStruct.CAN_ABOM = ENABLE;//自动离线管理功能
	CAN_InitTypeStruct.CAN_AWUM = ENABLE;//自动唤醒功能
	CAN_InitTypeStruct.CAN_Mode = CAN_Mode_LoopBack;//CAN_Mode_Normal;//工作模式
	CAN_InitTypeStruct.CAN_NART = ENABLE;//错误重传
	CAN_InitTypeStruct.CAN_RFLM = ENABLE;//是否锁定FIFO
	CAN_InitTypeStruct.CAN_TTCM = DISABLE;//是否使能时间触发功能
	CAN_InitTypeStruct.CAN_TXFP = DISABLE; //按ID优先级发送
	
	//配置成1Mbps
	CAN_InitTypeStruct.CAN_BS1 = CAN_BS1_5tq;
	CAN_InitTypeStruct.CAN_BS2 = CAN_BS2_3tq;
	CAN_InitTypeStruct.CAN_SJW = CAN_SJW_2tq;
	CAN_InitTypeStruct.CAN_Prescaler = 4;
	
	
	CAN_Init(CAN1,&CAN_InitTypeStruct);

}



void CAN_Filter_Config(void)
{
	CAN_FilterInitTypeDef CAN_FilterInitTypeStruct;
	
	CAN_FilterInitTypeStruct.CAN_FilterActivation = ENABLE;
	CAN_FilterInitTypeStruct.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0  ;
	CAN_FilterInitTypeStruct.CAN_FilterNumber = 0;//筛选器编号
	CAN_FilterInitTypeStruct.CAN_FilterScale = CAN_FilterScale_32bit;//筛选器尺度
	CAN_FilterInitTypeStruct.CAN_FilterMode = CAN_FilterMode_IdMask  ;//筛选器模式
	
	CAN_FilterInitTypeStruct.CAN_FilterIdHigh = ((PASS_ID<<3 |CAN_Id_Extended |CAN_RTR_Data)&0xFFFF0000)>>16;
	CAN_FilterInitTypeStruct.CAN_FilterIdLow = ((PASS_ID<<3 |CAN_Id_Extended |CAN_RTR_Data)&0xFFFF);
	
	CAN_FilterInitTypeStruct.CAN_FilterMaskIdHigh = 0xFFFF;
	CAN_FilterInitTypeStruct.CAN_FilterMaskIdLow =0xFFFF;	

	CAN_FilterInit(&CAN_FilterInitTypeStruct);
	
	CAN_ITConfig (CAN1,CAN_IT_FMP0,ENABLE);
	
}	

void CAN_NVIC_Config(void)
{

	NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 配置NVIC为优先级组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
  /* 配置抢占优先级 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 配置子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断通道 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

void CAN_Config(void)	
{
	CAN_GPIO_Config();
  CAN_Mode_Config();
	CAN_Filter_Config();
	CAN_NVIC_Config();
	
}
   

3.bsp_can.h

#ifndef __BSP_CAN_H
#define __BSP_CAN_H

#include "stm32f10x.h"


#define PASS_ID   ((uint32_t)0x1314)


#define CAN_TX_GPIO_PROT  		GPIOB
#define CAN_TX_GPIO_PIN   		GPIO_Pin_9

#define  CAN_RX_GPIO_PORT     GPIOB
#define  CAN_RX_GPIO_PIN      GPIO_Pin_8

#define CAN_GPIO_CLK					RCC_APB2Periph_GPIOB



void CAN_Config(void)	;     


#endif /* __BSP_CAN_H */

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值