2013年8月30日金曜日

STM32F103でCAN通信

STM32F103VE(事実上のSTBee)を使ったCAN通信のメモ
嘘偽りなく調べ物した時のメモとしてそのままブログのエディタを使ってるので可読性とかは気にしていません




ペリフェラルクロックのEna


RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);
RCC_APB1Periph_CANじゃなくてRCC_APB1Periph_CAN1を指定

Remap

標準のCANポート(PA11/PA12)はUSBポートと共有しているため、ココをCANとして使うとDFUでコードが書けない USBのハードウェアは出来上がっているため、CANをRemapする
GPIO_PinRemapConfig(GPIO_Remap2_CAN1, ENABLE);
(詳しく調べていないが、GPIO_Initの後にRemapするとうまく動かないらしい)
GPIO_Remap2_CAN1はCAN1をふたつめの設定でRemapするという意味
STM32F103VEはCANは1本しか無いのでCAN1を指定
設定は1でも2でもいいけど 今回は2を指定
この設定によりCANのポートはPD0/PD1となる

GPIO


GPIO_InitTypeDef GPIO_InitStructure = {
    .GPIO_Speed = GPIO_Speed_50MHz,
    .GPIO_Mode = GPIO_Mode_AF_PP,
    .GPIO_Pin = _BV(0) | _BV(1),
};
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIOはとりあえず50MHz AF_PPを指定してみる
・CANは最大1Mbpsなので2MHzでもいいはず

CAN


CAN_InitTypeDef CAN_InitStructure;
CAN_StructInit(&CAN_InitStructure);
まずは構造体を初期化
これにより
CAN_TTCMDISABLE
CAN_ABOMDISABLE
CAN_AWUMDISABLE
CAN_NARTDISABLE
CAN_RFLMDISABLE
CAN_TXFPDISABLE
CAN_ModeCAN_Mode_Normal
CAN_SJWCAN_SJW_1tq
CAN_BS1CAN_BS1_4tq
CAN_BS2CAN_SB2_3tq
CAN_Prescaler1
という設定になる
それぞれ
CAN_TTCMtime triggered communication modeタイマトリガ通信モード
CAN_ABOMautomatic bus-off management自動バスオフ管理
CAN_AWUMautomatic wake-up mode自動ウェークアップモード
CAN_NARTno-automatic retransmission mode非自動再送モード
CAN_RFLMreceive fifo locked mode
CAN_TXFPthe transmit FIFO priority
RFLMとTXFPはよくわからなかった

CAN_Modeは以下の4種類
CAN_Mode_NormalCAN hardware operates in normal mode通常モード
CAN_Mode_SilentCAN hardware operates in silent modeサイレントモード(受信専用)
CAN_Mode_LoopBackCAN hardware operates in loop back mode通常モード(送信した値を受信)
CAN_Mode_Silent_LoopBackCAN hardware operates in loop back combined with silent modeサイレントループバック… ってなんぞ?
LoopBackとかを使うとCAN機器1台でも動作確認できるみたい
なので今回はLoopBackを使ってみる
CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;

CAN_Init(CAN1, &CAN_InitStructure);
CAN_Initは引数が2つある 1つじゃない

とりあえずこの時点でSTBeeに焼いてオシロで覗いてみる
(1メモリ1V)

なんか微妙な電圧がでている
PD0が0.8V PD1が2.7V くらい
これドミナントっぽい 電圧レベル的にはおかしくない気はするけど
電圧差もmin1.5Vをクリアしてるし でも常時ドミナントが出てるのはおかしい

とりあえずアナログっぽい電圧はでてるので、ちゃんとCANとして初期化できてると仮定して次へ
やることはただひとつ、データの送信

CanTxMsg canMsg = {
    .StdId = 0xA5,
    .ExtId = 0x00,
    .IDE = CAN_ID_STD,
    .RTR = CAN_RTR_DATA,
    .DLC = 6,
    .Data[0] = 0xAA,
    .Data[1] = 0x55,
    .Data[2] = 0x00,
    .Data[3] = 0xFF,
    .Data[4] = 0x01,
    .Data[5] = 0x80,
};
CAN_Transmit(CAN1, &canMsg);
こんな感じの送信メッセージを作って
UARTを通じてPCから送ってねという文字列を検出したら上記コードが実行される
という感じにした

んでPCからコマンドを送ってオシロで覗いた様子
(1メモリ1V/2.5uS)
見て分かる通り、非常に高速な波形が出ている
4Mbpsとかそれくらいかも
それと一応波形としては何か出ているんだが、CANっぽくない波形になっている

とりあえずデータレート高すぎるのでCAN_Initの設定を少しいじる
CAN_InitStructure.CAN_Prescaler = 128;
を追加してオシロで観察
1V/500uS
およそ35kbpsくらいになりました
一応プリスケーラは1024まで設定できるようなので かなり低速な通信が可能と思われます

〜ココで青猫、STMicroのPDFを読み直す〜
STM32の内蔵CANはソフトウェア的なモノだけで、ハードウェアは別のモノが必要らしい
具体的にはCANトランシーバーというICが必要
そのICを介すことにより平衡接続が可能になる
それが無いとただのデジタル信号になってしまう

ということで、CANのハードウェア的な動作確認はそのトランシーバーを買ってからでないとできない
トランシーバはいくつかあって、例えばマイクロチップのMCP2551とかがありますが
このICは3.3V動作ができないっぽかったりとか もうちょっと調べてみる必要が有るようです


とりあえず手持ちの部品じゃできないようだというのはわかったので
一旦メモ書き公開しておきます

0 件のコメント:

コメントを投稿