(2) CanRxMsgTypeDef 구조체
CanTxMsgTypeDef 구조체와 비슷한 기능을 합니다. RX 메일박스 레지스터들과 대응되며 RX 메일박스에 있는 가장 최근에 수신된 CAN 프레임에 대한 정보를 임시 저장하는 구조체입니다. CAN_HandleTypeDef 구조체는 CanTxMsgTypeDef형 포인터 변수만 가지고 있기 때문에 CanTxMsgTypeDef 구조체와 마찬가지로 사용자가 CanRxMsgTypeDef형의 변수를 만들어서 CAN_HandleTypeDef형 핸들에 직접 연결시켜주어야 합니다. RX 메일 박스에서 가져온 내용을 임시 저장하는 변수이기 때문에 각 맴버 변수들은 RX 메일박스의 필드들과 거의 100% 대응됩니다.
(3) HAL_CAN_Receive 함수
HAL_StatusTypeDef HAL_CAN_Receive( CAN_HandleTypeDef *hcan, uint8_t FIFONumber, uint32_t Timeout )
{
uint32_t tickstart = 0;
__HAL_LOCK(hcan); /* 핸들을 잠근다. */
if (hcan->State == HAL_CAN_STATE_BUSY_TX) /* 핸들이 송신 상태였다면, */
{
hcan->State = HAL_CAN_STATE_BUSY_TX_RX; /* 핸들을 송수신 상태로 바꾼다. */
}
else /* 핸들이 송신 상태가 아니라면, */
{
hcan->State = HAL_CAN_STATE_BUSY_RX; /* 핸들을 송신 상태로 바꾼다. */
}
tickstart = HAL_GetTick(); /* 현재 SysTick의 틱 값을 가져온다. 다음에 나오는 while문의 타임아웃을 위한 기준 틱이다. */
/* CAN_RFxR 레지스터의 FMP 필드가 0인동안 반복하지만, 타임아웃 */
while (__HAL_CAN_MSG_PENDING(hcan, FIFONumber) == 0U)
{
/* 입력 변수의 Timeout 값이 HAL_MAX_DELAY(0xFFFFFFFF)가 아니라면, HAL_MAX_DELAY라면 무한정 기다린다. */
if (Timeout != HAL_MAX_DELAY)
{
/* while문 진입 후 SysTick의 틱 값을 다시 얻어와 tickstart 값을 빼서 경과한 시간을 계산한다. 이때 경과시간이 Timeout보다 크면 탈출한다. */
if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
{
/* 핸들을 풀어주고, 타임아웃 상태로 만든 뒤 탈출. */
hcan->State = HAL_CAN_STATE_TIMEOUT;
__HAL_UNLOCK(hcan);
return HAL_TIMEOUT;
}
}
}
/* while문을 탈출했다는 것은 메시지가 수신되었다는 의미이다. RX 메일박스에서 메시지 임시 저장용도로 사용되는 CanTxMsgTypeDef형 변수로 데이터를 복사한다.*/
/* CAN_RIxR 레지스터에서 비트2만 남기고 모두 지우고, IDE 맴버 변수에 복사한다. */
hcan->pRxMsg->IDE = (uint8_t)0x04U & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
if (hcan->pRxMsg->IDE == CAN_ID_STD) /* 표준 식별자를 사용한 프레임이라면, */
{
/* CAN_RIxR 레지스터에서 하위 11비트만 남기고 모두 지우고, StdId 맴버 변수에 복사한다. */
hcan->pRxMsg->StdId = 0x000007FFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21U);
}
else /* 확장 식별자를 사용한 프레임이라면, */
{
/* CAN_RIxR 레지스터에서 하위 29비트만 남기고 모두 지우고, StdId 맴버 변수에 복사한다. */
hcan->pRxMsg->ExtId = 0x1FFFFFFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3U);
}
/* CAN_RIxR 레지스터에서 비트2만 남기고 모두 지우고, RTR 맴버 변수에 복사한다. */
hcan->pRxMsg->RTR = (uint8_t)0x02U & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
/* CAN_RDTxR 레지스터에서 하위 4비트만 남기고 모두 지우고, DLC맴버 변수에 복사한다. */
hcan->pRxMsg->DLC = (uint8_t)0x0FU & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR;
/* CAN_RDTxR 레지스터에서 비트8부터 비트15까지의 값을 FIM 맴버 변수에 복사한다. */
hcan->pRxMsg->FMI = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8U);
/* CAN_RDL/HR 레지스터에서 데이터 값을 Data 맴버 변수에 복사한다.*/
hcan->pRxMsg->Data[0] = (uint8_t)0xFFU & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR;
hcan->pRxMsg->Data[1] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8U);
hcan->pRxMsg->Data[2] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16U);
hcan->pRxMsg->Data[3] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24U);
hcan->pRxMsg->Data[4] = (uint8_t)0xFFU & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR;
hcan->pRxMsg->Data[5] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8U);
hcan->pRxMsg->Data[6] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16U);
hcan->pRxMsg->Data[7] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24U);
/* RX FIFO를 풀어준다. 릴리즈(release) 해 준다. */
if (FIFONumber == CAN_FIFO0) /* RX FIFO 0을 선택했다면, */
{
/* CAN_RF0R 레지스터에서 RFOM0 비트에 1을 쓴다. */
__HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0);
}
else /* RX FIFO 1을 선택했다면, */
{
/* CAN_RF1R 레지스터에서 RFOM1 비트에 1을 쓴다. */
__HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1);
}
if (hcan->State == HAL_CAN_STATE_BUSY_TX_RX) /* 현재 핸들의 상태가 송수신 상태라면, */
{
/* 수신은 완료했으므로 다시 송신 상태로 바꿔준다.*/
hcan->State = HAL_CAN_STATE_BUSY_TX;
}
else /* 현재 핸들의 상태가 송수신 상태가 아니라면, */
{
hcan->State = HAL_CAN_STATE_READY; /* 준비 상태로 바꿔준다. */
}
__HAL_UNLOCK(hcan); /* 핸들을 풀어준다. */
return HAL_OK;
}
'CAN' 카테고리의 다른 글
| 8. HAL 드라이버 수정/추가 (1) 인터럽트가 2번 걸리는 문제 (0) | 2017.03.25 |
|---|---|
| 7. 오류 검출과 오류 상태 (0) | 2017.03.25 |
| 6. 데이터 수신 (풀링 방식) (1) 필터와 FMI (0) | 2017.03.25 |
| 5. 데이터 송신 (6) 오실로스코프로 데이터 프레임 파형 관찰 (7) 기타 의문점.. (0) | 2017.03.22 |
| 5. 데이터 송신 (인터럽트 방식) (5) HAL_CAN_IRQHandler와 CAN_Transmit_IT 함수 (0) | 2017.03.22 |