STM32F1(CAN)

                                          STM32F1(CAN)

GitHub 仓库:https://github.com/XinLiGH/STM32F1xx_CAN_Example

PS:博文不再更新,后续更新会在 GitHub 仓库进行。

 

1,开发环境

1,固件库:STM32F10x_StdPeriph_Lib_V3.5.0

2,编译器:ARMCC V5.06

3,IDE:Keil uVision5

4,操作系统:Windows 10 专业版

 

2,程序源码

RingBuffer.h 文件

/**
  ******************************************************************************
  * @file    RingBuffer.h
  * @author  XinLi
  * @version v1.1
  * @date    15-January-2018
  * @brief   Header file for RingBuffer.c module.
  ******************************************************************************
  * @attention
  *
  * 

Copyright © 2018 XinLi

* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ****************************************************************************** */ #ifndef __RINGBUFFER_H #define __RINGBUFFER_H #ifdef __cplusplus extern "C" { #endif /* Header includes -----------------------------------------------------------*/ #include #include #include /* Macro definitions ---------------------------------------------------------*/ #define RING_BUFFER_MALLOC(size) malloc(size) #define RING_BUFFER_FREE(block) free(block) /* Type definitions ----------------------------------------------------------*/ typedef struct { uint8_t *buffer; uint32_t size; uint32_t in; uint32_t out; }RingBuffer; /* Variable declarations -----------------------------------------------------*/ /* Variable definitions ------------------------------------------------------*/ /* Function declarations -----------------------------------------------------*/ RingBuffer *RingBuffer_Malloc(uint32_t size); void RingBuffer_Free(RingBuffer *fifo); uint32_t RingBuffer_In(RingBuffer *fifo, void *in, uint32_t len); uint32_t RingBuffer_Out(RingBuffer *fifo, void *out, uint32_t len); /* Function definitions ------------------------------------------------------*/ /** * @brief Removes the entire FIFO contents. * @param [in] fifo: The fifo to be emptied. * @return None. */ static inline void RingBuffer_Reset(RingBuffer *fifo) { fifo->in = fifo->out = 0; } /** * @brief Returns the size of the FIFO in bytes. * @param [in] fifo: The fifo to be used. * @return The size of the FIFO. */ static inline uint32_t RingBuffer_Size(RingBuffer *fifo) { return fifo->size; } /** * @brief Returns the number of used bytes in the FIFO. * @param [in] fifo: The fifo to be used. * @return The number of used bytes. */ static inline uint32_t RingBuffer_Len(RingBuffer *fifo) { return fifo->in - fifo->out; } /** * @brief Returns the number of bytes available in the FIFO. * @param [in] fifo: The fifo to be used. * @return The number of bytes available. */ static inline uint32_t RingBuffer_Avail(RingBuffer *fifo) { return RingBuffer_Size(fifo) - RingBuffer_Len(fifo); } /** * @brief Is the FIFO empty? * @param [in] fifo: The fifo to be used. * @retval true: Yes. * @retval false: No. */ static inline bool RingBuffer_IsEmpty(RingBuffer *fifo) { return RingBuffer_Len(fifo) == 0; } /** * @brief Is the FIFO full? * @param [in] fifo: The fifo to be used. * @retval true: Yes. * @retval false: No. */ static inline bool RingBuffer_IsFull(RingBuffer *fifo) { return RingBuffer_Avail(fifo) == 0; } #ifdef __cplusplus } #endif #endif /* __RINGBUFFER_H */

RingBuffer.c 文件

/**
  ******************************************************************************
  * @file    RingBuffer.c
  * @author  XinLi
  * @version v1.1
  * @date    15-January-2018
  * @brief   Ring buffer module source file.
  ******************************************************************************
  * @attention
  *
  * 

Copyright © 2018 XinLi

* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ****************************************************************************** */ /* Header includes -----------------------------------------------------------*/ #include "RingBuffer.h" #include /* Macro definitions ---------------------------------------------------------*/ #define min(a, b) (((a) < (b)) ? (a) : (b)) /* Type definitions ----------------------------------------------------------*/ /* Variable declarations -----------------------------------------------------*/ /* Variable definitions ------------------------------------------------------*/ /* Function declarations -----------------------------------------------------*/ static bool is_power_of_2(uint32_t x); static uint32_t roundup_pow_of_two(uint32_t x); /* Function definitions ------------------------------------------------------*/ /** * @brief Allocates a new FIFO and its internal buffer. * @param [in] size: The size of the internal buffer to be allocated. * @note The size will be rounded-up to a power of 2. * @return RingBuffer pointer. */ RingBuffer *RingBuffer_Malloc(uint32_t size) { RingBuffer *fifo = RING_BUFFER_MALLOC(sizeof(RingBuffer)); if(fifo != NULL) { if(is_power_of_2(size) != true) { if(size > 0x80000000UL) { RING_BUFFER_FREE(fifo); return NULL; } size = roundup_pow_of_two(size); } fifo->buffer = RING_BUFFER_MALLOC(size); if(fifo->buffer == NULL) { RING_BUFFER_FREE(fifo); return NULL; } fifo->size = size; fifo->in = fifo->out = 0; } return fifo; } /** * @brief Frees the FIFO. * @param [in] fifo: The fifo to be freed. * @return None. */ void RingBuffer_Free(RingBuffer *fifo) { RING_BUFFER_FREE(fifo->buffer); RING_BUFFER_FREE(fifo); } /** * @brief Puts some data into the FIFO. * @param [in] fifo: The fifo to be used. * @param [in] in: The data to be added. * @param [in] len: The length of the data to be added. * @return The number of bytes copied. * @note This function copies at most @len bytes from the @in into * the FIFO depending on the free space, and returns the number * of bytes copied. */ uint32_t RingBuffer_In(RingBuffer *fifo, void *in, uint32_t len) { len = min(len, RingBuffer_Avail(fifo)); /* First put the data starting from fifo->in to buffer end. */ uint32_t l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), in, l); /* Then put the rest (if any) at the beginning of the buffer. */ memcpy(fifo->buffer, (uint8_t *)in + l, len - l); fifo->in += len; return len; } /** * @brief Gets some data from the FIFO. * @param [in] fifo: The fifo to be used. * @param [in] out: Where the data must be copied. * @param [in] len: The size of the destination buffer. * @return The number of copied bytes. * @note This function copies at most @len bytes from the FIFO into * the @out and returns the number of copied bytes. */ uint32_t RingBuffer_Out(RingBuffer *fifo, void *out, uint32_t len) { len = min(len, RingBuffer_Len(fifo)); /* First get the data from fifo->out until the end of the buffer. */ uint32_t l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); memcpy(out, fifo->buffer + (fifo->out & (fifo->size - 1)), l); /* Then get the rest (if any) from the beginning of the buffer. */ memcpy((uint8_t *)out + l, fifo->buffer, len - l); fifo->out += len; return len; } /** * @brief Determine whether some value is a power of two. * @param [in] x: The number to be confirmed. * @retval true: Yes. * @retval false: No. * @note Where zero is not considered a power of two. */ static bool is_power_of_2(uint32_t x) { return (x != 0) && ((x & (x - 1)) == 0); } /** * @brief Round the given value up to nearest power of two. * @param [in] x: The number to be converted. * @return The power of two. */ static uint32_t roundup_pow_of_two(uint32_t x) { uint32_t b = 0; for(int i = 0; i < 32; i++) { b = 1UL << i; if(x <= b) { break; } } return b; }

CAN.h 文件

/**
  ******************************************************************************
  * @file    CAN.h
  * @author  XinLi
  * @version v1.0
  * @date    24-June-2018
  * @brief   Header file for CAN.c module.
  ******************************************************************************
  * @attention
  *
  * 

Copyright © 2018 XinLi

* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ****************************************************************************** */ #ifndef __CAN_H #define __CAN_H #ifdef __cplusplus extern "C" { #endif /* Header includes -----------------------------------------------------------*/ #include "stm32f10x.h" #include /* Macro definitions ---------------------------------------------------------*/ /******************************* CAN1 Configure *******************************/ #define CAN1_TX_BUFFER_SIZE (16) #define CAN1_RX_BUFFER_SIZE (16) #define CAN1_TX_GPIO_CLOCK RCC_APB2Periph_GPIOB #define CAN1_RX_GPIO_CLOCK RCC_APB2Periph_GPIOB #define CAN1_TX_GPIO_PORT GPIOB #define CAN1_RX_GPIO_PORT GPIOB #define CAN1_TX_GPIO_PIN GPIO_Pin_9 #define CAN1_RX_GPIO_PIN GPIO_Pin_8 #define CAN1_IRQ_PREEMPT_PRIORITY (0) #define CAN1_IRQ_SUB_PRIORITY (0) #define CAN1_PORT_REMAP() GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE) /******************************************************************************/ #ifdef STM32F10X_CL /******************************* CAN2 Configure *******************************/ #define CAN2_TX_BUFFER_SIZE (16) #define CAN2_RX_BUFFER_SIZE (16) #define CAN2_TX_GPIO_CLOCK RCC_APB2Periph_GPIOB #define CAN2_RX_GPIO_CLOCK RCC_APB2Periph_GPIOB #define CAN2_TX_GPIO_PORT GPIOB #define CAN2_RX_GPIO_PORT GPIOB #define CAN2_TX_GPIO_PIN GPIO_Pin_13 #define CAN2_RX_GPIO_PIN GPIO_Pin_12 #define CAN2_IRQ_PREEMPT_PRIORITY (0) #define CAN2_IRQ_SUB_PRIORITY (0) #define CAN2_PORT_REMAP() GPIO_PinRemapConfig(GPIO_Remap_CAN2 , DISABLE) /******************************************************************************/ #endif /* STM32F10X_CL */ /* Type definitions ----------------------------------------------------------*/ typedef enum { CAN_WorkModeNormal = CAN_Mode_Normal, CAN_WorkModeLoopBack = CAN_Mode_LoopBack }CAN_WorkMode; typedef enum { CAN_BaudRate1000K = 6, CAN_BaudRate500K = 12, CAN_BaudRate250K = 24, CAN_BaudRate125K = 48, CAN_BaudRate100K = 60, CAN_BaudRate50K = 120, CAN_BaudRate20K = 300, CAN_BaudRate10K = 600 }CAN_BaudRate; /* Variable declarations -----------------------------------------------------*/ /* Variable definitions ------------------------------------------------------*/ /* Function declarations -----------------------------------------------------*/ void CAN_Configure(CAN_TypeDef *CANx, CAN_WorkMode WorkMode, CAN_BaudRate BaudRate, uint32_t StdId, uint32_t ExtId); void CAN_Unconfigure(CAN_TypeDef *CANx); void CAN_SetTransmitFinishCallback(CAN_TypeDef *CANx, void (*Callback)(void)); void CAN_SetReceiveFinishCallback(CAN_TypeDef *CANx, void (*Callback)(void)); uint32_t CAN_SetTransmitMessage(CAN_TypeDef *CANx, CanTxMsg *Message, uint32_t Number); uint32_t CAN_GetReceiveMessage(CAN_TypeDef *CANx, CanRxMsg *Message, uint32_t Number); uint32_t CAN_GetUsedTransmitBufferSize(CAN_TypeDef *CANx); uint32_t CAN_GetUsedReceiveBufferSize(CAN_TypeDef *CANx); uint32_t CAN_GetUnusedTransmitBufferSize(CAN_TypeDef *CANx); uint32_t CAN_GetUnusedReceiveBufferSize(CAN_TypeDef *CANx); bool CAN_IsTransmitBufferEmpty(CAN_TypeDef *CANx); bool CAN_IsReceiveBufferEmpty(CAN_TypeDef *CANx); bool CAN_IsTransmitBufferFull(CAN_TypeDef *CANx); bool CAN_IsReceiveBufferFull(CAN_TypeDef *CANx); void CAN_ClearTransmitBuffer(CAN_TypeDef *CANx); void CAN_ClearReceiveBuffer(CAN_TypeDef *CANx); bool CAN_IsTransmitMessage(CAN_TypeDef *CANx); /* Function definitions ------------------------------------------------------*/ #ifdef __cplusplus } #endif #endif /* __CAN_H */

CAN.c 文件

/**
  ******************************************************************************
  * @file    CAN.c
  * @author  XinLi
  * @version v1.0
  * @date    24-June-2018
  * @brief   CAN module driver.
  ******************************************************************************
  * @attention
  *
  * 

Copyright © 2018 XinLi

* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ****************************************************************************** */ /* Header includes -----------------------------------------------------------*/ #include "CAN.h" #include "RingBuffer.h" /* Macro definitions ---------------------------------------------------------*/ /* Type definitions ----------------------------------------------------------*/ /* Variable declarations -----------------------------------------------------*/ static volatile bool can1InitFlag = false; static volatile bool can1TransmitFlag = false; static volatile void (*can1TransmitFinishCallback)(void) = 0; static volatile void (*can1ReceiveFinishCallback)(void) = 0; static RingBuffer *can1TxBuffer = 0; static RingBuffer *can1RxBuffer = 0; #ifdef STM32F10X_CL static volatile bool can2InitFlag = false; static volatile bool can2TransmitFlag = false; static volatile void (*can2TransmitFinishCallback)(void) = 0; static volatile void (*can2ReceiveFinishCallback)(void) = 0; static RingBuffer *can2TxBuffer = 0; static RingBuffer *can2RxBuffer = 0; #endif /* STM32F10X_CL */ /* Variable definitions ------------------------------------------------------*/ /* Function declarations -----------------------------------------------------*/ /* Function definitions ------------------------------------------------------*/ /** * @brief CAN configure. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @param [in] WorkMode: Work mode. * @param [in] BaudRate: Communication baud rate. * @param [in] StdId: Filter standard frame ID. * @param [in] ExtId: Filter extended frame ID. * @return None. */ void CAN_Configure(CAN_TypeDef *CANx, CAN_WorkMode WorkMode, CAN_BaudRate BaudRate, uint32_t StdId, uint32_t ExtId) { GPIO_InitTypeDef GPIO_InitStructure = {0}; CAN_InitTypeDef CAN_InitStructure = {0}; CAN_FilterInitTypeDef CAN_FilterInitStructure = {0}; NVIC_InitTypeDef NVIC_InitStructure = {0}; if(CANx == CAN1) { if(can1InitFlag == false) { can1InitFlag = true; can1TransmitFlag = false; can1TransmitFinishCallback = 0; can1ReceiveFinishCallback = 0; can1TxBuffer = RingBuffer_Malloc(sizeof(CanTxMsg) * CAN1_TX_BUFFER_SIZE); can1RxBuffer = RingBuffer_Malloc(sizeof(CanRxMsg) * CAN1_RX_BUFFER_SIZE); #ifdef STM32F10X_CL if(can2InitFlag == false) #endif /* STM32F10X_CL */ { RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); } RCC_APB2PeriphClockCmd(CAN1_TX_GPIO_CLOCK | CAN1_RX_GPIO_CLOCK | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin = CAN1_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(CAN1_TX_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = CAN1_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(CAN1_RX_GPIO_PORT, &GPIO_InitStructure); CAN1_PORT_REMAP(); CAN_InitStructure.CAN_Prescaler = BaudRate; CAN_InitStructure.CAN_Mode = WorkMode; CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; CAN_InitStructure.CAN_TTCM = DISABLE; CAN_InitStructure.CAN_ABOM = ENABLE; CAN_InitStructure.CAN_AWUM = DISABLE; CAN_InitStructure.CAN_NART = ENABLE; CAN_InitStructure.CAN_RFLM = DISABLE; CAN_InitStructure.CAN_TXFP = ENABLE; CAN_DeInit(CAN1); CAN_Init(CAN1, &CAN_InitStructure); CAN_FilterInitStructure.CAN_FilterIdHigh = (uint16_t)((((StdId<<18)|ExtId)<<3)>>16); CAN_FilterInitStructure.CAN_FilterIdLow = (uint16_t)(((StdId<<18)|ExtId)<<3); CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (~((uint16_t)((((StdId<<18)|ExtId)<<3)>>16)))&0xFFFF; CAN_FilterInitStructure.CAN_FilterMaskIdLow = (~((uint16_t)(((StdId<<18)|ExtId)<<3)))&0xFFF8; CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; CAN_FilterInitStructure.CAN_FilterNumber = 0; CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; CAN_FilterInit(&CAN_FilterInitStructure); CAN_ITConfig(CAN1, CAN_IT_TME | CAN_IT_FMP0 |CAN_IT_FF0 | CAN_IT_FOV0 | CAN_IT_FMP1 | CAN_IT_FF1 | CAN_IT_FOV1 | CAN_IT_WKU | CAN_IT_SLK |CAN_IT_EWG | CAN_IT_EPV | CAN_IT_BOF | CAN_IT_LEC | CAN_IT_ERR, DISABLE); CAN_ITConfig(CAN1, CAN_IT_TME | CAN_IT_FMP0, ENABLE); #ifdef STM32F10X_CL NVIC_InitStructure.NVIC_IRQChannel = CAN1_TX_IRQn; #else NVIC_InitStructure.NVIC_IRQChannel = USB_HP_CAN1_TX_IRQn; #endif /* STM32F10X_CL */ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CAN1_IRQ_PREEMPT_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelSubPriority = CAN1_IRQ_SUB_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #ifdef STM32F10X_CL NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn; #else NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; #endif /* STM32F10X_CL */ NVIC_Init(&NVIC_InitStructure); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == false) { can2InitFlag = true; can2TransmitFlag = false; can2TransmitFinishCallback = 0; can2ReceiveFinishCallback = 0; can2TxBuffer = RingBuffer_Malloc(sizeof(CanTxMsg) * CAN2_TX_BUFFER_SIZE); can2RxBuffer = RingBuffer_Malloc(sizeof(CanRxMsg) * CAN2_RX_BUFFER_SIZE); if(can1InitFlag == false) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); } RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE); RCC_APB2PeriphClockCmd(CAN2_TX_GPIO_CLOCK | CAN2_RX_GPIO_CLOCK | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin = CAN2_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(CAN2_TX_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = CAN2_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(CAN2_RX_GPIO_PORT, &GPIO_InitStructure); CAN2_PORT_REMAP(); CAN_InitStructure.CAN_Prescaler = BaudRate; CAN_InitStructure.CAN_Mode = WorkMode; CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; CAN_InitStructure.CAN_TTCM = DISABLE; CAN_InitStructure.CAN_ABOM = ENABLE; CAN_InitStructure.CAN_AWUM = DISABLE; CAN_InitStructure.CAN_NART = ENABLE; CAN_InitStructure.CAN_RFLM = DISABLE; CAN_InitStructure.CAN_TXFP = ENABLE; CAN_DeInit(CAN2); CAN_Init(CAN2, &CAN_InitStructure); CAN_FilterInitStructure.CAN_FilterIdHigh = (uint16_t)((((StdId<<18)|ExtId)<<3)>>16); CAN_FilterInitStructure.CAN_FilterIdLow = (uint16_t)(((StdId<<18)|ExtId)<<3); CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (~((uint16_t)((((StdId<<18)|ExtId)<<3)>>16)))&0xFFFF; CAN_FilterInitStructure.CAN_FilterMaskIdLow = (~((uint16_t)(((StdId<<18)|ExtId)<<3)))&0xFFF8; CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; CAN_FilterInitStructure.CAN_FilterNumber = 14; CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; CAN_FilterInit(&CAN_FilterInitStructure); CAN_ITConfig(CAN2, CAN_IT_TME | CAN_IT_FMP0 |CAN_IT_FF0 | CAN_IT_FOV0 | CAN_IT_FMP1 | CAN_IT_FF1 | CAN_IT_FOV1 | CAN_IT_WKU | CAN_IT_SLK |CAN_IT_EWG | CAN_IT_EPV | CAN_IT_BOF | CAN_IT_LEC | CAN_IT_ERR, DISABLE); CAN_ITConfig(CAN2, CAN_IT_TME | CAN_IT_FMP0, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = CAN2_TX_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CAN2_IRQ_PREEMPT_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelSubPriority = CAN2_IRQ_SUB_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn; NVIC_Init(&NVIC_InitStructure); } } #endif /* STM32F10X_CL */ } /** * @brief CAN unconfigure. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @return None. */ void CAN_Unconfigure(CAN_TypeDef *CANx) { NVIC_InitTypeDef NVIC_InitStructure = {0}; if(CANx == CAN1) { if(can1InitFlag == true) { can1InitFlag = false; #ifdef STM32F10X_CL NVIC_InitStructure.NVIC_IRQChannel = CAN1_TX_IRQn; #else NVIC_InitStructure.NVIC_IRQChannel = USB_HP_CAN1_TX_IRQn; #endif /* STM32F10X_CL */ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CAN1_IRQ_PREEMPT_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelSubPriority = CAN1_IRQ_SUB_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; NVIC_Init(&NVIC_InitStructure); #ifdef STM32F10X_CL NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn; #else NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; #endif /* STM32F10X_CL */ NVIC_Init(&NVIC_InitStructure); CAN_DeInit(CAN1); #ifdef STM32F10X_CL if(can2InitFlag == false) #endif /* STM32F10X_CL */ { RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, DISABLE); } can1TransmitFlag = false; can1TransmitFinishCallback = 0; can1ReceiveFinishCallback = 0; RingBuffer_Free(can1TxBuffer); RingBuffer_Free(can1RxBuffer); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { can2InitFlag = false; NVIC_InitStructure.NVIC_IRQChannel = CAN2_TX_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CAN2_IRQ_PREEMPT_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelSubPriority = CAN2_IRQ_SUB_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn; NVIC_Init(&NVIC_InitStructure); CAN_DeInit(CAN2); if(can1InitFlag == false) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, DISABLE); } RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, DISABLE); can2TransmitFlag = false; can2TransmitFinishCallback = 0; can2ReceiveFinishCallback = 0; RingBuffer_Free(can2TxBuffer); RingBuffer_Free(can2RxBuffer); } } #endif /* STM32F10X_CL */ } /** * @brief CAN set transmit finish callback. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @param [in] Callback: Callback. * @return None. */ void CAN_SetTransmitFinishCallback(CAN_TypeDef *CANx, void (*Callback)(void)) { if(CANx == CAN1) { if(can1InitFlag == true) { can1TransmitFinishCallback = (volatile void (*)(void))Callback; } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { can2TransmitFinishCallback = (volatile void (*)(void))Callback; } } #endif /* STM32F10X_CL */ } /** * @brief CAN set receive finish callback. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @param [in] Callback: Callback. * @return None. */ void CAN_SetReceiveFinishCallback(CAN_TypeDef *CANx, void (*Callback)(void)) { if(CANx == CAN1) { if(can1InitFlag == true) { can1ReceiveFinishCallback = (volatile void (*)(void))Callback; } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { can2ReceiveFinishCallback = (volatile void (*)(void))Callback; } } #endif /* STM32F10X_CL */ } /** * @brief CAN set transmit message. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @param [in] Message: The address of the message to be transmit. * @param [in] Number: The number of the message to be transmit. * @return The number of message transmit. */ uint32_t CAN_SetTransmitMessage(CAN_TypeDef *CANx, CanTxMsg *Message, uint32_t Number) { if(CANx == CAN1) { if(can1InitFlag == true) { uint32_t available = RingBuffer_Avail(can1TxBuffer) / sizeof(CanTxMsg); if(available > Number) { Number = RingBuffer_In(can1TxBuffer, Message, sizeof(CanTxMsg) * Number) / sizeof(CanTxMsg); } else { Number = RingBuffer_In(can1TxBuffer, Message, sizeof(CanTxMsg) * available) / sizeof(CanTxMsg); } if(Number > 0) { if(can1TransmitFlag == false) { can1TransmitFlag = true; CanTxMsg canTxMsg = {0}; RingBuffer_Out(can1TxBuffer, &canTxMsg, sizeof(canTxMsg)); CAN_Transmit(CAN1, &canTxMsg); } } return Number; } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { uint32_t available = RingBuffer_Avail(can2TxBuffer) / sizeof(CanTxMsg); if(available > Number) { Number = RingBuffer_In(can2TxBuffer, Message, sizeof(CanTxMsg) * Number) / sizeof(CanTxMsg); } else { Number = RingBuffer_In(can2TxBuffer, Message, sizeof(CanTxMsg) * available) / sizeof(CanTxMsg); } if(Number > 0) { if(can2TransmitFlag == false) { can2TransmitFlag = true; CanTxMsg canTxMsg = {0}; RingBuffer_Out(can2TxBuffer, &canTxMsg, sizeof(canTxMsg)); CAN_Transmit(CAN2, &canTxMsg); } } return Number; } } #endif /* STM32F10X_CL */ return 0; } /** * @brief CAN get receive message. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @param [in] Message: To store the address of the receive message. * @param [in] Number: To read the number of the received message. * @return The number of message obtained. */ uint32_t CAN_GetReceiveMessage(CAN_TypeDef *CANx, CanRxMsg *Message, uint32_t Number) { if(CANx == CAN1) { if(can1InitFlag == true) { return RingBuffer_Out(can1RxBuffer, Message, sizeof(CanRxMsg) * Number) / sizeof(CanRxMsg); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { return RingBuffer_Out(can2RxBuffer, Message, sizeof(CanRxMsg) * Number) / sizeof(CanRxMsg); } } #endif /* STM32F10X_CL */ return 0; } /** * @brief Get the size of the CAN transmit buffer used. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @return Used the size of the transmit buffer. */ uint32_t CAN_GetUsedTransmitBufferSize(CAN_TypeDef *CANx) { if(CANx == CAN1) { if(can1InitFlag == true) { return RingBuffer_Len(can1TxBuffer) / sizeof(CanTxMsg); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { return RingBuffer_Len(can2TxBuffer) / sizeof(CanTxMsg); } } #endif /* STM32F10X_CL */ return 0; } /** * @brief Get the size of the CAN receive buffer used. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @return Used the size of the receive buffer. */ uint32_t CAN_GetUsedReceiveBufferSize(CAN_TypeDef *CANx) { if(CANx == CAN1) { if(can1InitFlag == true) { return RingBuffer_Len(can1RxBuffer) / sizeof(CanRxMsg); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { return RingBuffer_Len(can2RxBuffer) / sizeof(CanRxMsg); } } #endif /* STM32F10X_CL */ return 0; } /** * @brief Get the size of the CAN transmit buffer unused. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @return Unused the size of the transmit buffer. */ uint32_t CAN_GetUnusedTransmitBufferSize(CAN_TypeDef *CANx) { if(CANx == CAN1) { if(can1InitFlag == true) { return RingBuffer_Avail(can1TxBuffer) / sizeof(CanTxMsg); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { return RingBuffer_Avail(can2TxBuffer) / sizeof(CanTxMsg); } } #endif /* STM32F10X_CL */ return 0; } /** * @brief Get the size of the CAN receive buffer unused. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @return Unused the size of the receive buffer. */ uint32_t CAN_GetUnusedReceiveBufferSize(CAN_TypeDef *CANx) { if(CANx == CAN1) { if(can1InitFlag == true) { return RingBuffer_Avail(can1RxBuffer) / sizeof(CanRxMsg); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { return RingBuffer_Avail(can2RxBuffer) / sizeof(CanRxMsg); } } #endif /* STM32F10X_CL */ return 0; } /** * @brief Is the CAN transmit buffer empty? * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @retval true: The transmit buffer is empty. * @retval false: The transmit buffer is not empty. */ bool CAN_IsTransmitBufferEmpty(CAN_TypeDef *CANx) { if(CANx == CAN1) { if(can1InitFlag == true) { return !(RingBuffer_Len(can1TxBuffer) / sizeof(CanTxMsg)); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { return !(RingBuffer_Len(can2TxBuffer) / sizeof(CanTxMsg)); } } #endif /* STM32F10X_CL */ return false; } /** * @brief Is the CAN receive buffer empty? * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @retval true: The receive buffer is empty. * @retval false: The receive buffer is not empty. */ bool CAN_IsReceiveBufferEmpty(CAN_TypeDef *CANx) { if(CANx == CAN1) { if(can1InitFlag == true) { return !(RingBuffer_Len(can1RxBuffer) / sizeof(CanRxMsg)); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { return !(RingBuffer_Len(can2RxBuffer) / sizeof(CanRxMsg)); } } #endif /* STM32F10X_CL */ return false; } /** * @brief Is the CAN transmit buffer full? * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @retval true: The transmit buffer is full. * @retval false: The transmit buffer is not full. */ bool CAN_IsTransmitBufferFull(CAN_TypeDef *CANx) { if(CANx == CAN1) { if(can1InitFlag == true) { return !(RingBuffer_Avail(can1TxBuffer) / sizeof(CanTxMsg)); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { return !(RingBuffer_Avail(can2TxBuffer) / sizeof(CanTxMsg)); } } #endif /* STM32F10X_CL */ return false; } /** * @brief Is the CAN receive buffer full? * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @retval true: The receive buffer is full. * @retval false: The receive buffer is not full. */ bool CAN_IsReceiveBufferFull(CAN_TypeDef *CANx) { if(CANx == CAN1) { if(can1InitFlag == true) { return !(RingBuffer_Avail(can1RxBuffer) / sizeof(CanRxMsg)); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { return !(RingBuffer_Avail(can2RxBuffer) / sizeof(CanRxMsg)); } } #endif /* STM32F10X_CL */ return false; } /** * @brief Clear the CAN transmit buffer. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @return None. */ void CAN_ClearTransmitBuffer(CAN_TypeDef *CANx) { if(CANx == CAN1) { if(can1InitFlag == true) { RingBuffer_Reset(can1TxBuffer); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { RingBuffer_Reset(can2TxBuffer); } } #endif /* STM32F10X_CL */ } /** * @brief Clear the CAN receive buffer. * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @return None. */ void CAN_ClearReceiveBuffer(CAN_TypeDef *CANx) { if(CANx == CAN1) { if(can1InitFlag == true) { RingBuffer_Reset(can1RxBuffer); } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { RingBuffer_Reset(can2RxBuffer); } } #endif /* STM32F10X_CL */ } /** * @brief Is the CAN transmit a message? * @param [in] CANx: Where x can be 1 or 2 to select the CAN peripheral. * @retval true: Is transmit a message. * @retval false: Not transmit a message. */ bool CAN_IsTransmitMessage(CAN_TypeDef *CANx) { if(CANx == CAN1) { if(can1InitFlag == true) { return can1TransmitFlag; } } #ifdef STM32F10X_CL if(CANx == CAN2) { if(can2InitFlag == true) { return can2TransmitFlag; } } #endif /* STM32F10X_CL */ return false; } /** * @brief This function handles CAN1 TX Handler. * @param None. * @return None. */ #ifdef STM32F10X_CL void CAN1_TX_IRQHandler(void) #else void USB_HP_CAN1_TX_IRQHandler(void) #endif /* STM32F10X_CL */ { if(CAN_GetITStatus(CAN1, CAN_IT_TME) != RESET) { CAN_ClearITPendingBit(CAN1, CAN_IT_TME); CanTxMsg canTxMsg = {0}; uint8_t number = RingBuffer_Out(can1TxBuffer, &canTxMsg, sizeof(canTxMsg)) / sizeof(canTxMsg); if(number > 0) { CAN_Transmit(CAN1, &canTxMsg); } else { can1TransmitFlag = false; if(can1TransmitFinishCallback != 0) { can1TransmitFinishCallback(); } } } } /** * @brief This function handles CAN1 RX0 Handler. * @param None. * @return None. */ #ifdef STM32F10X_CL void CAN1_RX0_IRQHandler(void) #else void USB_LP_CAN1_RX0_IRQHandler(void) #endif /* STM32F10X_CL */ { if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) != RESET) { CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0); CanRxMsg canRxMsg = {0}; CAN_Receive(CAN1, CAN_FIFO0, &canRxMsg); if(RingBuffer_Avail(can1RxBuffer) / sizeof(CanRxMsg) > 0) { RingBuffer_In(can1RxBuffer, &canRxMsg, sizeof(canRxMsg)); } if(can1ReceiveFinishCallback != 0) { can1ReceiveFinishCallback(); } } } #ifdef STM32F10X_CL /** * @brief This function handles CAN2 TX Handler. * @param None. * @return None. */ void CAN2_TX_IRQHandler(void) { if(CAN_GetITStatus(CAN2, CAN_IT_TME) != RESET) { CAN_ClearITPendingBit(CAN2, CAN_IT_TME); CanTxMsg canTxMsg = {0}; uint8_t number = RingBuffer_Out(can2TxBuffer, &canTxMsg, sizeof(canTxMsg)) / sizeof(canTxMsg); if(number > 0) { CAN_Transmit(CAN2, &canTxMsg); } else { can2TransmitFlag = false; if(can2TransmitFinishCallback != 0) { can2TransmitFinishCallback(); } } } } /** * @brief This function handles CAN2 RX0 Handler. * @param None. * @return None. */ void CAN2_RX0_IRQHandler(void) { if(CAN_GetITStatus(CAN2, CAN_IT_FMP0) != RESET) { CAN_ClearITPendingBit(CAN2, CAN_IT_FMP0); CanRxMsg canRxMsg = {0}; CAN_Receive(CAN2, CAN_FIFO0, &canRxMsg); if(RingBuffer_Avail(can2RxBuffer) / sizeof(CanRxMsg) > 0) { RingBuffer_In(can2RxBuffer, &canRxMsg, sizeof(canRxMsg)); } if(can2ReceiveFinishCallback != 0) { can2ReceiveFinishCallback(); } } } #endif /* STM32F10X_CL */

main.h 文件

/**
  ******************************************************************************
  * @file    main.h
  * @author  XinLi
  * @version v1.0
  * @date    24-June-2018
  * @brief   Header file for main.c module.
  ******************************************************************************
  * @attention
  *
  * 

Copyright © 2018 XinLi

* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ****************************************************************************** */ #ifndef __MAIN_H #define __MAIN_H #ifdef __cplusplus extern "C" { #endif /* Header includes -----------------------------------------------------------*/ #include "stm32f10x.h" /* Macro definitions ---------------------------------------------------------*/ /* Type definitions ----------------------------------------------------------*/ /* Variable declarations -----------------------------------------------------*/ /* Variable definitions ------------------------------------------------------*/ /* Function declarations -----------------------------------------------------*/ /* Function definitions ------------------------------------------------------*/ #ifdef __cplusplus } #endif #endif /* __MAIN_H */

main.c 文件

/**
  ******************************************************************************
  * @file    main.c
  * @author  XinLi
  * @version v1.0
  * @date    24-June-2018
  * @brief   Main program body.
  ******************************************************************************
  * @attention
  *
  * 

Copyright © 2018 XinLi

* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ****************************************************************************** */ /* Header includes -----------------------------------------------------------*/ #include "main.h" #include "CAN.h" #ifdef _RTE_ #include "RTE_Components.h" #endif #ifdef RTE_CMSIS_RTOS2 #include "cmsis_os2.h" #endif /* Macro definitions ---------------------------------------------------------*/ /* Type definitions ----------------------------------------------------------*/ /* Variable declarations -----------------------------------------------------*/ /* Variable definitions ------------------------------------------------------*/ static CanTxMsg canTxMsg = {0}; static CanRxMsg canRxMsg = {0}; /* Function declarations -----------------------------------------------------*/ static void SystemClock_Config(void); /* Function definitions ------------------------------------------------------*/ /** * @brief Main program. * @param None. * @return None. */ int main(void) { /* Configure the system clock to 72 MHz */ SystemClock_Config(); SystemCoreClockUpdate(); /* Add your application code here */ CAN_Configure(CAN1, CAN_WorkModeLoopBack, CAN_BaudRate250K, 0xAA55, 0x55AA); #ifdef RTE_CMSIS_RTOS2 /* Initialize CMSIS-RTOS2 */ osKernelInitialize(); /* Create thread functions that start executing, Example: osThreadNew(app_main, NULL, NULL); */ /* Start thread execution */ osKernelStart(); #endif /* Infinite loop */ while(1) { canTxMsg.StdId = 0xAA55; canTxMsg.ExtId = 0x55AA; canTxMsg.IDE = CAN_ID_STD; canTxMsg.RTR = CAN_RTR_DATA; canTxMsg.DLC = 8; canTxMsg.Data[0]++; canTxMsg.Data[1]++; canTxMsg.Data[2]++; canTxMsg.Data[3]++; canTxMsg.Data[4]++; canTxMsg.Data[5]++; canTxMsg.Data[6]++; canTxMsg.Data[7]++; CAN_SetTransmitMessage(CAN1, &canTxMsg, 1); while(CAN_IsReceiveBufferEmpty(CAN1) == true); CAN_GetReceiveMessage(CAN1, &canRxMsg, 1); } } /** * @brief System Clock Configuration. * The system Clock is configured as follow : * System Clock source = PLL (HSE) * SYSCLK(Hz) = 72000000 * HCLK(Hz) = 72000000 * AHB Prescaler = 1 * APB1 Prescaler = 2 * APB2 Prescaler = 1 * HSE Frequency(Hz) = 8000000 * HSE PREDIV1 = 1 * PLLMUL = 9 * Flash Latency(WS) = 2 * @param None. * @return None. */ static void SystemClock_Config(void) { /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration */ /* RCC system reset */ RCC_DeInit(); /* Enable HSE */ RCC_HSEConfig(RCC_HSE_ON); /* Wait till HSE is ready */ ErrorStatus HSEStartUpStatus = RCC_WaitForHSEStartUp(); if(HSEStartUpStatus == SUCCESS) { /* Enable Prefetch Buffer */ FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* Flash 2 wait state */ FLASH_SetLatency(FLASH_Latency_2); /* HCLK = SYSCLK */ RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK */ RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK1 = HCLK / 2 */ RCC_PCLK1Config(RCC_HCLK_Div2); /* Configure PLLs */ #ifdef STM32F10X_CL /* PLL2 configuration: PLL2CLK = (HSE(8MHz) / 2) * 10 = 40MHz */ RCC_PREDIV2Config(RCC_PREDIV2_Div2); RCC_PLL2Config(RCC_PLL2Mul_10); /* Enable PLL2 */ RCC_PLL2Cmd(ENABLE); /* Wait till PLL2 is ready */ while(RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET); /* PLL configuration: PLLCLK = (PLL2(40MHz) / 5) * 9 = 72MHz */ RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div5); RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9); #else /* PLLCLK = HSE(8MHz) * 9 = 72MHz */ RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); #endif /* Enable PLL */ RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */ while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); /* Select PLL as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ while(RCC_GetSYSCLKSource() != 0x08); } else { /* Disable HSE */ RCC_HSEConfig(RCC_HSE_OFF); /* Enable HSI */ RCC_HSICmd(ENABLE); /* Enable Prefetch Buffer */ FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* Flash 1 wait state */ FLASH_SetLatency(FLASH_Latency_1); /* HCLK = SYSCLK */ RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK */ RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK1 = HCLK */ RCC_PCLK1Config(RCC_HCLK_Div1); /* Configure PLLs */ /* PLLCLK = HSI(8MHz) / 2 * 9 = 36MHz */ RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9); /* Enable PLL */ RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */ while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); /* Select PLL as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ while(RCC_GetSYSCLKSource() != 0x08); } } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name. * @param line: assert_param error line source number. * @return None. */ void assert_failed(uint8_t *file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */ while(1) { } } #endif

 

3,注意

CAN 消息发送缓冲区和接收缓冲区的大小,可以根据应用的需求进行修改,缓冲区使用的是堆内存,需要根据缓冲区大小和应用程序中堆内存使用情况进行配置。

你可能感兴趣的:(STM32,STM32,CAN)