📄 stm8s_can.c
字号:
/*Enable the TTCM mode */
CAN->MCR |= CAN_MCR_TTCM;
/*Set TGT bits setting in Tx and FIFO pages*/
CAN->PSR = CAN_Page_TxMailBox0;
CAN->Page.TxMailbox.MDLCR |= CAN_MDLCR_TGT;
CAN->PSR = CAN_Page_TxMailBox1;
CAN->Page.TxMailbox.MDLCR |= CAN_MDLCR_TGT;
CAN->PSR = CAN_Page_TxMailBox2;
CAN->Page.TxMailbox.MDLCR |= CAN_MDLCR_TGT;
CAN->PSR = CAN_Page_RxFifo;
CAN->Page.RxFIFO.MDLCR |= CAN_MDLCR_TGT;
}
else
{
/*Disable the TTCM mode */
CAN->MCR &= ((u8)~CAN_MCR_TTCM);
/*Reset TGT bits setting in Tx and FIFO pages*/
CAN->PSR = CAN_Page_TxMailBox0;
CAN->Page.TxMailbox.MDLCR &= ((u8)~CAN_MDLCR_TGT);
CAN->PSR = CAN_Page_TxMailBox1;
CAN->Page.TxMailbox.MDLCR &= ((u8)~CAN_MDLCR_TGT);
CAN->PSR = CAN_Page_TxMailBox2;
CAN->Page.TxMailbox.MDLCR &= ((u8)~CAN_MDLCR_TGT);
CAN->PSR = CAN_Page_RxFifo;
CAN->Page.RxFIFO.MDLCR &= ((u8)~CAN_MDLCR_TGT);
}
/*Restore Last Page*/
CAN_SelectPage(can_page);
}
/**
* @brief Initiates the transmission of a message.
* @param[in] CAN_Id the ID number of the message, its size depends on @ref CAN_IDE value.
* @param[in] CAN_IDE the ID type of the message, this parameter can be one of the @ref CAN_Id_TypeDef enumeration.
* @param[in] CAN_RTR the message type, this parameter can be one of the @ref CAN_RTR_TypeDef enumeration.
* @param[in] CAN_DLC the number of data in the message type, this parameter can be a value between 0 to 7.
* @param[in] CAN_Data pointer to a the @ref u8 table which contains data to sent.
* @retval Transmit Status, this returned value can be one of the @ref CAN_TxStatus_TypeDef enumeration.
* @par Required preconditions:
* None
* @par Called functions:
* None
*/
CAN_TxStatus_TypeDef CAN_Transmit(u32 CAN_Id,
CAN_Id_TypeDef CAN_IDE,
CAN_RTR_TypeDef CAN_RTR,
u8 CAN_DLC,
u8 *CAN_Data)
{
CAN_TxStatus_TypeDef CAN_TxStatus = CAN_TxStatus_NoMailBox;
u8 count =0;
CAN_Page_TypeDef can_page = CAN_GetSelectedPage();
/* Check the parameters */
assert_param(IS_CAN_IDTYPE_OK(CAN_IDE));
if (CAN_IDE != CAN_Id_Standard)
{
assert_param(IS_CAN_EXTID_OK(CAN_Id));
}
else
{
assert_param(IS_CAN_STDID_OK(CAN_Id));
}
assert_param(IS_CAN_RTR_OK(CAN_RTR));
assert_param(IS_CAN_DLC_OK(CAN_DLC));
/* Select one empty transmit mailbox */
if ((CAN->TPR & CAN_TPR_TME0) == CAN_TPR_TME0)
{
CAN_TxStatus = CAN_TxStatus_MailBox0Ok;
}
else if ((CAN->TPR & CAN_TPR_TME1) == CAN_TPR_TME1)
{
CAN_TxStatus = CAN_TxStatus_MailBox1Ok;
}
else if ((CAN->TPR & CAN_TPR_TME2) == CAN_TPR_TME2)
{
CAN_TxStatus = CAN_TxStatus_MailBox2Ok;
}
else
{
CAN_TxStatus = CAN_TxStatus_NoMailBox;
}
if (CAN_TxStatus != CAN_TxStatus_NoMailBox)
{
CAN->PSR = (CAN_TxStatus);
/* Set up the Id */
if (CAN_IDE != CAN_Id_Standard)
{
CAN_Id &= (u32)CAN_EXTID_SIZE;
CAN->Page.TxMailbox.MIDR4 = (u8)(CAN_Id);
CAN_Id = CAN_Id>>8;
CAN->Page.TxMailbox.MIDR3 = (u8)(CAN_Id);
CAN_Id = CAN_Id>>8;
CAN->Page.TxMailbox.MIDR2 = (u8)(CAN_Id);
CAN_Id = CAN_Id>>8;
CAN->Page.TxMailbox.MIDR1 |= (u8)(CAN_Id |CAN_IDE | CAN_RTR);
}
else
{
CAN_Id &= (u16)CAN_STDID_SIZE;
CAN->Page.TxMailbox.MIDR1 = (u8)((CAN_Id>>6) | (CAN_RTR)) ;
CAN->Page.TxMailbox.MIDR2 = (u8)(CAN_Id<<2);
}
/* Set up the DLC */
/*clear old DLC value*/
CAN->Page.TxMailbox.MDLCR &= (u8)0xF0;
/*set the new value of DLC*/
CAN->Page.TxMailbox.MDLCR |= CAN_DLC;
/* Set up the data field */
for (count=0;count<CAN_DLC;count++)
{
CAN->Page.TxMailbox.MDAR[count] = CAN_Data[count];
}
/* Request transmission */
CAN->Page.TxMailbox.MCSR |= CAN_MCSR_TXRQ;
}
/*Restore Last Page*/
CAN_SelectPage(can_page);
return (CAN_TxStatus_TypeDef)CAN_TxStatus;
}
/**
* @brief Checks the transmission of a message.
* @param[in] TransmitMailbox: the number of the mailbox that is used for transmission, can be on of @ref CAN_TransmitMailBox_TypeDef.
* @retval CAN_TxStatus_Ok if the CAN driver transmits the message, CAN_TxStatus_Failed in an other case.
* @par Required preconditions:
* None
* @par Called functions:
* None
*/
CAN_TxStatus_TypeDef CAN_TransmitStatus(CAN_TransmitMailBox_TypeDef CAN_TransmitMailbox)
{
/* RQCP, TXOK and TME bits */
CAN_TxStatus_TypeDef tstate = CAN_TxStatus_Failed;
u8 tmpstate=0;
/* Check the parameters */
assert_param(IS_CAN_TRANSMITMAILBOX_OK(CAN_TransmitMailbox));
switch (CAN_TransmitMailbox)
{
case (CAN_TransmitMailBox_0): tmpstate = (u8)((CAN->TSR & (CAN_TSR_RQCP0|CAN_TSR_TXOK0)));
tmpstate |= (u8)((CAN->TPR & CAN_TPR_TME0));
break;
case (CAN_TransmitMailBox_1): tmpstate = (u8)((CAN->TSR & (CAN_TSR_RQCP1|CAN_TSR_TXOK1))>>1);
tmpstate |= (u8)((CAN->TPR & CAN_TPR_TME1) >> 1);
break;
case (CAN_TransmitMailBox_2): tmpstate = (u8)((CAN->TSR & (CAN_TSR_RQCP2|CAN_TSR_TXOK2))>>2);
tmpstate |= (u8)((CAN->TPR & CAN_TPR_TME2) >> 2);
break;
default: tstate = CAN_TxStatus_Failed;
break;
}
switch (tmpstate)
{
/*transmit pending */
case (0x00): tstate = CAN_TxStatus_Pending;
break;
/* transmit failed */
case (0x05): tstate = CAN_TxStatus_Failed;
break;
/* transmit succedeed */
case (0x15): tstate = CAN_TxStatus_Ok;
break;
/* transmit mailbox is empty : no activity on this TX mail box */
case (0x04): tstate = CAN_TxStatus_MailBoxEmpty;
break;
default: tstate = CAN_TxStatus_Failed;
break;
}
return (CAN_TxStatus_TypeDef)tstate;
}
/**
* @brief Cancels a transmit request.
* @param[in] TransmitMailbox : the Transmission mailbox, can be one of CAN_TransmitMailBox_TypeDef
* @retval void None
* @par Required preconditions:
* None
* @par Called functions:
* None
*/
void CAN_CancelTransmit(CAN_TransmitMailBox_TypeDef CAN_TransmitMailbox)
{
CAN_Page_TypeDef can_page = CAN_GetSelectedPage();
/* Check the parameters */
assert_param(IS_CAN_TRANSMITMAILBOX_OK(CAN_TransmitMailbox));
/*switch to the specific page */
CAN->PSR = CAN_TransmitMailbox;
/* abort transmission */
CAN->Page.TxMailbox.MCSR |= CAN_MCSR_ABRQ;
/*Restore Last Page*/
CAN_SelectPage(can_page);
}
/**
* @brief Releases the CAN FIFO.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
* @par Called functions:
* None
*/
void CAN_FIFORelease(void)
{
/* Release FIFO*/
CAN->RFR = CAN_RFR_RFOM; /*rc-w1*/
}
/**
* @brief Returns the number of pending messages.
* @param void None
* @retval Number of pending messages.
* @par Required preconditions:
* None
* @par Called functions:
* None
*/
CAN_NbrPendingMessage_TypeDef CAN_MessagePending(void)
{
CAN_NbrPendingMessage_TypeDef msgpending = CAN_NbrPendingMessage_0;
msgpending = (u8)(CAN->RFR & CAN_RFR_FMP01);
return (CAN_NbrPendingMessage_TypeDef)msgpending;
}
/**
* @brief Receives a message which contains CAN Id, IDE, RTR
* DLC, datas and FMI number.
* In order to get these data, use CAN_GetReceivedId(), CAN_GetReceivedIDE(), CAN_GetReceivedRTR(),
* CAN_GetReceivedDLC(), CAN_GetReceivedFMI() and CAN_GetReceivedData() functions.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
* @par Called functions:
* None
*/
void CAN_Receive(void)
{
u8 count = 0;
CAN_Page_TypeDef can_page = CAN_GetSelectedPage();
/* select Fifo page*/
CAN->PSR = CAN_Page_RxFifo;
/* Get the Id */
_IDE = (u8)(CAN->Page.RxFIFO.MIDR1 & CAN_Id_Extended);
if (_IDE != CAN_Id_Standard)
{
_Id = (u32)CAN_EXTID_SIZE & ((CAN->Page.RxFIFO.MIDR4) | ((u32)((u32)CAN->Page.RxFIFO.MIDR3) << 8) | ((u32)((u32)CAN->Page.RxFIFO.MIDR2) << 16) | ((u32)((u32)CAN->Page.RxFIFO.MIDR1 & 0x1F) << 24) );
}
else
{
_Id = (u16)CAN_STDID_SIZE & ((u16)((u16)(CAN->Page.RxFIFO.MIDR1 & 0x1F) << 6) | ((CAN->Page.RxFIFO.MIDR2 >> 2)&0x3F) );
}
_RTR = (u8)(0x20 & CAN->Page.RxFIFO.MIDR1);
/* Get the DLC */
_DLC = (u8)(CAN->Page.RxFIFO.MDLCR);
/* Get the FMI */
_FMI = CAN->Page.RxFIFO.MFMI;
/* Get the data field */
for (count=0;count<_DLC;count++)
{
_Data[count] = CAN->Page.RxFIFO.MDAR[count];
}
/* Release the FIFO */
CAN_FIFORelease();
/*Restore Last Page*/
CAN_SelectPage(can_page);
}
/**
* @brief Gets the CAN Id of the received message.
* @par Parameters:
* None
* @retval the received CAN message Id.
* @par Required preconditions:
* This function is used to get data loaded by CAN_Receive function.
* Before using this function, CAN_Receive function must be called.
* @par Called functions:
* None
*/
u32 CAN_GetReceivedId(void)
{
return (_Id);
}
/**
* @brief Gets the CAN IDE of the received message.
* @par Parameters:
* None
* @retval the received CAN message IDE.
* @par Required preconditions:
* This function is used to get data loaded by CAN_Receive function.
* Before using this function, CAN_Receive function must be called.
* @par Called functions:
* None
*/
CAN_Id_TypeDef CAN_GetReceivedIDE(void)
{
return (_IDE);
}
/**
* @brief Gets the CAN RTR of the received message.
* @par Parameters:
* None
* @retval the received CAN message RTR.
* @par Required preconditions:
* This function is used to get data loaded by CAN_Receive function.
* Before using this function, CAN_Receive function must be called.
* @par Called functions:
* None
*/
CAN_RTR_TypeDef CAN_GetReceivedRTR(void)
{
return (_RTR);
}
/**
* @brief Gets the CAN DLC of the received message.
* @par Parameters:
* None
* @retval the received CAN message DLC.
* @par Required preconditions:
* This function is used to get data loaded by CAN_Receive function.
* Before using this function, CAN_Receive function must be called.
* @par Called functions:
* None
*/
u8 CAN_GetReceivedDLC(void)
{
return (_DLC);
}
/**
* @brief Gets the CAN Data of the received message.
* @param[in] CAN_DataIndexe : number of the received Data, it can
* be an integer between 0 to 7.
* @retval the received CAN message ith Data.
* @par Required preconditions:
* This function is used to get data loaded by CAN_Receive function.
* Before using this function, CAN_Receive function must be called.
* @par Called functions:
* None
*/
u8 CAN_GetReceivedData(u8 CAN_DataIndex)
{
assert_param(IS_CAN_DLC_OK(CAN_DataIndex));
return (_Data[CAN_DataIndex]);
}
/**
* @brief Gets the CAN FMI of the received message.
* @par Parameters:
* None
* @retval the received CAN message FMI.
* @par Required preconditions:
* This function is used to get data loaded by CAN_Receive function.
* Before using this function, CAN_Receive function must be called.
* @par Called functions:
* None
*/
u8 CAN_GetReceivedFMI(void)
{
return (_FMI);
}
/**
* @brief Returns the Received time stamp.
* @par Parameters:
* None
* @retval u16 the received time stamp.
* @par Required preconditions:
* None
* @par Called functions:
* None
*/
u16 CAN_GetMessageTimeStamp(void)
{
u16 time;
CAN_Page_TypeDef can_page = CAN_GetSelectedPage();
/*switch to the specific page */
CAN->PSR = CAN_Page_RxFifo;
/* Get the Received Time stamp */
time = CAN->Page.RxFIFO.MTSRL;
time |= (u16)(((u16)CAN->Page.RxFIFO.MTSRH)<<8);
/*Restore Last Page*/
CAN_SelectPage(can_page);
return (u16)(time);
}
/**
* @brief Enters the Sleep low power mode.
* @par Parameters:
* None
* @retval CAN_Sleep_Ok if sleep entered, CAN_Sleep_Failed in an other case.
* @par Required preconditions:
* None
* @par Called functions:
* None
*/
CAN_Sleep_TypeDef CAN_Sleep(void)
{
CAN_Sleep_TypeDef sleepstatus = CAN_Sleep_Failed;
/* Request Sleep mode */
CAN->MCR = (u8)(((CAN->MCR) & (u8)(~CAN_MCR_INRQ)) | CAN_MCR_SLEEP);
/* Sleep mode status */
if ((CAN->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) == CAN_MSR_SLAK)
{
/* Sleep mode not entered */
sleepstatus = CAN_Sleep_Ok;
}
/* At this step, sleep mode status */
return (CAN_Sleep_TypeDef) sleepstatus;
}
/**
* @brief Wakes the CAN up.
* @par Parameters:
* None
* @retval CAN_WakeUp_Ok if sleep mode left, CAN_WakeUp_Failed in an other case.
* @par Required preconditions:
* None
* @par Called functions:
* None
*/
CAN_WakeUp_TypeDef CAN_WakeUp(void)
{
CAN_WakeUp_TypeDef wakeupstatus = CAN_WakeUp_Failed;
/* Wake up request */
CAN->MCR &= (u8)(~CAN_MCR_SLEEP);
/* Sleep mode status */
if ((CAN->MSR & CAN_MSR_SLAK) != CAN_MSR_SLAK)
{
/* Sleep mode exited */
wakeupstatus = CAN_WakeUp_Ok;
}
/* At this step, sleep mode status */
return (CAN_WakeUp_TypeDef)wakeupstatus;
}
/**
* @brief Select the CAN clock input.
* @param[in] CAN_ClockSource : CAN clock input, can be one of @ref CAN_ClockSource_TypeDef.
* @retval void None
* @par Required preconditions:
* None
* @par Called functions:
* None
*/
void CAN_SelectClock(CAN_ClockSource_TypeDef CAN_ClockSource)
{
u16 timeout =0;
CAN_Page_TypeDef can_page = CAN_GetSelectedPage();
/* Check the parameters */
assert_param(IS_CAN_CLOCKSOURCE_OK(CAN_ClockSource));
/* Request initialisation */
CAN->MCR |= (CAN_MCR_INRQ & ((u8)(~CAN_MCR_SLEEP)));
CAN->PSR = CAN_Page_Config;
if(CAN_ClockSource != CAN_ClockSource_Internal)
{
CAN->Page.Config.BTR2 |= (u8)CAN_BTR2_CLKS;
}
else
{
CAN->Page.Config.BTR2 &= (u8)(~CAN_BTR2_CLKS);
}
/* Request leave initialisation */
CAN->MCR &= (u8)(~CAN_MCR_INRQ);
/* Wait the acknowledge */
while ((timeout != 0)&&((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK))
{
timeout--;
}
/*Restore Last Page*/
CAN_SelectPage(can_page);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -