しろうさぎのblog

元ロボカッパー(ジュニアBオープン)でレスコンに参加していました。次はロボカップSSLに参加予定です。気が向いたときにいろいろ書いていきます。

STM32G4でCAN-FDのループバックテストをする

どうもしろうさぎです。

とりあえずCAN-FDがループバックモードで動いたのでメモっておきます。


↓ここに使ったソースコードを載せておくのでこれを見ながらやればできるかと思います。

STM32-CAN-test/G431_test/

ちなみに、ADCやらタイマーでNucleo上に載ってるLEDでPWMでLチカとかできるように用意がされています。(PWMでのLチカはすでに実装済み)

EB7s5QVVUAA8pmk
キャプチャ
bmp_77_002

動作中の様子。32byte一気に送信して受信ができてます。

CAN-FDの細かい説明は後日しようかと思います。とりあえずループバックテストができましたよということで・・・・・。

2台NucleoG4がそろったら2台間で通信をさせてそれができたら解説記事書こうかと思ってます。

それでは今日はこの辺で



STM32CubeHALでCAN通信をする

どうもお久しぶりです、しろうさぎです。
とりあえず大学院入試が終わったのでibisで使うCAN通信をCubeHALで動かしてみました。
一応今回はSTM32CubeIDEを使って試してみています。(とはいっても前の環境でも同じはずなんですけどね。あれ単に統合しただけなので・・・・・。というか複数台のマイコンの設定がウィンドウ増やせばできたのができなくなってて若干くそになってるとかいう話はしない)

とりあえずCANとは何ぞやという話ですが適当にググってください。
(参考:https://monoist.atmarkit.co.jp/mn/articles/0806/16/news124.html

今回は、STM32F446RET6とSTM32F303K8T6間で通信をさせます。送信はポーリングで受信はFIFOを使った割り込み処理で実装していきます。

まず配線をします。CAN通信にはCANトランシーバーが必要になります(使ったのはこれ)。バスの終端にはそれぞれ120Ω抵抗をつけます。

そして、F446側のCubeでの設定。

キャプチャ
CANを有効にしてボーレートの設定をします。Cubeが1MBpsで設定しようとすると怒られたのでとりあえず適当に入力します。ボーレートの話はあとで詳しくしようかと思います。

キャプチャ2

受信割込みをするので割り込み有効にしてNVICを適当に変えます。
キャプチャ1
クロック設定。


以上になります。STM32F303kのほうでもだいたい同じ感じで設定しておきます。

ジェネレートが終わったら、コードを書いていきます。
グローバル変数として

CAN_TxHeaderTypeDef   TxHeader;
CAN_RxHeaderTypeDef   RxHeader;

uint8_t               TxData[8];
uint8_t               RxData[8];
uint32_t              TxMailbox;
uint8_t cnt;

これらを置きます。

また、受信割込みコールバック関数として、
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
  if (HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
  {
    Error_Handler();
  }
  xprintf(" id=%d [0]=%d [1]=%[2]=%d\r\n",RxHeader.StdId,RxData[0],RxData[1],RxData[2]);
}

を用意します。
メインでは、
While(1)の前に、
 
HAL_CAN_Start(&hcan1);
 if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
    {
    Error_Handler();
    }

を記述して、While(1)内に、

   TxHeader.StdId = 1234;
  TxHeader.RTR = CAN_RTR_DATA;
  TxHeader.IDE = CAN_ID_STD;
  TxHeader.DLC = 3;
  TxHeader.TransmitGlobalTime = DISABLE;
  TxData[0] = 100;
  TxData[1] = 200;
  TxData[2] = cnt;

  if(HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox) != HAL_OK)
  {
    Error_Handler();
  }
  while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) != 3) {}

   if(cnt>250){
   cnt=0;
   }
   else{
   cnt++;
   }

と記述します。

CANのInit関数をボーレートに合わせて書き換えていきます。
  hcan1.Init.Prescaler = 3;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_8TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_6TQ;
と書き換えます。

F303kでは、
hcan.Init.Prescaler = 2;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_8TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_7TQ;

とします。これでボーレートは1MBpsに設定できます。

また、CANのInit関数のUser code Bigin以下にCANフィルタを記述します。

  CAN_FilterTypeDef  sFilterConfig;
  sFilterConfig.FilterBank = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
  sFilterConfig.FilterIdHigh = 0x456<<5;
  sFilterConfig.FilterIdLow = 0x456<<5;
  sFilterConfig.FilterMaskIdHigh = 0x456<<5;
  sFilterConfig.FilterMaskIdLow = 0x456<<5;
  sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.SlaveStartFilterBank = 14;

  if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)
  {
  Error_Handler();
  }

ここでは、F303側のIDを0x456としたので、IDには0x456を5ビット左シフトさせたものを代入します。


ソースコードとしては以上になります。F303K側も大体同じ感じで書きます。


使ったソースコード及びプロジェクトファイルをここに置いておきます


スクリーンショット (180)
うごかしてみるとちゃんと動作しているのがわかるかと思います。

bmp_70_000
せっかくなのでオシロ波形をば。青(CH2)がバス上の波形で、黄色(Ch1)がF446のCAN-RXピンの波形です。

ACKが返ってないときはボーレートが2個の間でおなじかを確認します。(これでかなりの時間を溶かした)最悪は遅いほうにシステムクロックを合わせて設定をおなじにしてあげればよいかと思います。それでとりあえず動作の確認は取れるかと・・・・・


最後に、ボーレートについて。
STのデーターシートを読むとこのように書かれています。
キャプチャ3

ここから3つのパラメータを設定していくわけなのですが、

CANBusClock=APB1PeriferalClock(45MHz)/Prescaler(3)=15MHz

TimeQuantum=15[MHz]/1[Mbps]=15[Times]


つまり、1bit送る際に15回クロックの立ち上がりが来る
Start bitで1 [Times] 消費するので、Bit Segment 1を8 [Times]に設定すると,

SamplePoint=(8+1)[Times]/15[Times]=0.6

Sample Pointは80%から90%に設定するのがいいらしいですが、
配線が短ければ50%~70%でも動作します。

こんな感じにボーレートを決めてそれに従って、プリスケーラーと
TimeSeg1、TimeSeg2を計算していきます



まぁだいたいこんな感じです。すごくわかりくいですが勘弁してください、
まだやり始めたばかりでCANとはなんぞやってのが濃厚すぎて説明ができない。


何かありましたらどうぞお気軽に。

それでは今回はこの辺で。


CubeIDE環境でC++でSTM32を開発する

どうもしろうさぎです。

結構前にCubeIDEがリリースされました。なんかC++が使えるようになったそうなのですが、それに関する記事が全くなかったので適当に試してまとめておきました。

とりあえずプロジェクトを作成します。ここで、C++のほうを選択しておきます。
スクリーンショット (176)
それで適当にプロジェクトを作成します。

スクリーンショット (177)
リネームを選択して、
スクリーンショット (178)
それでmain.cがあるので、main.cppに変更します。

これでビルドをすると、g++でビルドしているので正常にC++のプロジェクトとして認識されているのがわかります。

スクリーンショット (179)

一応今回クラスを使って動かしているので、C++固有の書き方をしましたがちゃんと動作しています。

10回100msごとにトグルして、そのあと10回1000msごとにトグルするようになっています。

//クラス定義
class TEST{
public:
int figure;
void calc(int temp){
figure=temp;
HAL_Delay(figure);
}
};
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  while (1)
  {
  TEST test;
  for(int i=0;i<10;i++){
  test.calc(100);
  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
  }

  for(int i=0;i<10;i++){
  test.calc(1000);
  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
  }

  }
  /* USER CODE END 3 */
}

一応適当に使ったサンプルを張っておきます。


C++として開発する際のお話は以上です。


ここで注意ですが、Cubeをジェネレートするたびにmain.cが作成されてもともとのmain.cppは一切継承されません。
IMG_0620


こうなります。main.cとmain.cppがある・・・・・。

まぁ基板作ってCでペリフェラル確認して、それが終わってからC++で実際のコードを書くといった感じになるんでしょうかね。

CubeIDEでは、ペリフェラル設定の.ioc画面では、今までのHALのジェネレートボタンがなくなって(実際には奥にあったけど表に出ていない)保存をするたびに勝手にジェネレートするっぽいです。


それでは今日はこの辺で。




アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

記事検索
ギャラリー
  • SSL研究会2019に行ってきました。
  • SSL研究会2019に行ってきました。
  • STM32G4でCAN-FDのループバックテストをする
  • STM32G4でCAN-FDのループバックテストをする
  • STM32G4でCAN-FDのループバックテストをする
  • STM32CubeHALでCAN通信をする
QRコード
QRコード