STM32 CAN

DongHee Lim·2022년 3월 27일
0

STM32

목록 보기
1/11

[CAN 통신 - CANable 사용기]

[CAN통신 Youtube강의 링크]

사용 보드 : F429ZI

프로그램 : CubeIDE

1. CAN

Controller Area Network

2개 선(CAN_H, CAN_L) 으로 여러 대 장치와 통신 가능

안정적인 에러 처리

차동신호 -> GND 불필요, 외부 노이즈에 강함(noise tollerance)
(기존 GND 모터제어할 때 모터속도에 따라 전압 레벨이 불안정해짐 - 통제힘듬)

Twisted Pair Cable 권장 -> 장거리

CAN Transceiver 필요(전기적 레벨이 다름)

보드와 Tx-Tx, Rx-Rx 끼리 연결

양 끝에 종단 저항 120Ω을 달아줘야함 (통신선의 임피던스 일치)

비동기식 멀티 마스터 방식으로 통신 (동시에 모든 노드가 데이터 수신 가능)

데이터의 아이디(메세지 구분)가 있고 버스에 아이디 필터가 있음

Std ID : 11bit (CAN 2.0A)

Ext ID : 29bit (CAN 2.0B)

Filter_ID_Mask 모드

Filter_ID_List 모드

통신 속도(타임퀀텀) : 1 bit를 보내는데 걸리는 시간 (CAN 2.0B 최대 1Mbps)

선로의 길이가 길어지면 통신속도를 낮춰야함 (예- 500Kbps)

한 프레임 당 8 Byte까지 데이터 송신 가능 -> 인터럽트 CPU 부담 감소

2. 용어

DLC : Data Length Code 데이터의 길이를 표시

CRC : Cyclic Redundancy Check (순환 중복 검사) 오류 체크 기능

ACK : Acknowledge 응답

EOF : End Of Frame 통신 종료

Remote Frame : 데이터를 요청할 때 사용(ID : 내가 원하는 메세지의 아이디)

3. 통신 속도

APB1 클럭/prescaler => 시간 -> 1 타임 퀀텀 [ Time Quantum(Quanta) ]

SYNC_SEG -> 1 타임 퀀텀

BIT SEGMENT 1 -> 1~16 타임 퀀텀

BIT SEGMENT 2 -> 1~8 타임 퀀텀

SAMPLE POINT는 전체 비트 타임의 75% 정도로 해줘야함(70~80%)

예) 500kbps -> 초당 500k bit -> 1bit 당 2us


APB1 = 45Mhz


Prescaler = 9


9/45Mhz = 0.2 us


1bit에 0.2us * 10개 = 2us, 10개의 타임 퀀텀


SYNC_SEG + BS1 + BS2 = 10


SAMPLE POINT => (SYNC_SEG + BS1)/10 = 0.75 (75%)

BS1 : 6 개 타임퀀텀 (2안 : 7개)
BS2 : 3 개 타임퀀텀 (2안 : 2개)

4. CAN Filter 설정

  • Filter ID List 모드

설정한 Filter ID와 일치하는 ID의 메세지만 수신

  • Filter ID Mask 모드

Filter Mask ID 와 Filter ID

Filter Mask ID 의 bit 1 이면 -> Filter ID 와 메세지 ID 반드시 일치

Filter Mask ID 의 bit 0 이면 -> 상관없이 다 받아들임

& 연산 안됨

Mask ID가 1인 부분의 Filter ID 값을 동일하게 가져온다.

5. Set up

Time Triggered Communication : 데이터 8 byte 중 7, 8번에 시간 정보를 추가

Automatic Bus-Off Management : 에러를 내는 장치 차단

수신 데이터 저장 FIFO 2개가 있음

RX0, RX1 Interrupt

CAN1 RX0 interrupts 사용 할 예정

Generate Code를 한다.

6. Transmit 송신

can.c에 변수 추가

다음 코드 추가

CAN_FilterTypeDef canFilter1;
CAN_RxHeaderTypeDef canRxHeader;
CAN_TxHeaderTypeDef canTxHeader;
uint8_t can1Rx0Data[8];
uint32_t TxMailBox;
uint8_t can1Tx0Data[8];

canRxHeader :수신받은 데이터의 헤더 정보 저장

Transmit
canTxHeader 부분에는
ID
RTR(Remote Transmission Request)
IDE(IDentifier Extention)
DLC(Data Length Code) : 데이터 길이
정보가 들어있다.

RTR
1 이면 Remote Frame : 데이터 요청
0 이면 Data Frame : 데이터 송신

IDE
1 이면 29 bit Extended ID
0 이면 11 bit Standartd ID

Time Triggered Communication -> Disable 했기 때문에 TransmitGlobalTime는 사용 X

can.h

아래와 같이 매크로가 되어 있기 때문에 16 진법으로 작성 안해도 된다.

7. Receive 수신

수신할 때는 Filter 를 설정하여 받을 데이터를 정한다.

Driver -> STM32F4xx_HAL_Driver -> Inc -> stm32f4xx_hal_can.h 에
CAN_FilterTypeDef 구조체가 있다.

can.c 나 can.h 에 CAN_FilterTypeDef 누르고 F3 하면 바로 들어가짐

FilterIdHigh
FilterIdLow
FilterMaskIdHigh
FilterMaskIdLow
FilterFIFOAssignment : FIFO channel 0, channel 1, ID 저장소
FilterBank : (FilterMaskId + FilterId) 의 개수
FilterMode : Mask Mode, List Mode
FilterScale : 16 bit, 32 bit
FilterActivation : 사용 유무
SlaveStartFilterBank : Dual CAN 때 사용

FilterScale 에 따라서
32 bit 는 IdHigh 16 bit + IdLow 16 bit, MaskIdHigh 16 bit + MaskIdLow 16 bit -> 1쌍(2개)

16 bit 는
IdHigh 16 bit 한개 + MaskIdHigh 16bit 한개,
IdLow 16 bit 한개 + MaskIdLow 16bit 한개 -> 2 쌍(4개)
하지만 Single CAN 에서는 High 나 Low 하나만 쓰기 때문에 2개 다 같게 설정해준다.

Rx 또한 매크로가 다 있어서 찾아서 사용하면 된다.

8. 코드

buttonFlag 는 버튼을 눌렀을 때 인터럽트 발생 시 상태
can1_rx0_flag 는 CAN 수신 인터럽트 CALLBACK 발생 시 상태

CAN 통신을 시작할 때는
HAL_CAN_Start(사용할 can 주소);

CAN 송신 부분이다.
버튼을 눌러 데이터를 송신한다.

canTxHeader 구조체에

StdId, RTR, IDE, DLE 정하고

보낼 데이터를 만들어서

TxMailBox 에 넣는다 (MailBox 는 주소(Id)가 적혀있는 택배상자 정도로 생각된다.)

HAL_CAN_GetMailboxesFreeLevel(&hcan1) 은 3개의 MailBox 중 비어있는 곳을 사용한다는 것이다.

HAL_CAN_AddTxMessage(설정한 CAN 채널, Tx헤더주소, 보낼 데이터, 사용할 TxMailBox)
를 통해서 메세지를 전송한다.
------------------------------------------------------------------------
can1_rx0_flag 는 수신인터럽트가 발생할 때 1로 변경됨
if문은 수신 인터럽트가 발생했을 때 데이터를 받는 부분이다.

16 bit라서 High, Low 중 하나만 쓰면 되어서 같은 값을 넣어줬다.

<<5 시프트 연산자는 StdID 가 11 bit 로 되어있는데
보내는 데이터 한줄은 16 bit 이기 때문이다.

FIFO (First In First Out) 은 자료구조 Queue 의 형태를 말한다.

FilterBank 는 FilterMastId + FilterId 조합을 몇 개를 사용할 것인지 말한다.
(single CAN 0~13, dual CAN 0~27) 로 1개를 사용할 경우 0을 입력한다.

HAL_CAN_ActiveNotification(설정한 CAN 채널, FIFO0에 처리할 수신 메세지가 있는지 있으면 인터럽트 발생) -> 수신 인터럽트

HAL_GPIO_EXTI_Callback()
-> 버튼 눌렀을 때 인터럽트

HAL_CAN_RxFifo0MsgPendingCallback()
-> 수신 인터럽트 발생 시 작업

  • HAL_CAN_GetRxMessage
    (설정한 CAN 채널, 사용할 수신 FIFO 번호 , 받은 RxHeader 정보, 데이터 저장할 곳) <- 매개변수
profile
하고 싶은 것, 소유하고 싶은 것, 좋아하는 것

0개의 댓글