2013年10月8日火曜日

STM32F1 standard peripheral CAN

STM32F1のCAN周り覚書

なお古いライブラリ(少なくとも4年以上)を使っているので、最新とは違うかも

CanRxMsgの中身
    uint32_t StdId;
    uint32_t ExtId;
    uint8_t IDE;
    uint8_t RTR;
    uint8_t DLC;
    uint8_t Data[8];
    uint8_t FMI;

・StdId
標準の識別子 0から0x7FFの範囲

・ExtId
拡張識別子 0から0x1FFFFFFFの範囲

・IDE
受信したメッセージの識別子タイプ CAN_identifier_type

・RTR
受信したメッセージのフレームタイプ CAN_remote_transmission_request

・DLC
受信したフレームの長さ 0から8の範囲

・Data[8]
受信したデータ 配列は8バイト確保されている 有効なデータ数はDLC

・FMI
フィルタ関係?


CAN_identifier_typeについて
    #define CAN_ID_STD
    #define CAN_ID_EXT
    #define IS_CAN_IDTYPE(IDTYPE)
CANID_STDとCANID_EXTがある
それぞれ標準IDと拡張IDを示している
IS_CAN_IDTYPEは「引数がSTDかEXTならば0位外を返す」というマクロ
ただCAN_ID_STDもCAN_ID_EXTも中身はuint32_t
STDかEXTかを調べるには自分でifで判断する必要がある


CAN_remote_transmission_requestについて
    #define CAN_RTR_DATA
    #define CAN_RTR_REMOTE
    #define IS_CAN_RTR(RTR)
CAN_identifier_typeと同様

なお (CAN_RTR_DATA == CAN_ID_STD) == true という関係なので
例えばIS_CAN_IDTYPE(CAN_RTR_DATA)とやるとtrueになる(おそらく
このためIS_CAN_IDTYPEやIS_CAN_RTRはあまり信用しない方がいいはず


CAN_MessagePendingについて
宣言は以下のとおり
uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber);

説明は以下
  * @brief  Returns the number of pending messages.
  * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.
  * @param  FIFONumber: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1.
  * @retval NbMessage which is the number of pending message.
要約すると
説明:保留中のメッセージの数を返す
引数:CAN1もしくはCAN2 ペリフェラルを選択
引数:FIFOの選択 FIFO0もしくはFIFO1
戻り値:保留中のメッセージ数

何をする関数かというと、FIFOにたまっているメッセージ数を返す
中身は
(uint8_t)(CANx->RF0R&(uint32_t)0x03)
もしくは
(uint8_t)(CANx->RF1R&(uint32_t)0x03)
を引数に応じて返している

CanRxMsg構造体の中にはデータの有効性を確認するためのレジスタはない
また、CAN_Receive関数の中にもデータの存在を確認する処理はない
FIFOにデータが有ろうが無かろうがReceive関数を呼べばFIFOの中身を返してくる
しかしFIFOの中身が0であれば意味のない値になる
しかし意味がある値日意味のない値かは値から判断することはできない

実際にCANを使う場合は一定期間ごとにCAN_MessagePendingをポーリングして
戻り値>0が真の場合にCAN_Receiveを読んでデータを処理することになる


CANで1つのデータが一番短い時はRTRの37bit
1Mbpsで通信している場合40bitとして1回40マイクロ秒くらい
実際にはもっと長いけど、FIFOが4フレーム分3フレーム分しか無いことを考えるとかなり高速でポーリングする必要があるかも
といってもまぁものすごいクリティカルな用途でもなければ秒数百回程度ポーリングすれば十分なはず

最悪の場合スマートじゃないけどCanRxMsgの配列を作ってCAN受信割り込みでリングバッファに貯めこんで大容量のFIFOを作るってやり方もあるw

0 件のコメント:

コメントを投稿