Nucleo-F303K8でCAN Bus通信を行う


目的

Nucleo F303K8ボードでCAN Busによる通信を行う際の覚書を記載します。

環境

  • Nucleo-F303K8 CAN通信環境
項目 内容
OS Windows 10 Home
マイコン Nucleo-F303K8
CANトランシーバー MCP2551 amazonリンク
終端抵抗 金属皮膜抵抗 120オーム 2個
Nucleo Board Firmware STM32Cube_FW_F3_V1.9.1

CAN出力機能付きのNucleo Boardを利用する際はMCP2551素子を利用します, MCP2515と紛らわしいので注意してください(MCP2515はSPI通信をCAN通信に変換してくれます。)

Firmware V1.10からCAN通信ドライバの関数が変更になっています 参考情報
新しいCAN通信ドライバのドキュメントはネットにあまり上がっていないので、詳細は次のフォルダ内にあるCAN通信の例を参考にするしか
なさそうです。

C:\Users(ユーザー名)\STM32Cube\Repository\STM32Cube_FW_F3_V(Version番号)\Projects\STM32303C_EVAL\Examples\CAN

  • デバッグ用CAN bus受信環境
項目 内容
マイコン (デバッグ用) Arduino Uno R3
Arduino CAN Bus Shield Sparkfun CAN bus shiled Sparkfunリンク

システム構成図

配線例

手順概要

  • STM32CubeMX設定
  • eclipseコード変更
  • Arduino環境構築
  • 動作確認

STM32CubeMX設定

Pinoutタブ

  • RCC->High Speed Clock (HSE)をBYPASS Clock Sourceに設定 参考情報

  • CAN->Master Modeに設定

  • USART1はRS232通信が必要であれば設定する。(オプション)

RCC->High Speed ClockでBYPASS Clock Sourceに設定した際には、initialise_monitor_handlesが見つかりませんエラーに
なってしまう。CAN Bus通信とsemihostingは両立できない??。現在、原因究明中

Clockタブ

以下のように設定しました。

Configurationタブ

ボーレートは500kbpsで設定しています。参考資料

計算式は以下です,

$ CAN Bus Clock = APB1 Periferal Clock (32MHz) / Prescaler (4) = 8 MHz $

ボーレートは500kbpsにしたいので

$ Time Quantum = 8 [MHz] / 0.5 [Mbps] = 16 [Times]$

つまり、1bit送る際に16回クロックの立ち上がりが来る

Start bitで1 [Times] 消費するので、Bit Segment 1を11 [Times]に設定すると

$ Sample Point = (11 + 1) [Times] / 16 [Times] = 0.75 $

つまり、この例ではSample Pointは75%。(ただ、添付資料によるとSample Pointは80%から90%に設定するのがいいらしいが、配線が短ければ50%~70%でも動作する)

上記設定が終われば、Generate Projectでプロジェクトを生成します。

eclipseコード修正 (can送信テスト)

  • Main関数while loop内
/* Infinite loop */
  /* USER CODE BEGIN WHILE */
    while (1)
    {

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
        hcan.pTxMsg->Data[0] = 0x31;
        hcan.pTxMsg->Data[1] = 0x32;
        if (HAL_CAN_Transmit(&hcan, 10) != HAL_OK) {
            Error_Handler();
        }
        HAL_Delay(1000);
    }
  /* USER CODE END 3 */
  • MX_CAN_Init内
/* CAN init function */
static void MX_CAN_Init(void)
{

  hcan.Instance = CAN;
  hcan.Init.Prescaler = 4;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SJW = CAN_SJW_1TQ;
  hcan.Init.BS1 = CAN_BS1_11TQ;
  hcan.Init.BS2 = CAN_BS2_4TQ;
  hcan.Init.TTCM = DISABLE;
  hcan.Init.ABOM = DISABLE;
  hcan.Init.AWUM = DISABLE;
  hcan.Init.NART = DISABLE;
  hcan.Init.RFLM = DISABLE;
  hcan.Init.TXFP = DISABLE;
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  CAN_FilterConfTypeDef  sFilterConfig;
  static CanTxMsgTypeDef        TxMessage;
  static CanRxMsgTypeDef        RxMessage;
  hcan.pTxMsg = &TxMessage;
  hcan.pRxMsg = &RxMessage;
  hcan.pTxMsg = &TxMessage;
  hcan.pRxMsg = &RxMessage;

  /*##-2- Configure the CAN Filter ###########################################*/
  sFilterConfig.FilterNumber = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;
  sFilterConfig.FilterMaskIdLow = 0x0000;
  sFilterConfig.FilterFIFOAssignment = 0;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.BankNumber = 14;

  if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
  {
    /* Filter configuration Error */
    Error_Handler();
  }

  /*##-3- Configure Transmission process #####################################*/
  hcan.pTxMsg->StdId = 0x321;
  hcan.pTxMsg->RTR = CAN_RTR_DATA;
  hcan.pTxMsg->IDE = CAN_ID_STD;
  hcan.pTxMsg->DLC = 2;

}

Arduino環境構築

  • Sparkfun社のCAN-Bus-Libraryをダウンロード

  • "C:\Program Files (x86)\Arduino\libraries"以下に展開したフォルダ内の"\Libraries\Canbus"をコピーします。

  • 以下のコードをArduino IDEにコピーしてArduinoに書き込みます。

/****************************************************************************
CAN Read Demo for the SparkFun CAN Bus Shield. 

Written by Stephen McCoy. 
Original tutorial available here: http://www.instructables.com/id/CAN-Bus-Sniffing-and-Broadcasting-with-Arduino
Used with permission 2016. License CC By SA. 

Distributed as-is; no warranty is given.
*************************************************************************/

#include <Canbus.h>
#include <defaults.h>
#include <global.h>
#include <mcp2515.h>
#include <mcp2515_defs.h>

//********************************Setup Loop*********************************//

void setup() {
  Serial.begin(9600); // For debug use
  Serial.println("CAN Read - Testing receival of CAN Bus message");  
  delay(1000);

  if(Canbus.init(CANSPEED_500))  //Initialise MCP2515 CAN controller at the specified speed
    Serial.println("CAN Init ok");
  else
    Serial.println("Can't init CAN");

  delay(1000);
}

//********************************Main Loop*********************************//

void loop(){

  tCAN message;
if (mcp2515_check_message()) 
    {
   Serial.println("Getting Message");
    if (mcp2515_get_message(&message)) 
    {
        //if(message.id == 0x620 and message.data[2] == 0xFF)  //uncomment when you want to filter
             //{

               Serial.print("ID: ");
               Serial.print(message.id,HEX);
               Serial.print(", ");
               Serial.print("Data: ");
               Serial.print(message.header.length,DEC);
               for(int i=0;i<message.header.length;i++) 
                {   
                  Serial.print(message.data[i],HEX);
                  Serial.print(" ");
                }
               Serial.println("");
             //}
           }}

}

動作確認

  • eclipseを立ち上げてNucleo-F303K8のプログラムを書き込んで実行します。

  • Arduinoでシリアルモニタを立ち上げて以下のような表示が出ると成功です。