STM32 CAN bus application, debugging is for reference only

Publisher:VS821001Latest update time:2017-02-16 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

1. Turn on the STM32 CAN system working clock 

 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

2. Open system interruption, select according to actual situation

   
    NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
  
//     NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX1_IRQn;
//     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
//     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//     NVIC_Init(&NVIC_InitStructure);

    //NVIC_InitStructure.NVIC_IRQChannel = CAN1_SCE_IRQn;
    //NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
    //NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    //NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    //NVIC_Init(&NVIC_InitStructure);
   
//     NVIC_InitStructure.NVIC_IRQChannel = USB_HP_CAN1_TX_IRQn;
//     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
//     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//     NVIC_Init(&NVIC_InitStructure);

3. Port Configuration

//初始化MCU_CAN_RXD---PA11
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

//初始化MCU_CAN_TXD---PA12 
    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);  

4. CAN initialization


void CAN_Configuration(void)
{
    CAN_InitTypeDef        CAN_InitStructure;
    CAN_FilterInitTypeDef  CAN_FilterInitStructure;

   
    CAN_DeInit(CAN1);
    CAN_StructInit(&CAN_InitStructure);

   
    CAN_InitStructure.CAN_TTCM = DISABLE;
    CAN_InitStructure.CAN_ABOM = DISABLE;
    CAN_InitStructure.CAN_AWUM = DISABLE;
    CAN_InitStructure.CAN_NART = ENABLE;
    CAN_InitStructure.CAN_RFLM = DISABLE;
    CAN_InitStructure.CAN_TXFP = ENABLE; 
    //CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;     
    CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq;     
    CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;     
    CAN_InitStructure.CAN_Prescaler = 200;          

   
                       //Here Tseg1+1 = CAN_BS1_8tp
   

    if (CAN_Init(CAN1,&CAN_InitStructure) == CANINITFAILED)   
    {
                        
                                         
    } 
   
   
   
   
   
   
   
   
   
   
   
    CAN_FilterInitStructure.CAN_FilterNumber=0;    
    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; 
    CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0; 
    CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);
   
    
    CAN_FilterInitStructure.CAN_FilterNumber=1;    
    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; 
    CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=1; 
    //CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);
   
    CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);  
    CAN_ITConfig(CAN2, CAN_IT_TME, ENABLE);   //打开发送中断
 CAN_ITConfig(CAN2, CAN_IT_FMP1, ENABLE);  //打开接收中断
 CAN_ITConfig(CAN2, CAN_IT_EWG|CAN_IT_EPV|CAN_IT_BOF|CAN_IT_LEC|CAN_IT_ERR, ENABLE);//打开错误中断
   
    //CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);  //FIFO0 消息挂号中断屏蔽
    //CAN_ITConfig(CAN1,CAN_IT_TME, ENABLE);   //发送邮箱空中断屏蔽
    //CAN_ITConfig(CAN1,CAN_IT_BOF, ENABLE);   //离线中断允许
}

5. Send data function


void CanWriteData(uint16_t CanAddress,uint8_t SendData[8])
{
   
    CanTxMsg TxMessage; //Define data structure type variable
    u8 TransmitMailbox = 0;
    u16 i = 0;
    TxMessage.StdId = CanAddress;
    TxMessage.ExtId=0x00; //tempId is the address of the receiving board, which needs to be shifted left by 13 bits during application
    TxMessage.IDE=CAN_ID_STD; //Use standard id
    TxMessage.RTR=CAN_RTR_DATA; //Send data frame
    TxMessage.DLC= 8; //Set the length of the data to be sent
    TxMessage.Data[0] = SendData[0]; //Assign value to be sent
    TxMessage.Data[1] = SendData[1]; //Assign value to be sent
    TxMessage.Data[2] = SendData[2]; //Assign value to be sent
    TxMessage.Data[3] = SendData[3];//Assign value to be sentTxMessage.Data
    [4] = SendData[4];//Assign value to be
    sentTxMessage.Data[5] = SendData[5];//Assign value to be
    sentTxMessage.Data[6] = SendData[6];//Assign value to be
    sentTxMessage.Data[7] = SendData[7];//Assign value to be
    sentTransmitMailbox = CAN_Transmit(CAN1,&TxMessage);//Start sending datai
    = 0;
    //Confirm whether the transmission is successful by checking the CANTXOK bitwhile
    ((CAN_TransmitStatus(CAN1,TransmitMailbox) != CANTXOK) && (i != 0xFF))
    {
        i++;
    }
    i = 0;
    while((CAN_MessagePending(CAN1,CAN_FIFO0) < 1) && (i != 0xFF)) //Return whether the number of pending messages is 0
    {
        i++;
    }
}

void SEND_CAN_TQ_COMMAND(u8 device_add,u8 GFB_flag,u8 TQ_A_flag,u8 TQ_B_flag)
{
    u16 Send_add,num;
    u8  Send_Data[8];
    if(device_add == 0)
    {
        switch(GFB_flag)
        {
            case 90:
                if(TQ_A_flag == 0x22)
                {
                    TQ_CON_A = 1;
                    TQ_CON_B = 1;
                    TQ_CON_C = 1;
                    JDQ_A_Flag = 0x07;
                    Net_Node_CapA[0] = Net_Node_CapA[0]|0x07;
                }
                else if(TQ_A_flag == 0x11)
                {
                    TQ_CON_A = 0;
                    TQ_CON_B = 0;
                    TQ_CON_C = 0;
                    JDQ_A_Flag = 0x00;
                    Net_Node_CapA[0] = Net_Node_CapA[0]&0x00;
                }
                if(TQ_B_flag == 0x22)
                {
                    TQ_CON_2A = 1;
                    TQ_CON_2B = 1;
                    TQ_CON_2C = 1;
                    JDQ_B_Flag = 0x07;
                    Net_Node_CapB[0] = Net_Node_CapB[0]|0x07;
                }
                else if(TQ_B_flag == 0x11)
                {
                    TQ_CON_2A = 0;
                    TQ_CON_2B = 0;
                    TQ_CON_2C = 0;
                    JDQ_B_Flag = 0x00;
                    Net_Node_CapB[0] = Net_Node_CapB[0]&0x00;
                }
                break;
            case 91:
                if(TQ_A_flag == 0x22)
                {
                    TQ_CON_A = 1;
                    JDQ_A_Flag |= 0x04;
                    Net_Node_CapA[0] = Net_Node_CapA[0]|0x04;
                }
                else if(TQ_A_flag == 0x11)
                {
                    TQ_CON_A = 0;
                    JDQ_A_Flag &= 0xFB;
                    Net_Node_CapA[0] = Net_Node_CapA[0]&0xFB;
                }
                break;
            case 92:
                if(TQ_A_flag == 0x22)
                {
                    TQ_CON_A = 1;
                    JDQ_A_Flag |= 0x02;
                    Net_Node_CapA[0] = Net_Node_CapA[0]|0x02;
                }
                else if(TQ_A_flag == 0x11)
                {
                    TQ_CON_A = 0;
                    JDQ_A_Flag &= 0xFD;
                    Net_Node_CapA[0] = Net_Node_CapA[0]&0xFD;
                }
                break;
            case 93:
                if(TQ_A_flag == 0x22)
                {
                    TQ_CON_A = 1;
                    JDQ_A_Flag |= 0x01;
                    Net_Node_CapA[0] = Net_Node_CapA[0]|0x01;
                }
                else if(TQ_A_flag == 0x11)
                {
                    TQ_CON_A = 0;
                    JDQ_A_Flag &= 0xFE;
                    Net_Node_CapA[0] = Net_Node_CapA[0]&0xFE;
                }
                break;
        }
    }
    else
    {
        Send_add = 0x100 + device_add;
        Send_Data[0] = 0x55;
        Send_Data[1] = 0x01;
        Send_Data[2] = device_add;      //从机地址
        Send_Data[3] = GFB_flag;   //共补投入控制指令
        Send_Data[4] = TQ_A_flag;
        Send_Data[5] = TQ_B_flag;   
        num = Send_Data[1] + Send_Data[2] + Send_Data[3] + Send_Data[4] + Send_Data[5];
        Send_Data[6] = num&0xFF;         
        Send_Data[7] = 0xAA;
        CanWriteData(Send_add,Send_Data);
        switch(GFB_flag)
        {
            case 90:
                if(TQ_A_flag == 0x22)
                {
                    Net_Node_CapA[device_add] = Net_Node_CapA[device_add]|0x07;
                }
                else if(TQ_A_flag == 0x11)
                {
                    Net_Node_CapA[device_add] = Net_Node_CapA[device_add]&0x00;
                }
                if(TQ_B_flag == 0x22)
                {
                    Net_Node_CapB[device_add] = Net_Node_CapB[device_add]|0x07;
                }
                else if(TQ_B_flag == 0x11)
                {
                    Net_Node_CapB[device_add] = Net_Node_CapB[device_add]&0x00;
                }
                break;
            case 91:
                if(TQ_A_flag == 0x22)
                {
                    Net_Node_CapA[device_add] = Net_Node_CapA[device_add]|0x04;
                }
                else if(TQ_A_flag == 0x11)
                {
                    Net_Node_CapA[device_add] = Net_Node_CapA[device_add]&0xFB;
                }
                break;
            case 92:
                if(TQ_A_flag == 0x22)
                {
                    Net_Node_CapA[device_add] = Net_Node_CapA[device_add]|0x02;
                }
                else if(TQ_A_flag == 0x11)
                {
                    Net_Node_CapA[device_add] = Net_Node_CapA[device_add]&0xFD;
                }
                break;
            case 93:
                if(TQ_A_flag == 0x22)
                {
                    Net_Node_CapA[device_add] = Net_Node_CapA[device_add]|0x01;
                }
                else if(TQ_A_flag == 0x11)
                {
                    Net_Node_CapA[device_add] = Net_Node_CapA[device_add]&0xFE;
                }
                break;
        }
    }
}

6. Interrupt receiving function

void USB_LP_CAN1_RX0_IRQHandler(void) //CAN interrupt function
{
    CanRxMsg RxMessage;
    u8 i;
    RxMessage.StdId=0x00; //Initialize the receive data pool
    RxMessage.ExtId=0x00;   
    RxMessage.IDE=0;    
    RxMessage.DLC=0;    
    RxMessage.FMI =0;    
    RxMessage.Data[0]=0x00;  
    RxMessage.Data[1]=0x00;  
    RxMessage.Data[2]=0x00;
    RxMessage.Data[3]=0x00;
    RxMessage.Data[4]=0x00
    ; Data[5]=0x00;
    RxMessage.Data[6]=0x00;
    RxMessage.Data[7]=0x00;
    //while(CAN_IT_FF0==0);
    for(i=0;i<8;i++)
    {
        if(Can_Receive_Flag[i] == 0)
        {
            if(CAN_IT_FF0 > 0)            
            {
                CAN_Receive(CAN1, CAN_FIFO0, &RxMessage); //Receive messages from CAN1 port buffer FIFO 0 to RxMessage
                CAN_Receive_data[i][0] = ( RxMessage.StdId>>8)&0xff;
                CAN_Receive_data[i][1] = (RxMessage.StdId)&0xff;
                CAN_Receive_data[i][2] = RxMessage.Data[0];
                CAN_Receive_data[i][3] = RxMessage.Data [1];
                CAN_Receive_data[i][4] = RxMessage.Data[2];
                CAN_Receive_data[i][5] = RxMessage.Data[3];
                CAN_Receive_data[i][6] = RxMessage.Data[4];
                CAN_Receive_data [i][7] = RxMessage.Data[5];
                CAN_Receive_data[i][8] = RxMessage.Data[6];
                CAN_Receive_data[i][9] = RxMessage.Data[7];
                CAN_Receive_data[i][10] = 0xff;
                Can_Receive_Flag[i ] = 1;
                break;
            }
            if(CAN_IT_FF1 > 0)
            {
                CAN_Receive(CAN1, CAN_FIFO1, &RxMessage); //Receive messages from CAN1 port buffer FIFO 0 to RxMessage
                CAN_Receive_data[i][0] = (RxMessage.StdId> >8)&0xff;
                CAN_Receive_data[i][1] = (RxMessage.StdId)&0xff;
                CAN_Receive_data[i][2] = RxMessage.Data[0];
                CAN_Receive_data[i][3] = RxMessage.Data[1];
                CAN_Receive_data[i][4] = RxMessage.Data[2];
                CAN_Receive_data[i][5] = RxMessage.Data[3];
                CAN_Receive_data[i][6] = RxMessage.Data[4];
                CAN_Receive_data[i][7] = RxMessage.Data[ 5];
                CAN_Receive_data[i][8] = RxMessage.Data[6];
                CAN_Receive_data[i][9] = RxMessage.Data[7];
                CAN_Receive_data[i][10] = 0xff;
                Can_Receive_Flag[i] = 1;
                break;
            }
        }
    } 
 CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
}
附录:

The receiving and sending functions are test program codes in the current project and can be adjusted according to actual conditions.


Keywords:STM32 Reference address:STM32 CAN bus application, debugging is for reference only

Previous article:STM32 small package PD0, PD1 have no external interrupt function
Next article:STM32 CAN filtering principle

Recommended ReadingLatest update time:2024-11-17 09:57

STM32 timer remapping
 void TIM3_GPIOB5_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE); GPIO_AFIODeInit(); //Restore the remapping to the initial value //This can only be called once in the program, otherwise the previous setting
[Microcontroller]
stm32 SPI-FLASH W25Q64
W25Q64 SPI Configuration Steps 1. Enable SPI clock 2. Enable GPIO port clock 3. Initialize GPIO and configure pin mode 4. Initialize SPI 5. Enable SPI 6. SPI read and write data 7. Check SPI transmission status Example typedef struct { uint16_t SPI_Direction; uint16_t SPI_Mode;  uint16_t SPI
[Microcontroller]
stm32 SPI-FLASH W25Q64
How to view the system clock in STM32 CubeMX
code show as below: uint32_t sysclock = 0;    sysclock = HAL_RCC_GetSysClockFreq(); In this way, you can view sysclock during online simulation to determine whether the microcontroller is running normally. These functions are all in the rcc library file, and you can also view the clocks on other buses on the clo
[Microcontroller]
STM32ADC conversion interrupt read
The ADC interrupt reading method is suitable for low-frequency ADC acquisition, while high-frequency AD acquisition must use DMA. The initialization function of ADC interrupt reading only adds an interrupt configuration file compared to the direct reading method in the previous article. The code is as follows: static
[Microcontroller]
STM32 register operation mode learning-clock configuration
1. When the STM32 is just powered on, it runs from the internal oscillator with a frequency of 8 MHz. If the program sets the external high-speed clock (HSE) as the system clock source, the operation of the HSI related registers before the external high-speed clock is ready is invalid, and the value of the related bit
[Microcontroller]
STM32-Serial communication printf redirection
Preface: When we do C language programming, we often use the printf function to print out and debug the code. However, this printf function C library has already implemented it for us, and usually we only need to call it directly. But if we are on a new development platform, if the library has not implemented it for u
[Microcontroller]
How to download programs using the STM32 serial port (USB serial port)
1. Steps for STM32 serial port download program  1) Install "CH340 driver (USB serial port driver)_XP_WIN7 common"  2) Open the serial port download software "STM32F4 serial port download software (FLYMCU)"  3) Connect the USB interface of the development board to the USB port of the computer and power the development
[Microcontroller]
Design and implementation of digital oscilloscope based on STM32
0 Introduction With the development of integrated circuits and the adoption of digital signal processing technology, digital oscilloscopes have become intelligent measuring instruments that integrate various functions such as display, measurement, calculation, analysis, and recording. Digital oscilloscopes have gradu
[Test Measurement]
Design and implementation of digital oscilloscope based on STM32
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号