전송이 완료되면 인터럽트가 발생하면서 CAN_ISR인 HAL_CAN_IRQHandler에 진입하게 됩니다. 송신이 완료되었을 때 뿐만 아니라 수신이 완료된 경우, 오류가 발생한 경우에도 HAL_CAN_IRQHandler에 진입하게 됩니다. 송신과 오류에 의한 진입의 경우에도 인터럽트 소스와 이밴트 상태를 검사하는 방법은 송신과 동일합니다. 여기서는 송신에 대해서만 자세히 알아보고 나머지는 주석처리했습니다.
void HAL_CAN_IRQHandler( CAN_HandleTypeDef *hcan )
{
/* 송신 완료에 의해 CAN_ISR 진입. */
/* CAN_IER 레지스터의 TMEIE 비트가 셋되어 있다면 */
if (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_TME))
{
/* 어떤 메일박스의 전송이 완료되었는지 검사하기 위해 CAN_TSR 레지스터의 RQCPx 비트들을 검사한다. */
if ( (__HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_0)) ||
(__HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_1)) ||
(__HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_2)) )
{
/* HAL_CAN_IRQHandler 함수 다음에 설명 */
CAN_Transmit_IT(hcan);
}
}
/* RX FIFO 0에 대한 수신 완료에 의해 CAN_ISR 진입 */
/* CAN_IER 레지스터의 FMPIE0 비트가 1로 셋되어 있고, CAN_RF0R 레지스터의 FMP 필드가 0이 아닌 경우 */
if ( (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP0)) &&
(__HAL_CAN_MSG_PENDING(hcan, CAN_FIFO0) != 0) )
{
/* 생략 */
CAN_Receive_IT(hcan, CAN_FIFO0);
}
/* RX FIFO 1에 대한 수신 완료에 의해 CAN_ISR 진입 */
/* CAN_IER 레지스터의 FMPIE0 비트가 1로 셋되어 있고, CAN_RF0R 레지스터의 FMP 필드가 0이 아닌 경우 */
if ( (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP1)) &&
(__HAL_CAN_MSG_PENDING(hcan, CAN_FIFO1) != 0) )
{
/* 생략 */
CAN_Receive_IT(hcan, CAN_FIFO1);
}
/* 참고로 CAN_ESR 레지스터에 있는 모든 오류 플래그는 직접 인터럽트 소스가 되지 못한다. CAN_MSR 레지스터의 ERRI 비트가 인터럽트 소스가 되고, 각 오류 플래그를 ERRI 비트에 연결시키는 방법을 사용해야 한다.*/
/* 수신 또는 송신 오류 카운터가 96 이상이어서 CAN_ISR 진입 */
/* CAN_IER 레지스터의 EWGIE 비트가 셋되어 있고,(CAN_ESR 레지스터의 EWGF 비트가 CAN_MSR 레지스터의 ERRI 비트와 연결되어 있다면) CAN_IER 레지스터의 ERRIE 비트가 셋되어 있고(ERRI 비트를 인터럽트 소스로 설정했다면), CAN_ESR 레지스터의 EWGF 비트가 셋된 경우. */
if ( (__HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EWG)) &&
(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EWG)) &&
(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR)) )
{
/* 핸들의 자세한 오류 내용 기입. 마지막 if 문에서 이용한다. */
hcan->ErrorCode |= HAL_CAN_ERROR_EWG;
}
/* 수신 또는 송신 오류 카운터가 96 이상이어서 CAN_ISR 진입 */
if ( (__HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EPV)) &&
(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EPV)) &&
(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR)) )
{
hcan->ErrorCode |= HAL_CAN_ERROR_EPV;
}
/* 수신 또는 송신 오류 카운터가 255 이상이어서 CAN_ISR 진입 */
if ( (__HAL_CAN_GET_FLAG(hcan, CAN_FLAG_BOF)) &&
(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_BOF)) &&
(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR)) )
{
hcan->ErrorCode |= HAL_CAN_ERROR_BOF;
}
/* CAN 컨트롤러가 프레임에서 오류를 검출하여 CAN_ISR 진입 */
/* 단, LEC는 여러 개의 오류가 검출되도 마지막에 검출된 오류만 나타낸다. */
if ( (!HAL_IS_BIT_CLR(hcan->Instance->ESR, CAN_ESR_LEC)) &&
(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_LEC)) &&
(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR)) )
{
switch (hcan->Instance->ESR & CAN_ESR_LEC)
{
case(CAN_ESR_LEC_0):
hcan->ErrorCode |= HAL_CAN_ERROR_STF;
break;
case(CAN_ESR_LEC_1):*/
hcan->ErrorCode |= HAL_CAN_ERROR_FOR;
break;
case(CAN_ESR_LEC_1 | CAN_ESR_LEC_0):
hcan->ErrorCode |= HAL_CAN_ERROR_ACK;
break;
case(CAN_ESR_LEC_2):
hcan->ErrorCode |= HAL_CAN_ERROR_BR;
break;
case(CAN_ESR_LEC_2 | CAN_ESR_LEC_0):
hcan->ErrorCode |= HAL_CAN_ERROR_BD;
break;
case(CAN_ESR_LEC_2 | CAN_ESR_LEC_1):
hcan->ErrorCode |= HAL_CAN_ERROR_CRC;
break;
default:
break;
}
/* 이미 정보는 얻었으므로 CAN_ESR 레지스터의 LEC 필드를 클리어한다. */
hcan->Instance->ESR &= ~(CAN_ESR_LEC);
}
if (hcan->ErrorCode != HAL_CAN_ERROR_NONE) /* 오류가 있다면, */
{
hcan->Instance->MSR |= CAN_MSR_ERRI; /* 1을 쓰면 클리어되는 비트이다. */
hcan->State = HAL_CAN_STATE_READY; /* 다시 전송을 시작하기 위해서 */
HAL_CAN_ErrorCallback(hcan); /* 비어 있는 함수 */
}
}
static HAL_StatusTypeDef CAN_Transmit_IT( CAN_HandleTypeDef *hcan )
{
__HAL_CAN_DISABLE_IT(hcan, CAN_IT_TME); /* CAN_IER 레지스터의 TMEIE 비트를 클리어 */
if (hcan->State == HAL_CAN_STATE_BUSY_TX)
{
/* 모든 오류에 관한 인터럽트 연결/소스를 클리어 한다. */
__HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG);
__HAL_CAN_DISABLE_IT(hcan, CAN_IT_EPV);
__HAL_CAN_DISABLE_IT(hcan, CAN_IT_BOF);
__HAL_CAN_DISABLE_IT(hcan, CAN_IT_LEC);
__HAL_CAN_DISABLE_IT(hcan, CAN_IT_ERR);
}
if (hcan->State == HAL_CAN_STATE_BUSY_TX_RX) /* 핸들의 상태가 송수신 상태라면, */
{
/* 송신은 끝났으므로 수신만 하는 상태로 바꿔준다. */
hcan->State = HAL_CAN_STATE_BUSY_RX;
}
else /* 그렇지 않다면, */
{
hcan->State = HAL_CAN_STATE_READY; /* 준비사태로 바꿔준다. */
}
HAL_CAN_TxCpltCallback(hcan); /* 비어 있다. */
return HAL_OK;
}
'CAN' 카테고리의 다른 글
6. 데이터 수신 (풀링 방식) (1) 필터와 FMI (0) | 2017.03.25 |
---|---|
5. 데이터 송신 (6) 오실로스코프로 데이터 프레임 파형 관찰 (7) 기타 의문점.. (0) | 2017.03.22 |
5. 데이터 송신 (인터럽트 방식) (3) CanTxMsgTypeDef 구조체 (4) HAL_CAN_Transmit_IT 함수 (0) | 2017.03.22 |
5. 데이터 송신 (1) 데이터 프레임 (2) 리모트 프레임 (2) | 2017.03.21 |
4. 필터설정 (6) CAN_FilterConfTypeDef 구조체와 HAL_CAN_ConfigFilter 함수 (0) | 2017.03.21 |