2733 views|3 replies

13

Posts

0

Resources
The OP
 

stm32 CANOpen [Copy link]

Below is a comparison between the CAN protocol and the OSI network model. The CAN physical layer is divided into three layers: MDI, PMA and PLS, and the data link layer is divided into two layers: MAC and LLC. These five layers are the original CAN protocol, and the standard is ISO11898. In other words, the CAN protocol did not have an application layer at the beginning. Later, a CAN-based application layer protocol called CANOpen was developed, and the standard is CiA301.

When developing CAN devices, you do not have to use CANOpen. You can customize your own application layer protocol according to your needs.

The CANOpen protocol has 6 communication objects, namely: PDO, SDO, SYNC, TIME, EMCY, and NMT. These 6 communication objects complete all the communication functions of the CANOpen protocol. Among them, we only introduce the more commonly used PDO, SDO, and NMT (4.4).

Communication Object ID (COB-ID)
The communication objects of the CANOpen protocol mainly utilize the data frame and remote frame in the CAN protocol. In order to distinguish different communication objects, the CANOpen protocol uses the ID in the data frame/remote frame. Among them, the 7th to 10th bits are the function code. The 0th to 6th bits are the node ID, which is used to distinguish the same function of different nodes. This allows up to 127 slave nodes to communicate with the master node.


The following are the predefined COB-IDs for each communication object.

The green part is the broadcast communication object, and the blue part is the point-to-point communication object.

The size of the COB-ID also determines the priority of the communication object, among which NMT has the highest priority and PDO has a higher priority than SDO.

CANOpen network management uses a master/slave structure. The master can control the slave's state through the module control service: {STOPPED, PRE-OPERATIONAL, OPERATIONAL, INITIALISING}. The module control service can be targeted at only one node or all nodes can be changed at the same time.

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "SysTick/systick.h" 
#include "GeneralTim.h" 
#include "stmflash.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


/* Private variables ---------------------------------------------------------*/
uint8_t CAN1_RxRdy,CAN2_RxRdy;
uint16_t CAN1_Val_Tx,CAN1_Val_Rx,CAN2_Val_Tx,CAN2_Val_Rx;
CanTxMsg Can1TxMessage;
CanTxMsg Can2TxMessage;
CanRxMsg Can1RxMessage;
CanRxMsg Can2RxMessage;
/* Private function prototypes -----------------------------------------------*/

void GPIO_Configuration(void);
void NVIC_Configuration(void);
void CAN_Configuration(void);
void CanWriteData( CAN_TypeDef* CANx ,CanTxMsg *TxMessage );

  

u8 CAN1_TX_data[128],CAN1_RX_data[128];
u16 CAN1_Tx_Counter,CAN1_Rx_Counter,CAN1_TX_flag,CAN1_RX_flag,CAN1_TX_status,CAN1_RX_status;
u8 CAN2_TX_data[128],CAN2_RX_data[128];
u16 CAN2_Tx_Counter,CAN2_Rx_Counter,CAN2_TX_flag,CAN2_RX_flag,CAN2_TX_status,CAN2_RX_status;


char KEY1_up,KEY2_up,KEY3_up,KEY4_up,KEY5_up,KEY6_up;
char canopen_ID=0x01;
char canopen_start,canopen_reset,canopen_pretreatment;
char canopen_RSDO,canopen_RPDO;
/*******************************************************************************
* Function Name  : main
* Description    : Main program
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
int main(void)
{
	CAN_Configuration();
	
	CAN2_RxRdy = DISABLE;
	Can2TxMessage.StdId=0x0700+canopen_ID;            //地址
	Can2TxMessage.DLC=3;
	Can2TxMessage.RTR = CAN_RTR_DATA; /* 设置为数据帧 */
	Can2TxMessage.IDE = CAN_ID_STD;   /* 使用标准id	*/
	Can2TxMessage.Data[0] = 0x00;			
	CAN_Transmit(CAN2,&Can2TxMessage);
	
	while (1)
	{		
		
		if(canopen_pretreatment==1)                            //高压恢复
		{
			canopen_pretreatment=0;
			CAN2_RxRdy = DISABLE;
			Can2TxMessage.StdId=0x0180+canopen_ID;            //地址
			Can2TxMessage.DLC=8;
			Can2TxMessage.RTR = CAN_RTR_DATA; /* 设置为数据帧 */
			Can2TxMessage.IDE = CAN_ID_STD;   /* 使用标准id	*/
			Can2TxMessage.Data[0] = GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_0);
			Can2TxMessage.Data[1] = GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_1);       	
			Can2TxMessage.Data[2] = GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_2);
			Can2TxMessage.Data[3] = GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_3);
			Can2TxMessage.Data[4] = GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_4);
			Can2TxMessage.Data[5] = GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_5);       	
			Can2TxMessage.Data[6] = GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_6);
			Can2TxMessage.Data[7] = GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_7);
							
			CAN_Transmit(CAN2,&Can2TxMessage);	
		}
		if(CAN1_RX_flag==1)
		{
			CAN1_RX_flag=0;
			if((Can1RxMessage.StdId==0x0000)&&(Can1RxMessage.Data[0]==0x10)&&(Can1RxMessage.Data[1]==0x00))
			{
				canopen_start=1;
			}
			if((Can1RxMessage.StdId==0x0000)&&(Can1RxMessage.Data[0]==0x10)&&(Can1RxMessage.Data[1]==canopen_ID))
			{
				canopen_start=1;
			}
			if(canopen_start==1) 
			{
				if((Can1RxMessage.StdId==0x0000)&&(Can1RxMessage.Data[0]==0x20)&&(Can1RxMessage.Data[1]==0x00))
				{
					canopen_start=0;
				}
				if((Can1RxMessage.StdId==0x0000)&&(Can1RxMessage.Data[0]==0x20)&&(Can1RxMessage.Data[1]==canopen_ID))
				{
					canopen_start=0;
				}
				if((Can1RxMessage.StdId==0x0000)&&(Can1RxMessage.Data[0]==0x82)&&(Can1RxMessage.Data[1]==0x00))
				{
					canopen_reset=1;
				}
				if((Can1RxMessage.StdId==0x0000)&&(Can1RxMessage.Data[0]==0x81)&&(Can1RxMessage.Data[1]==canopen_ID))
				{
					canopen_reset=1;
				}
				if((Can1RxMessage.StdId==0x0000)&&(Can1RxMessage.Data[0]==0x80)&&(Can1RxMessage.Data[1]==0x00))
				{
					canopen_pretreatment=1;
				}
				if((Can1RxMessage.StdId==0x0000)&&(Can1RxMessage.Data[0]==0x80)&&(Can1RxMessage.Data[1]==canopen_ID))
				{
					canopen_pretreatment=1;
				}
				if((Can1RxMessage.StdId-0x0600)==canopen_ID)
				{
					canopen_RSDO=1;
					if(canopen_RSDO==1)
					{
						canopen_RSDO=0;
						if((Can1RxMessage.Data[0]==0x2F)&&(Can1RxMessage.Data[1]==0x00)&&(Can1RxMessage.Data[2]==0x20)&&(Can1RxMessage.Data[3]==0x00))
						{
							canopen_ID=Can1RxMessage.Data[4];
						}
					}
				}
				if((Can1RxMessage.StdId-0x0200)==canopen_ID)
				{
					canopen_RPDO=1;
					if(canopen_RPDO==1)
					{
						canopen_RPDO=0;
						if(Can1RxMessage.Data[0]==0x31)
						{
							GPIO_WriteBit(GPIOB,GPIO_Pin_0,1);
						}
						if(Can1RxMessage.Data[0]==0x30)
						{
							GPIO_WriteBit(GPIOB,GPIO_Pin_0,0);
						}
						if(Can1RxMessage.Data[1]==0x31)
						{
							GPIO_WriteBit(GPIOB,GPIO_Pin_1,1);
						}
						if(Can1RxMessage.Data[1]==0x30)
						{
							GPIO_WriteBit(GPIOB,GPIO_Pin_1,0);
						}
					}
				}
			}
		}	
	}
}

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : Configures the different GPIO ports.
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO ,ENABLE);
  /* CAN1 and CAN2 periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2, ENABLE);						 
	 
  /* Configure CAN1 RX pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  /* Configure CAN1 pin: TX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  /* Configure CAN2 RX pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  /* Configure CAN2 pin: TX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);  

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure); 	

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
}

/*******************************************************************************
* Function Name  : NVIC_Configuration
* Description    : Configures the nested vectored interrupt controller.
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

  /* Enable CAN1 RX0 interrupt IRQ channel */
  NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  /* Enable CAN2 RX0 interrupt IRQ channel */
  NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

/*******************************************************************************
* Function Name  : CAN_Configuration
* Description    : Configures the CAN
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void CAN_Configuration(void)
{
  CAN_InitTypeDef        CAN_InitStructure;
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;

  NVIC_Configuration();
  GPIO_Configuration();
  /* CAN register init */
  CAN_DeInit(CAN1);
  CAN_DeInit(CAN2);
  CAN_StructInit(&CAN_InitStructure);

  CAN1_RxRdy = CAN2_RxRdy = DISABLE;
  CAN1_Val_Tx = CAN1_Val_Rx = CAN2_Val_Tx = CAN2_Val_Rx = 0;

  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM = DISABLE; /* 时间触发禁止, 时间触发:CAN硬件的内部定时器被激活,并且被用于产生时间戳 */
  CAN_InitStructure.CAN_ABOM = DISABLE; /* 自动离线禁止,自动离线:一旦硬件监控到128次11个隐性位,就自动退出离线状态。在这里要软件设定后才能退出 */
  CAN_InitStructure.CAN_AWUM = DISABLE; /* 自动唤醒禁止,有报文来的时候自动退出休眠	*/
  CAN_InitStructure.CAN_NART = DISABLE; /* 报文重传, 如果错误一直传到成功止,否则只传一次 */
  CAN_InitStructure.CAN_RFLM = DISABLE; /* 接收FIFO锁定, 1--锁定后接收到新的报文摘不要,0--接收到新的报文则覆盖前一报文	*/
  CAN_InitStructure.CAN_TXFP = ENABLE;  /* 发送优先级  0---由标识符决定  1---由发送请求顺序决定	*/
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; /* 模式	*/
  CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;      /* 重新同步跳宽,只有can硬件处于初始化模式时才能访问这个寄存器 */
  CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq;      /* 时间段1 */
  CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;      /* 时间段2 */
  CAN_InitStructure.CAN_Prescaler = 8;          /* 波特率预分频数 */  
 
  /* 波特率计算方法 */
  /* CANbps= Fpclk/((BRP+1)*((Tseg1+1)+(Tseg2+1)+1)  此处计算为  CANbps=36000000/(45*(4+3+1))=1200kHz */   														  //此处Tseg1+1 = CAN_BS1_8tp
  /* 配置大方向: Tseg1>=Tseg2  Tseg2>=tq; Tseg2>=2TSJW */						

  /*Initializes the CAN1  and CAN2 */
  CAN_Init(CAN1, &CAN_InitStructure);
  CAN_Init(CAN2, &CAN_InitStructure);

  /* CAN1 filter init */
  /* 配置CAN过滤器 */
  /* 32位对应的id */
  /* stdid[10:0],extid[17:0],ide,rtr	*/
  /* 16位对应的id */
  /* stdid[10:0],ide,rtr,extid[17:15] */
  /* 一般使用屏蔽模式	*/
  /* 要注意的是fifo接收存满了中断,还有就是fifo的概念,即取的一直是最早那一个数据, 要释放才能取下一个数据 */
  /* 常使用的中断有 */
  /* 1,有信息中断,即fifo挂号中断 */
  /* 2,fifo满中断	*/
  /* 3,fifo满之后又有信息来则中断,即fifo溢出中断	*/
  CAN_FilterInitStructure.CAN_FilterNumber = 0;     /* 过滤器1 */
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;  /* 屏敝模式 */
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; /* 32位 */
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;  /* 以下四个都为0, 表明不过滤任何id */
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;  
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);

  /* CAN2 filter init */
  CAN_FilterInitStructure.CAN_FilterNumber = 14;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
  CAN_FilterInit(&CAN_FilterInitStructure);

  /* IT Configuration for CAN1 */  
  CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

  /* IT Configuration for CAN2 */  
  CAN_ITConfig(CAN2, CAN_IT_FMP0, ENABLE);
}

/*******************************************************************************
* Function Name  : CanWriteData
* Description    : Can Write Date to CAN-BUS
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void CanWriteData( CAN_TypeDef* CANx ,CanTxMsg *TxMessage )
{
  /* transmit */
//  TxMessage->StdId = 0xA5A5;     /* 设置标准id  注意标准id的最高7位不能全是隐性(1)。共11位 */
//TxMessage->ExtId = 0x00;       //设置扩展id  扩展id共18位
  TxMessage->RTR = CAN_RTR_DATA; /* 设置为数据帧 */
  TxMessage->IDE = CAN_ID_STD;   /* 使用标准id	*/
//  TxMessage->DLC = 8;            /* 数据长度, can报文规定最大的数据长度为8字节 */
 
  CAN_Transmit(CANx,TxMessage);  /* 返回这个信息请求发送的邮箱号0,1,2或没有邮箱申请发送no_box */	
}

/*******************************************************************************
* Function Name  : CAN1_RX0_IRQHandler
* Description    : This function handles CAN1 RX0 interrupts 
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void CAN1_RX0_IRQHandler(void)
{
  int i;
	CAN_Receive(CAN1,CAN_FIFO0, &Can1RxMessage);  /* 此函数包含释放提出报文了的,在非必要时,不需要自己释放 */
  CAN1_RxRdy = ENABLE;
	CAN1_RX_flag=1;
}

/*******************************************************************************
* Function Name  : CAN2_RX0_IRQHandler
* Description    : This function handles CAN2 RX0 interrupts
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void CAN2_RX0_IRQHandler(void)
{
  CAN_Receive(CAN2,CAN_FIFO0, &Can2RxMessage);  /* 此函数包含释放提出报文了的,在非必要时,不需要自己释放 */
  CAN2_RxRdy = ENABLE;
	CAN2_RX_flag=1;
}

/*********************************************************************************************************
      END FILE
*********************************************************************************************************/

This post is from stm32/stm8

Latest reply

The original poster uploaded the picture again. Our administrator has also added your QQ. We can communicate on the forum or QQ at any time.   Details Published on 2020-7-27 13:29
 

310

Posts

5

Resources
2
 

The picture is broken, maybe the way to upload the picture is wrong

This post is from stm32/stm8
 
 

13

Posts

0

Resources
3
 

How did it become like this?

This post is from stm32/stm8

Comments

The original poster uploaded the picture again. Our administrator has also added your QQ. We can communicate on the forum or QQ at any time.  Details Published on 2020-7-27 13:29
 
 

2w

Posts

74

Resources
4
 
gandong posted on 2020-7-25 08:58 How did it become like this?

The original poster uploaded the picture again. Our administrator has also added your QQ. We can communicate on the forum or QQ at any time.

This post is from stm32/stm8
Add and join groups EEWorld service account EEWorld subscription account Automotive development circle
 
Personal signature

加油!在电子行业默默贡献自己的力量!:)

 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list