📄 stm8s_can.c
字号:
/**
******************************************************************************
* @file stm8s_can.c
* @brief This file contains all the functions for the CAN peripheral.
* @author STMicroelectronics - MCD Application Team
* @version V1.1.1
* @date 06/05/2009
******************************************************************************
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2009 STMicroelectronics</center></h2>
* @image html logo.bmp
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm8s_can.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define CAN_IDLIST_IDMASK_MASK ((u8) 0x55)
#define CAN_IDMASK_IDLIST_MASK ((u8) 0xAA)
#define CAN_MODE_MASK ((u8) 0x03)
#define CAN_ACKNOWLEDGE_TIMEOUT ((u16)0xFFFF)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
vu32 _Id;
vu8 _IDE;
vu8 _RTR;
vu8 _DLC;
vu8 _Data[8];
vu8 _FMI;
/* Private function prototypes -----------------------------------------------*/
static ITStatus CheckITStatus(u8 CAN_Reg, u8 It_Bit);
/* Private functions ---------------------------------------------------------*/
/**
* @addtogroup CAN_Public_Functions
* @{
*/
/**
* @brief Deinitializes the CAN peripheral registers to their default reset values.
* @par Parameters:
* None
* @retval None
*/
void CAN_DeInit(void)
{
/* Request initialisation */
CAN->MCR = CAN_MCR_INRQ;
CAN->PSR = CAN_Page_Config;
CAN_OperatingModeRequest(CAN_OperatingMode_Initialization);
CAN->Page.Config.ESR = CAN_ESR_RESET_VALUE;
CAN->Page.Config.EIER = CAN_EIER_RESET_VALUE;
CAN->Page.Config.BTR1 = CAN_BTR1_RESET_VALUE;
CAN->Page.Config.BTR2 = CAN_BTR2_RESET_VALUE;
CAN->Page.Config.FMR1 = CAN_FMR1_RESET_VALUE;
CAN->Page.Config.FMR2 = CAN_FMR2_RESET_VALUE;
CAN->Page.Config.FCR1 = CAN_FCR_RESET_VALUE;
CAN->Page.Config.FCR2 = CAN_FCR_RESET_VALUE;
CAN->Page.Config.FCR3 = CAN_FCR_RESET_VALUE;
CAN_OperatingModeRequest(CAN_OperatingMode_Normal);
CAN->PSR = CAN_Page_RxFifo;
CAN->Page.RxFIFO.MDLCR = CAN_MDLC_RESET_VALUE;
CAN->PSR = CAN_Page_TxMailBox0;
CAN->Page.TxMailbox.MDLCR = CAN_MDLC_RESET_VALUE;
CAN->PSR = CAN_Page_TxMailBox1;
CAN->Page.TxMailbox.MDLCR = CAN_MDLC_RESET_VALUE;
CAN->PSR = CAN_Page_TxMailBox2;
CAN->Page.TxMailbox.MDLCR = CAN_MDLC_RESET_VALUE;
CAN->MCR = CAN_MCR_RESET_VALUE;
CAN->MSR = (u8)(~CAN_MSR_RESET_VALUE);/* rc_w1 */
CAN->TSR = (u8)(~CAN_TSR_RESET_VALUE);/* rc_w1 */
CAN->RFR = (u8)(~CAN_RFR_RESET_VALUE);/* rc_w1 */
CAN->IER = CAN_IER_RESET_VALUE;
CAN->DGR = CAN_DGR_RESET_VALUE;
CAN->PSR = CAN_PSR_RESET_VALUE;
}
/**
* @brief Initializes the CAN peripheral according to the specified parameters.
* @param[in] CAN_MasterCtrl : Master control option, can be one or a combinaison of @ref CAN_MasterCtrl_TypeDef.
* @param[in] CAN_Mode : CAN mode , can be one of @ref CAN_Mode_TypeDef.
* @param[in] CAN_SynJumpWidth : CAN Synchronisation Jump Width , can be one of @ref CAN_SynJumpWidth_TypeDef.
* @param[in] CAN_BitSeg1 : CAN bit segment 1 , can be one of @ref CAN_BitSeg1_TypeDef.
* @param[in] CAN_BitSeg2 : CAN bit segment 2 , can be one of @ref CAN_BitSeg2_TypeDef.
* @param[in] CAN_ClockSource : CAN clock source , can be one of @ref CAN_ClockSource_TypeDef.
* @param[in] CAN_Prescaler : CAN Baud Rate Prescaler , can be a value from 0x01 to 0xFF.
* @retval Indicates if initialization is succeed. it can be one of @ref CAN_InitStatus_TypeDef enumeration.
*/
CAN_InitStatus_TypeDef CAN_Init(CAN_MasterCtrl_TypeDef CAN_MasterCtrl,
CAN_Mode_TypeDef CAN_Mode,
CAN_SynJumpWidth_TypeDef CAN_SynJumpWidth,
CAN_BitSeg1_TypeDef CAN_BitSeg1,
CAN_BitSeg2_TypeDef CAN_BitSeg2,
CAN_ClockSource_TypeDef CAN_ClockSource,
u8 CAN_Prescaler)
{
CAN_InitStatus_TypeDef InitStatus = CAN_InitStatus_Failed;
u16 timeout = CAN_ACKNOWLEDGE_TIMEOUT;
CAN_Page_TypeDef can_page = CAN_GetSelectedPage();
/* Check the parameters */
assert_param(IS_CAN_MASTERCTRL_OK(CAN_MasterCtrl));
assert_param(IS_CAN_MODE_OK(CAN_Mode));
assert_param(IS_CAN_SYNJUMPWIDTH_OK(CAN_SynJumpWidth));
assert_param(IS_CAN_BITSEG1_OK(CAN_BitSeg1));
assert_param(IS_CAN_BITSEG2_OK(CAN_BitSeg2));
assert_param(IS_CAN_CLOCKSOURCE_OK(CAN_ClockSource));
assert_param(IS_CAN_PRESCALER_OK(CAN_Prescaler));
/* Request initialisation */
CAN->MCR = CAN_MCR_INRQ;
/* Wait the acknowledge */
while ((timeout != 0)&&((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK))
{
timeout--;
}
/* Check acknowledged */
if ((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK)
{
InitStatus = CAN_InitStatus_Failed;
}
else
{
/* Set the time triggered communication mode & Set the automatic bus-off management & Set the automatic wake-up mode
& Set the no automatic retransmission & Set the receive FIFO locked mode & Set the transmit FIFO priority */
CAN->MCR |= (u8)CAN_MasterCtrl;
/* Set the bit timing register */
CAN->DGR |= (u8)CAN_Mode ;
CAN->PSR = CAN_Page_Config;
CAN->Page.Config.BTR1 = (u8)(CAN_SynJumpWidth | (CAN_Prescaler - 1));
CAN->Page.Config.BTR2 = (u8)(CAN_BitSeg1 | CAN_BitSeg2 | CAN_ClockSource);
/* Request leave initialisation */
CAN->MCR &= (u8)(~CAN_MCR_INRQ);
/* Wait the acknowledge */
timeout = 0xFFFF;
while ((timeout != 0)&&((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK))
{
timeout--;
}
/* Check acknowledged */
if ((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
{
InitStatus = CAN_InitStatus_Failed;
}
else
{
InitStatus = CAN_InitStatus_Success;
}
}
/*Restore Last Page*/
CAN_SelectPage(can_page);
/* Return the status of initialization */
return (CAN_InitStatus_TypeDef)InitStatus;
}
/**
* @brief Initializes the CAN peripheral Filter according to the specified parameters.
* @param[in] CAN_FilterNumber : CAN Filter number , can be one of @ref CAN_FilterNumber_TypeDef
* @param[in] CAN_FilterActivation : CAN Filter Activation state , can be one of @ref FunctionalState
* @param[in] CAN_FilterMode : CAN Filter Mode , can be one of @ref CAN_FilterMode_TypeDef
* @param[in] CAN_FilterScale : CAN Filter Scale , can be one of @ref CAN_FilterScale_TypeDef
* @param[in] CAN_FilterID1 : CAN Filter ID 1 , can be a value from 0x00 to 0xFF
* @param[in] CAN_FilterID2 : CAN Filter ID 2 , can be a value from 0x00 to 0xFF
* @param[in] CAN_FilterID3 : CAN Filter ID 3 , can be a value from 0x00 to 0xFF
* @param[in] CAN_FilterID4 : CAN Filter ID 4 , can be a value from 0x00 to 0xFF
* @param[in] CAN_FilterIDMask1 : CAN Filter ID 1/ Mask 1 , can be a value from 0x00 to 0xFF depending of CAN_FilterMode parameter
* @param[in] CAN_FilterIDMask2 : CAN Filter ID 2/ Mask 2 , can be a value from 0x00 to 0xFF depending of CAN_FilterMode parameter
* @param[in] CAN_FilterIDMask3 : CAN Filter ID 3/ Mask 3 , can be a value from 0x00 to 0xFF depending of CAN_FilterMode parameter
* @param[in] CAN_FilterIDMask4 : CAN Filter ID 4/ Mask 4 , can be a value from 0x00 to 0xFF depending of CAN_FilterMode parameter
* @retval None
*/
void CAN_FilterInit(CAN_FilterNumber_TypeDef CAN_FilterNumber,
FunctionalState CAN_FilterActivation,
CAN_FilterMode_TypeDef CAN_FilterMode,
CAN_FilterScale_TypeDef CAN_FilterScale,
u8 CAN_FilterID1,
u8 CAN_FilterID2,
u8 CAN_FilterID3,
u8 CAN_FilterID4,
u8 CAN_FilterIDMask1,
u8 CAN_FilterIDMask2,
u8 CAN_FilterIDMask3,
u8 CAN_FilterIDMask4)
{
u8 fact = 0;
u8 fsc = 0;
u8 fmhl = 0;
CAN_Page_TypeDef can_page_filter = CAN_Page_Filter01;
CAN_Page_TypeDef can_page = CAN_GetSelectedPage();
/* Check the parameters */
assert_param(IS_CAN_FILTER_NUMBER_OK(CAN_FilterNumber));
assert_param(IS_FUNCTIONALSTATE_OK(CAN_FilterActivation));
assert_param(IS_CAN_FILTER_MODE_OK(CAN_FilterMode));
assert_param(IS_CAN_FILTER_SCALE_OK(CAN_FilterScale));
if (CAN_FilterNumber == CAN_FilterNumber_0)
{
fact = 0x01;
fsc = 0x00;
fmhl = 0x03;
can_page_filter = CAN_Page_Filter01;
}
else if (CAN_FilterNumber == CAN_FilterNumber_1)
{
fact = 0x10;
fsc = 0x04;
fmhl = 0x0C;
can_page_filter = CAN_Page_Filter01;
}
else if (CAN_FilterNumber == CAN_FilterNumber_2)
{
fact = 0x01;
fsc = 0x00;
fmhl = 0x30;
can_page_filter = CAN_Page_Filter23;
}
else if (CAN_FilterNumber == CAN_FilterNumber_3)
{
fact = 0x10;
fsc = 0x04;
fmhl = 0xC0;
can_page_filter = CAN_Page_Filter23;
}
else if (CAN_FilterNumber == CAN_FilterNumber_4)
{
fact = 0x01;
fsc = 0x00;
fmhl = 0x03;
can_page_filter = CAN_Page_Filter45;
}
else /*if (CAN_FilterNumber == CAN_FilterNumber_5)*/
{
fact = 0x10;
fsc = 0x04;
fmhl = 0x0C;
can_page_filter = CAN_Page_Filter45;
}
CAN_OperatingModeRequest(CAN_OperatingMode_Initialization);
CAN->PSR = CAN_Page_Config;
/*---------------------------------------------------------*/
/*Configuration of Filter Scale */
/*---------------------------------------------------------*/
if (can_page_filter == CAN_Page_Filter01) /* FCR1 */
{
/* Filter Deactivation & Reset the Filter Scale */
CAN->Page.Config.FCR1 &= (u8)~( fact | ((CAN_FCR1_FSC00|CAN_FCR1_FSC01) << fsc ));
/* Set the new Filter Scale */
CAN->Page.Config.FCR1 |= (u8)(CAN_FilterScale << fsc);
}
else if (can_page_filter == CAN_Page_Filter23) /* FCR2*/
{
/* Filter Deactivation & Reset the Filter Scale */
CAN->Page.Config.FCR2 &= (u8)~( fact | ((CAN_FCR1_FSC00|CAN_FCR1_FSC01) << fsc ));
/* Set the new Filter Scale */
CAN->Page.Config.FCR2 |= (u8)(CAN_FilterScale << fsc);
}
else /*if(can_page_filter == CAN_Page_Filter45)*/ /* FCR3*/
{
/* Filter Deactivation & Reset the Filter Scale */
CAN->Page.Config.FCR3 &= (u8)~( fact | ((CAN_FCR1_FSC00|CAN_FCR1_FSC01) << fsc ));
/* Set the new Filter Scale */
CAN->Page.Config.FCR3 |= (u8)(CAN_FilterScale << fsc);
}
/*---------------------------------------------------------*/
/*Configuration of Filter Mode */
/*---------------------------------------------------------*/
if (can_page_filter != CAN_Page_Filter45) /* FMR1*/
{
/* Filter Mode */
if (CAN_FilterMode == CAN_FilterMode_IdMask)
{
/*Id/Mask mode for the filter*/
CAN->Page.Config.FMR1 &= (u8)~(fmhl);
}
else if ( CAN_FilterMode == CAN_FilterMode_IdList)
{
/*Identifier list mode for the filter*/
CAN->Page.Config.FMR1 |= (u8)(fmhl);
}
else if ( CAN_FilterMode == CAN_FilterMode_IdList_IdMask)
{
/*Identifier list mode is first for the filter*/
CAN->Page.Config.FMR1 |= (u8)(fmhl & CAN_IDLIST_IDMASK_MASK);
}
else /* ( CAN_FilterMode == CAN_FilterMode_IdMask_IdList)*/
{
/*Id Mask mode is first for the filter*/
CAN->Page.Config.FMR1 |= (u8)(fmhl & CAN_IDMASK_IDLIST_MASK);
}
}
else /* FMR2 */
{
/* Filter Mode */
if (CAN_FilterMode == CAN_FilterMode_IdMask)
{
/*Id/Mask mode for the filter*/
CAN->Page.Config.FMR2 &= (u8)~(fmhl);
}
else if ( CAN_FilterMode == CAN_FilterMode_IdList)
{
/*Identifier list mode for the filter*/
CAN->Page.Config.FMR2 |= (u8)(fmhl);
}
else if ( CAN_FilterMode == CAN_FilterMode_IdList_IdMask)
{
/*Identifier list mode is first for the filter*/
CAN->Page.Config.FMR2 |= (u8)(fmhl & CAN_IDLIST_IDMASK_MASK);
}
else /* ( CAN_FilterMode == CAN_FilterMode_IdMask_IdList)*/
{
/*Id Mask mode is first for the filter*/
CAN->Page.Config.FMR2 |= (u8)(fmhl & CAN_IDMASK_IDLIST_MASK);
}
}
/*---------------------------------------------------------*/
/*Configuration of Filter IDs */
/*---------------------------------------------------------*/
CAN->PSR = (u8)can_page_filter;
if (fsc != 0)
{
/* Filter Scale */
if (CAN_FilterScale == CAN_FilterScale_8Bit)
{
CAN->Page.Filter.FR09 = CAN_FilterID1;
CAN->Page.Filter.FR10 = CAN_FilterIDMask1;
CAN->Page.Filter.FR11 = CAN_FilterID2;
CAN->Page.Filter.FR12 = CAN_FilterIDMask2;
CAN->Page.Filter.FR13 = CAN_FilterID3;
CAN->Page.Filter.FR14 = CAN_FilterIDMask3;
CAN->Page.Filter.FR15 = CAN_FilterID4;
CAN->Page.Filter.FR16 = CAN_FilterIDMask4;
}
else if (CAN_FilterScale == CAN_FilterScale_16_8Bit)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -