A thorough study of the CAN bus based on stm32

Publisher:炫酷骑士Latest update time:2016-09-22 Source: eefocusKeywords:stm32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
1. Initialization of CAN bus
void can_init(void)
{
      CAN_InitTypeDef        CAN_InitStructure;
      CAN_FilterInitTypeDef  CAN_FilterInitStructure;
      /* CAN register init */
      CAN_DeInit();
      CAN_StructInit(&CAN_InitStructure);
    
      /* CAN cell init */
      CAN_InitStructure.CAN_TTCM=DISABLE;//Disable time triggered communication mode
      CAN_InitStructure.CAN_ABOM=DISABLE;
      CAN_InitStructure.CAN_AWUM=DISABLE;
      CAN_InitStructure.CAN_NART=DISABLE;//CAN message is sent only once, regardless of the result of the transmission (success, error or arbitration loss) 
      CAN_InitStructure.CAN_RFLM=DISABLE;
      CAN_InitStructure.CAN_TXFP=DISABLE;
      CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
      //CAN_Mode_LoopBack
      //CAN_Mode_Normal
      CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
      CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;//1--16
      CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;//1--8
      CAN_InitStructure.CAN_Prescaler=2;
      CAN_Init(&CAN_InitStructure);
#ifdef can_id_filter
       /* CAN filter init */
      CAN_FilterInitStructure.CAN _FilterNumber=0;//Select filter 0
      CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//Specify that the filter is set to identifier mask mode
      CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//Give the filter bit width 32 bits
      CAN_FilterInitStructure.CAN_FilterIdHigh=slave_id<<5;//Filter identifier
      CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;//
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xffff;//Filter mask identifier
      CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xfffc;
      CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;//Select FIFO0
      CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//Enable filterCAN_FilterInit
      (&CAN_FilterInitStructure);//Enter initialization function
#else
      /* CAN filter init */
      CAN_FilterInitStructure.CAN_FilterNumber=0;//Select filter 0
      CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//Specify that the filter is set to identifier mask modeCAN_FilterInitStructure.CAN_FilterScale
      =CAN_FilterScale_32bit;//Give the filter a bit width of 32
      bitsCAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;//Filter identifierCAN_FilterInitStructure.CAN_FilterIdLow
      =0x0000;//
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; //Filter mask identifier
      CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
      CAN_ITConfig(CAN_IT_FMP0, ENABLE); //Enable the specified CAN interrupt
}
 
 
void CAN_DeInit(void)
{
  /* Enable CAN reset state */
  RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN, ENABLE);
  /* Release CAN from reset state */
  RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN, DISABLE);
}
2. Sending program
unsigned char CAN_PushMessage(CAN_MSG *pTransmitBuf )
{
  u8 TransmitMailbox=0;
  CanTxMsg TxMessage;
  if(pTransmitBuf -> LEN > 8)
  {
       return 1;
  }
  /* transmit */
  TxMessage.StdId=pTransmitBuf ->StdId;//Used to set the standard identifier (0-0x7ff, 11 bits)
  TxMessage.ExtId=pTransmitBuf ->ExtId;
  TxMessage.RTR= pTransmitBuf ->RTR;//Set the RTR bit to the data frame
  TxMessage.IDE= pTransmitBuf ->IDE;//Identifier extension bit, standard frame
  TxMessage.DLC= pTransmitBuf ->LEN;//Set the data length
  //According to the value of the DLC field, copy the valid data to the transmit data register
  memcpy(TxMessage.Data, pTransmitBuf ->BUF,pTransmitBuf ->LEN);
  TransmitMailbox = CAN_Transmit(&TxMessage);
 // TxMessage.Data[1]=(data & 0xff00)>>8;
  return 1;
}
3. Interrupt receiving program
void USB_LP_CAN_RX0_IRQHandler(void)
{
  //Clear can receive buffer
  CanRxMsg RxMessage;
  RxMessage.StdId=0x00;
  RxMessage.ExtId=0x00;
  RxMessage.IDE=0;
  RxMessage.DLC=0;
  RxMessage.FMI=0;//CAN filter master control register
  memset( &RxMessage.Data[0],0,8);
  //can bus receive data function
  CAN_Receive(CAN_FIFO0, &RxMessage);
  //Write the received data to modbus register 1
  //modbus_regester[1]=(RxMessage.Data[0]<<8)|(RxMessage.Data[1]);
 // if((RxMessage.StdId==slave_id) && (RxMessage.ExtId==0x00) && (RxMessage.IDE==CAN_ID_STD))
  {
    //Set the can receive flag to 1, indicating that a can message has been received from the card
    flag_can_recv=0;
    memcpy(can_rx_data,&RxMessage.Data,RxMessage.DLC);
      flag_can_recv=1;
  }
}
4. CAN bus ID filtering

Filtering on extended data frames:

CAN_FilterInitStructure.CAN_FilterNumber   = 0; 
CAN_FilterInitStructure.CAN_FilterMode     = CAN_FilterMode_IdMask; 
CAN_FilterInitStructure.CAN_FilterScale    = CAN_FilterScale_32bit; 
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)CAN_ID<<3)&0xFFFF0000)>>16; 
CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)CAN_ID<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; 
CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF; 
CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFF; 

Filtering on standard data frames:

CAN_FilterInitStructure.CAN_FilterIdHigh= (((u32)CAN_ID0<<21)&0xFFFF0000)>>16; 
CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)CAN_ID0<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF; 
CAN_FilterInitStructure.CAN_FilterMaskIdHigh   = 0xFFFF; 
CAN_FilterInitStructure.CAN_FilterMaskIdLow    = 0xFFFF; 

If you want to filter standard remote frames, then:

Just need to

CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)CAN_ID0<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF; 改成:

CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)CAN_ID0<<21)|CAN_ID_STD|CAN_RTR_REMOTE)&0xFFFF;

5. CAN bus frame format

Data frame format:

Remote frame format:

6. Logic level of CAN bus

The physical connection of the CAN bus has two wires: CANH and CANL, which are output in differential form.

(Sometimes there is a ground wire, used as a shielding wire)

The high level of the CAN bus is 3.5v, indicating logic 0

The low level of the CAN bus is 1.5V, indicating logic 1

7. Calculation of CAN bus baud rate

The CAN clock is RCC_APB1PeriphClock. Please note that the CAN clock frequency 
CAN baud rate = RCC_APB1PeriphClock/CAN_SJW CAN_BS1 CAN_BS2/CAN_Prescaler; 
if the CAN clock is 8M, CAN_SJW = 1, CAN_BS1 = 8, CAN_BS2 = 7, CAN_Prescaler = 2 
, then the baud rate is = 8M/(1 8 7)/2=250K 

8. Arbitration mechanism of CAN bus

Priority is determined by arbitration:

    (1) If at the same time, a standard format message and an extended format message seize the bus at the same time, and their basic IDs are the same, then the node sending the standard format message will succeed in the PK. This is because the extended format is followed by the SRR bit and the IDE bit after the basic ID, and these two bits are recessive. In the standard format, these two bits correspond to the RTR and r1, where RTR can be either a recessive bit or a dominant bit, but r1 must be a dominant bit. According to the arbitration rules, the standard frame will definitely win at this time.

    (2) Similarly, if a data frame with the same format and ID competes with a remote frame for bus control at the same time, the data frame will win because RTR explicitly indicates a data frame and implicitly indicates a remote frame.

 
The configuration of the CAN bus of stm32 is as follows:
      CAN_InitStructure.CAN_TTCM=DISABLE;//Disable time-triggered communication mode
      CAN_InitStructure.CAN_ABOM=DISABLE;
      CAN_InitStructure.CAN_AWUM=DISABLE;
      CAN_InitStructure.CAN_NART=DISABLE;//CAN message is only sent once, regardless of the result of the transmission (success, error or arbitration loss) 
      CAN_InitStructure.CAN_RFLM=DISABLE;
      CAN_InitStructure.CAN_TXFP=DISABLE;
      CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
      //CAN_Mode_LoopBack
      //CAN_Mode_Normal
      CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
      CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;//1--16
      CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;//1--8
      CAN_InitStructure.CAN_Prescaler=2;

      CAN_Init(&CAN_InitStructure);
       /* CAN filter init */
      CAN_FilterInitStructure.CAN_FilterNumber=0;//Select filter 0
      CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//Specify that the filter is set to identifier mask mode
      CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//Give the filter a bit width of 32 bits
 
The following determines the configuration of the CAN bus according to the different set parameters:
1. Filter the extended data frame: (only receive the extended data frame)
      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<3)&0xFFFF0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
(Note: standard frame data frame, standard remote frame and extended remote frame are all filtered)
2. Filter the extended remote frame: (only receive the extended remote frame)
      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<3)&0xFFFF0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_REMOTE)&0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInit Structure.CAN_FilterMaskIdLow = 0xFFFF;
3. Filter standard remote frames: (only receive standard remote frames)
      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<21)&0xffff0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_REMOTE)&0xffff;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
4. Filter standard data frames: (only receive standard data frames)
      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<21)&0xffff0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
5. Filter extended frames: (extended frames will not be filtered out)
      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<3)&0xFFFF0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<3)|CAN_ID_EXT)&0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFC;
6. Filter standard frames: (standard frames will not be filtered out)
      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<21)&0xffff0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<21)|CAN_ID_STD)&0xffff;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFC;
Note: slave_id is the ID number to be filtered.

Keywords:stm32 Reference address:A thorough study of the CAN bus based on stm32

Previous article:Thermocouple Measurement System Based on Cortex-M3 Microcontroller
Next article:STM32 programming software simulates IIC to read and write 24C02 memory

Recommended ReadingLatest update time:2024-11-16 22:55

Why does STM32 have SysTick?
Why does STM32 need SysTick? There are many tim timers in STM32, why does it need SysTick? System time base timer  This timer is dedicated to real-time operating systems and can also be used as a standard down counter. It has the following features:  ● 24-bit down counter  ● Automatic reload function  ●
[Microcontroller]
STM32 serial port reception uses DMA double buffering
#define IMAGE_BUFFER_SIZE 100 //In words After testing, increasing this value did not improve the speed u32 Image_Buffer1 ={0}; u32 Image_Buffer2 ={0}; //OV2640 JPEG mode interface configuration void OV2640_JpegDcmiInit(void) { DCMI_InitTypeDef DCMI_InitStructure; DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef
[Microcontroller]
STM32 development of STM32 hardware IIC operation
  STM32 has an IIC interface, which has the following main features Multi-host function: the module can be used as both a master device and a slave device Main device function C address detection Generate and detect 7-bit/10-bit addresses and general calls Support different communication speeds Status Flag
[Microcontroller]
STM32 development of STM32 hardware IIC operation
STM32 timer 4-channel counter application
The universal timer is indeed quite powerful, and I am quite dizzy with its many functions.  This is to count and light up the lamp like C51 without involving PWM and DMA.  Of course, you need to configure some IO ports for lighting, which I will not go into details here.   like #defineLED2_ON  GPIO_ResetBits(
[Microcontroller]
Commonly used sending functions of USART in STM32
1. Interrupt mode void USART2_IRQHandler(void) //Serial port 2 interrupt service routine {  u8 u8Temp;  /*****************Send interrupt****************************************/  if (USART_GetITStatus(USART2, USART_IT_TXE) == SET)  {    if(TX2_cn == TX2_no)   {   DIS_485TX();   USART_ITConfig(USART2, USART_IT_TXE, D
[Microcontroller]
STM32 counter configuration
void Counter_Config() {    NVIC_InitTypeDef NVIC_InitStructure;      GPIO_InitTypeDef GPIO_InitStructure;    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;  GPIO
[Microcontroller]
Some lessons on STM32 16-bit IO port operation
I have taken a lot of detours when using TFT screens recently. Since TFT screens are all 16-bit, most of them use a set of IO ports corresponding to 16 data bits to transmit data through parallel ports. Recently, due to the shortage of IO ports, I wanted to change to a serial port, but found that the serial port refre
[Microcontroller]
STM32 NVIC
Understanding of NVIC (Nested Vectored Interrupt Control) in STM32 (Cortex-M3) 1. The concept of priority in STM32 (Cortex-M3)       There are two priority concepts in STM32 (Cortex-M3): preemptive priority and response priority. The response priority is also called "sub-priority" or "sub-priority". Each interrupt s
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号