技術者見習いのメモ書き

電子工作や神社めぐりなどの趣味の話を中心に書いていきます。 Twitter:@hakura_riku

中国製RISC-Vマイコン CH32V307でUART通信

はじめに

中国製RISC-Vマイコン CH32V307でUART通信を行う方法を解説します.

本記事は参考文献 1を参考にして, CH32V307V-EVT-R1で動作確認を行っています.

USARTとは

CH32V307はUARTでは無くUSARTのポートを持っています. USARTは非同期のシリアル通信に加えて同期式のシリアル通信にも対応しているポートです. 非同期通信の場合, UARTとUSARTの違いはありません.

UART:非同期式のシリアル通信にのみ対応

USART:同期および非同期式のシリアル通信に対応

サンプルプログラムの解説

CH32V307のUSART1はデバッグポートとして使用されているため, 今回のプログラムではUSART2を使用します[3]. ピンと機能の割り付けについては, 参考文献4の3.2章をご確認ください.

今回紹介するプログラムは参考文献1と参考文献3のコードを参考に記述した物です. プログラムの実装内容は下記の通りです.

  1. GPIO_InitTypeDef, USART_InitTypeDefを定義する.

  2. USART2のRX, TXピンのGPIOクロックとUSART2クロックを有効にする.

  3. GPIOポートの設定とシリアルポートの初期化

  4. NVIC_InitTypeDefの定義とNVICの設定

  5. シリアルポートとUSART受信割り込みを有効化する.

  6. 文字を送信する関数と文字列を送信する関数を定義する

  7. USART受信割り込み関数を定義する

USART2初期化関数

下記のコードでUSART2で使用するGPIOの初期化とUSART2の初期化を行っています.

/********************************************************************
* 関数名   : USART2_Init
* 機能        : USART2初期化
* 入力        : 無し
* 戻り値     : 無し
********************************************************************/
void USART2_Init(void)
{
   GPIO_InitTypeDef  GPIO_InitStructure;
   USART_InitTypeDef USART_InitStructure;

   RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);       //USART2のクロックを有効化する
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);        //GPIOAのクロックを有効化する
    /* USART2 TX-->PA2  RX-->PA3 */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;              //TX:PA2をオルタネート機能プッシュプル出力に設定
   GPIO_Init(GPIOA, &GPIO_InitStructure);
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                 //RX:回路上にプルアップ抵抗が無いので,PA3をプルアップ機能付きの入力に設定
   GPIO_Init(GPIOA, &GPIO_InitStructure);

   USART_InitStructure.USART_BaudRate =  115200;                    // シリアルポートのボーレートを115200に設定する
   USART_InitStructure.USART_WordLength =   USART_WordLength_8b;    // ワード長を8ビットデータ形式にする
   USART_InitStructure.USART_StopBits =  USART_StopBits_1;          // ストップビット1
   USART_InitStructure.USART_Parity =    USART_Parity_No;           // パリティビットなし
   USART_InitStructure.USART_HardwareFlowControl =   USART_HardwareFlowControl_None; // ハードウェアフロー制御なし
   USART_InitStructure.USART_Mode = USART_Mode_Tx |  USART_Mode_Rx; //送受信モード

   USART_Init(USART2, &USART_InitStructure);                        //シリアルポートを初期化する
}

割り込みの初期化

下記のコードで受信割り込みの初期化を行っています.

/********************************************************************
* 関数名   : Interrupt_Init
* 機能        : USART2受信割り込み初期化
* 入力        : 無し
* 戻り値   : 無し
********************************************************************/
void Interrupt_Init(void)
{
   NVIC_InitTypeDef NVIC_InitStructure={0};
   NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
}

ASCiiコードの文字送信

ライブラリ関数のUSAT_SendDataを使用して, ASCiiコードの文字を1文字送信します.

/********************************************************************
* 関数名   : USARTx_SendByte
* 機能        : ASCiiコード文字の送信
* 入力        : USART_TypeDef, 8bitの送信データ
* 戻り値   : 無し
********************************************************************/
void USARTx_SendByte(USART_TypeDef* pUSARTx, uint8_t data)
{
    USART_SendData(pUSARTx, data);
    while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}

参考文献3より引用

文字列の送信

USARTx_SendByte関数を使用して文字列を送信します.

/********************************************************************
* 関数名   : USARTx_SendStr
* 機能        : 文字列の送信
* 入力        : USART_TypeDef, 文字列データ
* 戻り値   : 無し
********************************************************************/
void USARTx_SendStr(USART_TypeDef* pUSARTx, char *str)
{
    uint8_t i = 0;
    do
    {
        USARTx_SendByte(pUSARTx, *(str+i));
        i++;
    }while(*(str+i) != '\0');
    while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET);
}

参考文献3より引用

割り込み関数

受信した文字をそのまま送信するプログラムです.

/********************************************************************
* 関数名      : USART2_IRQHandler(void)
* 機能   : 割り込み関数
* 入力         : 無し
* 戻り値         : 無し
*********************************************************************/
void USART2_IRQHandler(void)   __attribute__((interrupt("WCH-Interrupt-fast")));
void USART2_IRQHandler(void)
{
    uint8_t ucTemp;
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_RXNE);//割り込みフラグをリセットする
        ucTemp = USART_ReceiveData(USART2);           //データを受信する
        USART_SendData(USART2, ucTemp);               //データを送信する
    }
}

参考文献3より引用

作成したプログラムの全体

上記のプログラムとメイン関数を記述した物が下記になります.

#include "debug.h"


/********************************************************************
* 関数名   : USART2_Init
* 機能        : USART2初期化
* 入力        : 無し
* 戻り値     : 無し
********************************************************************/
void USART2_Init(void)
{
   GPIO_InitTypeDef  GPIO_InitStructure;
   USART_InitTypeDef USART_InitStructure;

   RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);       //USART2のクロックを有効化する
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);        //GPIOAのクロックを有効化する
    /* USART2 TX-->PA2  RX-->PA3 */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;              //TX:PA2をオルタネート機能プッシュプル出力に設定
   GPIO_Init(GPIOA, &GPIO_InitStructure);
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                 //RX:回路上にプルアップ抵抗が無いので,PA3をプルアップ機能付きの入力に設定
   GPIO_Init(GPIOA, &GPIO_InitStructure);

   USART_InitStructure.USART_BaudRate =  115200;                    // シリアルポートのボーレートを115200に設定する
   USART_InitStructure.USART_WordLength =   USART_WordLength_8b;    // ワード長を8ビットデータ形式にする
   USART_InitStructure.USART_StopBits =  USART_StopBits_1;          // ストップビット1
   USART_InitStructure.USART_Parity =    USART_Parity_No;           // パリティビットなし
   USART_InitStructure.USART_HardwareFlowControl =   USART_HardwareFlowControl_None; // ハードウェアフロー制御なし
   USART_InitStructure.USART_Mode = USART_Mode_Tx |  USART_Mode_Rx; //送受信モード

   USART_Init(USART2, &USART_InitStructure);                        //シリアルポートを初期化する
}


/********************************************************************
* 関数名   : Interrupt_Init
* 機能        : USART2受信割り込み初期化
* 入力        : 無し
* 戻り値   : 無し
********************************************************************/
void Interrupt_Init(void)
{
   NVIC_InitTypeDef NVIC_InitStructure={0};
   NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
}

/********************************************************************
* 関数名   : USARTx_SendByte
* 機能        : ASCiiコードの文字送信
* 入力        : USART_TypeDef, 8bitの送信データ
* 戻り値   : 無し
********************************************************************/
void USARTx_SendByte(USART_TypeDef* pUSARTx, uint8_t data)
{
    USART_SendData(pUSARTx, data);
    while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}

/********************************************************************
* 関数名   : USARTx_SendStr
* 機能        : 文字列の送信
* 入力        : USART_TypeDef, 文字列データ
* 戻り値   : 無し
********************************************************************/
void USARTx_SendStr(USART_TypeDef* pUSARTx, char *str)
{
    uint8_t i = 0;
    do
    {
        USARTx_SendByte(pUSARTx, *(str+i));
        i++;
    }while(*(str+i) != '\0');
    while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET);
}

/*********************************************************************
 * @fn      main
 *
 * @brief   Main program.
 *
 * @return  none
 */
int main(void)
{
    USART2_Init();                                  //USART2を初期化する
    Interrupt_Init();                               //割り込みを初期化する

    USART_Cmd(USART2, ENABLE);                      //USART2を有効化する
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);  //割り込みを有効化する

    USARTx_SendStr(USART2, "Hello World.\n");       //テストデータの送信

    while(1);                                       //無限ループ
}

/********************************************************************
* 関数名      : USART2_IRQHandler(void)
* 機能   : 割り込み関数
* 入力         : 無し
* 戻り値         : 無し
*********************************************************************/
void USART2_IRQHandler(void)   __attribute__((interrupt("WCH-Interrupt-fast")));
void USART2_IRQHandler(void)
{
    uint8_t ucTemp;
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_RXNE);//割り込みフラグをリセットする
        ucTemp = USART_ReceiveData(USART2);           //データを受信する
        USART_SendData(USART2, ucTemp);               //データを送信する
    }
}

動作確認の配線

CH32V307V-EVT-R1に実装されているWCH-LinkをUSBシリアル変換器として使用して動作確認を行いました.

WCH-Linkのジャンパピンを全て外し, RX0をジャンパ線でPA2に接続し, TX0をジャンパ線でPA3に接続することでWCH-LinkをUSBシリアル変換器として使えます.

配線

WCH-LinkをUSBシリアル変換器として使用する場合の注意点

WCH-LinkをUSBシリアルとして使用すると稀にWCH-LinkがARMモードに切り替わってしまう事があります.

WCH-LinkのCON LED(青色のLED)が常時点灯している場合は, ARMモードになっているので下記の手順でRSIC-Vモードに切り替えてください.

1.WCH-Linkの電源を切りTX0とGNDをジャンパピンでショートする

2.WCH-Linkの電源を投入する. 青色LEDが消灯していればRSIC-VモードになっているのでWCH-Linkの電源を切り元の状態に戻す.

おわりに

UART通信の方法を解説しました. WCH-LinkがARMモードに切り替わってしまった時は故障かと勘違いしましたが, 参考文献5のマニュアルを確認することで対処できました.

書き込みが上手く行かない場合はWCH-Linkのマニュアルを確認すると良さそうです.

参考文献

[1] Xy_, ‘‘CH32V307教程 [第四集] [通信协议], ” https://verimake.com/d/152-ch32v307.

[2] わわわIT用語辞典, ‘‘USARTとは, ” https://wa3.i-3-i.info/word12983.html.

[3] 草帽王子, ‘‘CH32V103应用教程——USART, ” https://www.risc-v1.com/thread-1529-1-1.html.

[4] WCH, ‘‘CH32V20x_30xDS0.PDF, ” http://www.wch-ic.com/downloads/CH32V20x_30xDS0_PDF.html.

[5] WCH, ‘‘WCH-Link使用说明, ” http://www.wch.cn/bbs/thread-71088-1.html.

中国製RISC-Vマイコン CH32V307のタイマ機能

はじめに

中国製RISC-Vマイコン CH32V307のタイマ機能の使用方法を解説します.

本記事は参考文献 1を参考にして, CH32V307V-EVT-R1で動作確認を行っています.

CH32V307のタイマ機能

CH32V307は3種類のタイマーを持っています. 各タイマの概要を下記に記載します.

タイマの名称 詳細
Advanced-control Timer (ADTM) 最も多機能な16bitタイマで, カスケード接続によりタイマ間で同期できます. (TIM1, 8, 9, 10に機能が割り当たっています. ) 詳細については参考文献2の14章をご確認ください.
General-purpose Timer (GPTM) 16bitの基本的なキャプチャ機能とPWM出力機能などを持つ汎用タイマです. (TIM2, 3, 4, 5に機能が割り当たっています. ) 詳細については参考文献2の15章をご確認ください.
Basic Timer (BCTM) 最も機能の少ない16bitタイマで割り込みなどに使用できます. (TIM6, 7に機能が割り当たっています) 詳細については参考文献2の16章をご確認ください.

タイマ割り込み機能

タイマ割り込みを使用してLEDを0.5秒ごとに点滅させるプログラムを作成します.

紹介するプログラムではBCTMのTIM6(16bitのカウンタ)を使用して割り込みを行っています.

動作周波数の設定

CH32V307の動作周波数はデフォルトで72MHzに設定されているので144MHzに変更します.

「User」フォルダの直下にある「system_ch32V30x.c」のコードを表示します. この部分でチップの動作周波数が設定されており, 下記の様に72MHzの部分をコメントアウトし, 144MHzの部分を有効化することで144MHzで動作します.

周波数設定の変更方法

水晶発振器の起動タイムアウト時間設定

実装されている水晶発振器の起動時間が長くタイムアウトする場合があるので, 水晶発振器の起動タイムアウト閾値を変更します.

水晶発振器の起動タイムアウト閾値を変更は「ch32v30x.h」で行います. 「ch32v30x.h」は「Debug」フォルダ直下にある「debug.h」を表示し, インクルードされている「ch32v30x.h」を右クリックして「Open Declaration」を選択することで表示できます.

ch32v30x.hの表示方法

HSE_STARTUP_TIMEOUTが水晶発振器の起動タイムアウト閾値です. この値を0x4000に変更します.

ちなみにHSE_VALUEが外部水晶発振器の周波数です. CH32V307V-EVT-R1の水晶発振器は8MHzなので今回は変更する必要ありません.

起動タイムアウト閾値の変更

タイマの初期化

TIM6を初期化するコードは下記の通りです.

設定する機能の名称や関数名がSTM32系のマイコンと同じなので, それらのマイコンを使用した事がある人は簡単に設定できると思います. CH32Vシリーズのタイマ関連のコードを詳しく確認したい方は参考文献4に記載されているのでご確認ください.

/********************************************************************
* 関数名        : TIM6_Init
* 機能             : TIM6タイマ初期化
* 入力             : arr:カウント上限値,psc プリスケーラの値
* 戻り値          : 無し
********************************************************************/
void TIM6_Init( u16 arr, u16 psc)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM6, ENABLE );              //TIM6クロックを有効化する

    TIM_TimeBaseInitStructure.TIM_Period = arr;                         //カウント上限回数を設定する
    TIM_TimeBaseInitStructure.TIM_Prescaler = psc;                      //クロックの分周に使用するプリスケーラの値を指定
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;         //クロック分周係数
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Down;   //TIMカウントモード, ダウンカウントモード
    TIM_TimeBaseInit( TIM6, &TIM_TimeBaseInitStructure);                //設定したパラメータにしたがってTIM6を初期化するコード

    TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);                          //TIM6割り込みを有効化し, 割り込み更新を許可する
    TIM_ARRPreloadConfig( TIM6, ENABLE );                               //TIM6のプリロード機能を有効化
    TIM_Cmd( TIM6, ENABLE );                                            //TIM6を有効にする
}

参考文献1より引用

割り込みの設定

TIM6のNVICを設定します.

設定方法は下記の通り, 前回紹介した外部割込みのコードから一部分を削除した様な感じです.

/********************************************************************
* 関数名   : Interrupt_Init
* 機能        : タイマ割り込み初期化
* 入力        : 無し
* 戻り値   : 無し
********************************************************************/
void Interrupt_Init(void)
{
   NVIC_InitTypeDef NVIC_InitStructure={0};
   NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn ;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
}

参考文献1より引用

割り込みプログラム

割り込み関数も外部割込みの際に使用したプログラムと大差ありません.

下記の通りに入力してください.

/********************************************************************
* 関数名      : TIM6_IRQHandler
* 機能   : 割り込み関数
* 入力         : 無し
* 戻り値         : 無し
*********************************************************************/
void TIM6_IRQHandler(void)   __attribute__((interrupt("WCH-Interrupt-fast")));
volatile uint16_t LED_Status = 0;
void TIM6_IRQHandler(void)
{
    TIM_ClearFlag(TIM6, TIM_FLAG_Update);//割り込みフラグリセット
    LED_Status = !LED_Status ;
    GPIO_WriteBit(GPIOE, GPIO_Pin_11, LED_Status);
}

参考文献1より引用

プログラム全体

これまでに作成したプログラムにGPIOの初期化とメイン関数を追加した物を以下に記載します.

メイン関数内に記述されている「TIM6_Init」の引数の意味は下記の通りです. (レジスタは0からカウントを開始するため, 設定したい値から-1しています.)

14400-1:分周比を14400に設定して144MHzを10kHzにするためにこの値を入れています.

5000-1:カウント値を5000に設定し, 0.5msので割り込みが発生するようにしています.

#include "debug.h"

/********************************************************************
*関数名       : GPIO_INIT
*機能    :  GPIO初期化
*入力          : 無し
*戻り値          : 無し
********************************************************************/
void GPIO_INIT(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure={0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOE, &GPIO_InitStructure);
}


/********************************************************************
* 関数名        : TIM6_Init
* 機能             : TIM6タイマ初期化
* 入力             : arr:カウント上限値,psc プリスケーラの値
* 戻り値          : 無し
********************************************************************/
void TIM6_Init( u16 arr, u16 psc)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM6, ENABLE );              //TIM6クロックを有効化する

    TIM_TimeBaseInitStructure.TIM_Period = arr;                         //カウント上限回数を設定する
    TIM_TimeBaseInitStructure.TIM_Prescaler = psc;                      //クロックの分周に使用するプリスケーラの値を指定
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;         //クロック分周係数
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Down;   //TIMカウントモード, ダウンカウントモード
    TIM_TimeBaseInit( TIM6, &TIM_TimeBaseInitStructure);                //設定したパラメータにしたがってTIM6を初期化するコード

    TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);                          //TIM6割り込みを有効化し, 割り込み更新を許可する
    TIM_ARRPreloadConfig( TIM6, ENABLE );                               //TIM6のプリロード機能を有効化
    TIM_Cmd( TIM6, ENABLE );                                            //TIM6を有効にする
}


/********************************************************************
* 関数名   : Interrupt_Init
* 機能        : タイマ割り込み初期化
* 入力        : 無し
* 戻り値   : 無し
********************************************************************/
void Interrupt_Init(void)
{
   NVIC_InitTypeDef NVIC_InitStructure={0};
   NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn ;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
}


/********************************************************************
* 関数名    :  main
* 機能   : main関数
* 入力         : 無し
* 戻り値         : 無し
*********************************************************************/
int main(void)
{
    GPIO_INIT();     //GPIO初期化
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//割り込み優先度の設定
    TIM6_Init( 5000-1, 14400-1 );
    Interrupt_Init();//割り込み初期化
    while(1);        // 無限ループ
}



/********************************************************************
* 関数名      : TIM6_IRQHandler
* 機能   : 割り込み関数
* 入力         : 無し
* 戻り値         : 無し
*********************************************************************/
void TIM6_IRQHandler(void)   __attribute__((interrupt("WCH-Interrupt-fast")));
volatile uint16_t LED_Status = 0;
void TIM6_IRQHandler(void)
{
    TIM_ClearFlag(TIM6, TIM_FLAG_Update);//割り込みフラグリセット
    LED_Status = !LED_Status ;
    GPIO_WriteBit(GPIOE, GPIO_Pin_11, LED_Status);
}

参考文献1より引用

動作確認のための配線

動作確認をする際はCH32V307V-EVT-R1のPE11とLED1を配線してください.

動作確認時の配線

おわりに

CH32V307のタイマ機能について紹介しました. 参考文献1ではPWM機能の使い方も紹介しているので, PWMを使用したい方は参考文献1をご参照ください.

CH32系マイコンはSTM32と近い使用感でプログラミングでき, 中国国内ではSTM32を置き換える事の出来る製品としてCH32V103が紹介されています[5]. STM32より安く, 使用感が近いマイコンを探している方は試しに使用してみてもいいかもしれません.

参考文献

[1] Xy_, ‘‘CH32V307教程 [第三集] [时钟], ” https://verimake.com/d/151-ch32v307.

[2] openwch, ‘‘CH32FV2x_V3x Reference Manual, ” https://github.com/openwch/ch32v307/tree/main/Datasheet.

[3] openwch, ‘‘Input_Capture, ” https://github.com/openwch/ch32v307/blob/main/EVT/EXAM/TIM/Input_Capture/User/main.c.

[4] 草帽王子, ‘‘第七章:CH32V103应用教程——定时器中断, ” https://www.risc-v1.com/thread-1533-1-1.html.

[5] gaosmile, ‘‘[分享] 能够替代STM32的国产产品介绍, ” https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=628667.

中国製RISC-Vマイコン CH32V307の外部割込み機能

はじめに

中国製RISC-Vマイコン CH32V307の外部割込み機能の使用方法を解説します.

前回と同様に参考文献 1を参考にCH32V307V-EVT-R1を使用して動作確認を行いましたので, その方法をメモとして残します.

CH32V307の外部割込み機能

CH32V307には16個の外部割込みが存在し, EXTI0~EXTI15を全てのIOポート(Px0~Px15(x=A/B/C/D/E))に外部割込み/イベント機能として設定することが出来ます.

しかし, 外部割込みのチャンネルとGPIOのポート番号が一致していなければならないという制約があります. つまり, PA1に対して割り込みを設定している場合, PB1, PC1, PD1, PE1には割り込みを設定できません.

割り込みのチャンネル 対応ポート
EXTI0 PA0, PB0, PC0, PD0, PE0
EXTI1 PA1, PB1, PC1, PD1, PE1
EXTI2 PA2, PB2, PC2, PD2, PE2
EXTI15 PA15, PB15, PC15, PD15, PE15

外部割込み機能有効化の手順

WCHが公式にアップロードしている外部割込みのサンプルコードに記載されている初期化プログラムは3つの機能で構成されています.

  1. 外部入力を入れるGPIOを初期化し, 入力モードとして設定する

  2. EXTernal Interrupt(EXTI)を設定する

  3. ベクタ割込みコントローラ(NVIC)を設定する

コードの中身を確認するとPA0を割り込み用のピンとして設定しており, 信号の立下りで割り込みが入るようになっている事が分かります.

void EXTI0_INT_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    EXTI_InitTypeDef EXTI_InitStructure = {0};
    NVIC_InitTypeDef NVIC_InitStructure = {0};

     /* 外部入力を入れるGPIOを初期化し, 入力モードとして設定する*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /*EXTernal Interrupt(EXTI)を設定する*/
    /* GPIOA ----> EXTI_Line0 */
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
    EXTI_InitStructure.EXTI_Line = EXTI_Line0;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;      //割り込みのトリガー条件設定
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    /* ベクタ割込みコントローラ(NVIC)を設定する*/
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //割り込み優先度
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //サブプライオリティー
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

参考文献2より引用

割り込み発生時の処理

WCHが公式にアップロードしている外部割込みの実行部分はch32v30x_it.cに記載されています.

void EXTI0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

/*********************************************************************
 * @fn      EXTI0_IRQHandler
 *
 * @brief   This function handles EXTI0 Handler.
 *
 * @return  none
 */
void EXTI0_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line0)!=RESET)
  {
#if 0
    printf("Run at EXTI\r\n");

#endif
    EXTI_ClearITPendingBit(EXTI_Line0);     /* Clear Flag */
  }
}

参考文献2より引用

動作確認用プログラム

参考文献1に記載されているプログラムを参考に割り込みプログラムの作成を行いました. このプログラムはPA0, PC1に割り込み機能を割り当て, スイッチのON/OFFでLED1, 2を点灯/消灯させます.

#include "debug.h"
/********************************************************************
* 関数名       : GPIO_INIT
* 機能       :LED点灯用GPIOの初期化
********************************************************************/
void GPIO_INIT(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure={0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOE, &GPIO_InitStructure);
}
/********************************************************************
* 関数名       : EXTI_INT_INIT
* 機能       : 外部割り込みの初期化
********************************************************************/
void EXTI_INT_INIT(void)
{
   GPIO_InitTypeDef  GPIO_InitStructure={0};
   EXTI_InitTypeDef EXTI_InitStructure={0};
   NVIC_InitTypeDef NVIC_InitStructure={0};

   /*
    * EXTI0の設定
    * GPIOAの0ピンに対して割り込み機能を設定する
   */
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA,ENABLE);

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
   GPIO_Init(GPIOA, &GPIO_InitStructure);

   GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
   EXTI_InitStructure.EXTI_Line= EXTI_Line0;
   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //割り込みのトリガー条件設定
   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
   EXTI_Init(&EXTI_InitStructure);

   NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //割り込み優先度
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;        //サブプライオリティー
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);


   /*
    * EXTI1の設定
    * GPIOCの1ピンに対して割り込み機能を設定する
   */
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOC,ENABLE);

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
   GPIO_Init(GPIOC, &GPIO_InitStructure);


   GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource1);
   EXTI_InitStructure.EXTI_Line= EXTI_Line1;
   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //割り込みのトリガー条件設定
   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
   EXTI_Init(&EXTI_InitStructure);

   NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //割り込み優先度
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;        //サブプライオリティー
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
}

/********************************************************************
* 関数名      :  main
* 機能   : メイン関数
*********************************************************************/
int main(void)
{
    EXTI_INT_INIT(); // 割り込み機能の初期化
    GPIO_INIT();     // GPIOの初期化
    while(1);        // 無限ループ
}

/********************************************************************
* 関数名    : EXTI0_IRQHandler
* 機能    : EXTI0の割り込み関数
*********************************************************************/
void EXTI0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
volatile uint16_t LED_Status = 0; // volatileを持つ割り込みで使用される変数は、グローバル変数として扱うことができる
void EXTI0_IRQHandler(void)
{
    Delay_Ms(500); //チャタリング防止用
    EXTI_ClearFlag(EXTI_Line0); // 割り込みフラグをリセット
    LED_Status = !LED_Status ;  // LEDの状態値の反転
    GPIO_WriteBit(GPIOE, GPIO_Pin_11, LED_Status); // PE11(つまりLED1)の状態を設定する
}

/********************************************************************
* 関数名    : EXTI1_IRQHandler
* 機能    : EXTI1の割り込み関数
*********************************************************************/
void EXTI1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
volatile uint16_t LED_Status2 = 0; // volatileを持つ割り込みで使用される変数は、グローバル変数として扱うことができる
void EXTI1_IRQHandler(void)
{
    Delay_Ms(500);  //チャタリング防止用
    EXTI_ClearFlag(EXTI_Line1); // 割り込みフラグをリセット
    LED_Status2 = !LED_Status2 ;  // LEDの状態値の反転
    GPIO_WriteBit(GPIOE, GPIO_Pin_12, LED_Status2); // PE11(つまりLED1)の状態を設定する
}

動作確認時の配線

CH32V307V-EVT-R1には自由に使用できるスイッチが一つしかないので, PA0で動作確認する場合とPC1で動作確認する場合それぞれで配線を変える必要があります.

・PA0とKEYの配線 : スイッチの配線PA0の割り込み機能確認時に配線する

・PC1とKEYの配線 : スイッチの配線PC1の割り込み機能確認時に配線する

・PE10とLED1の配線 : LED1の配線

・PE11とLED2の配線 : LED2の配線

ポート

おわりに

外部割込み機能の確認を行いました. サンプルコードや情報が充実(中国語ではありますが)しているので, 使用経験のある他の中国製マイコンと比較して使いやすいマイコンだと感じました.

参考文献

[1] Xy_, VeriMake, ‘‘CH32V307教程 [第二集] [GPIO], ” https://verimake.com/d/150-ch32v307-gpio.

[2] WCH, ‘‘EXTI / EXTI0, ” https://github.com/openwch/ch32v307/blob/main/EVT/EXAM/EXTI/EXTI0/User/main.c.

中国製RISC-Vマイコン CH32V307V-EVT-R1 の開発環境構築とサンプルプログラムの実行

はじめに

中国の組み込み業界では西側諸国のプロセッサIP独占を打破するため, 積極的にRISC-VのプロセッサIP開発を行っています[1].

高機能な中国製RISC-Vマイコンを知るためにCH32V307V-EVT-R1の開発環境構築を行ったので, サンプルプログラムの実行までの手順をメモとして残します.

CH32V307V-EVT-R1について

CH32V307Vは32ビット 144MHz動作のRISC-Vマイコンであり, ハードウェアスタック領域と高速割り込みを備えています.

標準のRISC-Vと比較して, 割り込み応答速度が大幅に向上, 単精度浮動小数点命令セットが追加され, スタック領域, UART数, モータータイマー数が拡張されています. そして, USB2.0高速インターフェース(480Mbps)とPHYトランシーバーを内蔵しています[2].

CH32V307VCT6のブロック図

購入方法

CH32V307VはLCSCもしくはAliExpressで購入することが出来ます.

22年5月現在のLCSCでの価格はIC単体で¥562, 開発ボードで¥1510です. 円安の影響もあってか少し割高ですが, マイコンの入手性が悪い現在でも購入できました.

lcsc.com

lcsc.com

データシートのダウンロード

CH32V307Vの英語版データシートは参考文献3のリンクからダウンロードできます.

電気的特性はCH32V20x_30xDS0に記載されており, 周辺機能の説明, 使用方法, レジスタ構成についてはCH32FV2x_V3xRMに記載されています.

github.com

開発環境のダウンロードとインストール

以降の内容は参考文献4の内容をベースに記載しています.

一次情報を確認したい方は参考文献4をご確認ください. また、本記事では開発環境の機能の一部分のみ紹介するので, より詳細な使用方法については参考文献5をご参照ください.

CH32V307Vは無償で利用できるMounRiver Studioで開発できます. 参考文献6のリンクから公式サイトに移動し, 下記の図の赤枠で示すリンクをクリックしてインストーラをダウンロードしてください.

mounriver.com

ダウンロードページ

解凍したフォルダに格納されているexeファイルを起動してインストールを行います.

インストールフォルダのパスにスペースが入っているとインストールに失敗するので, 特にこだわりが無い場合はインストール先はデフォルトのままにしておく事をお勧めします.

フォルダの中身

プロジェクトファイルの作成

インストール後の最初の起動時は下記の画面が表示されるので, 赤枠で示す「New MounRiver Project」を選択します.

初期画面

(1)使用するマイコンのシリーズ(CH32V307)を選択します.

(2)詳細な形名(CH32V307VCT6)を選択します.

(3)Project Nameを入力します.

(4)保存するフォルダのパスを変更する場合はチェックを外し, フォルダを選択する

プロジェクトファイルの詳細

プログラムの作成

Lチカのサンプルプログラムを作成します.

Project ExplorerからUser→main.cを選択し, メインプログラムを表示します. 初期状態のプログラムはprintfのサンプルが記述されています.

main.cの表示

初期状態のプログラムにGPIOポートを初期化するコードを追加します. 下記のプログラムをint main(void)より前にコピぺして下さい.

/*******************************************************************************
* Function Name  : GPIO_INIT
* Description    : Initializes GPIOA.0
* Input          : None
* Return         : None
*******************************************************************************/
void GPIO_INIT(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
}

参考文献4より引用

main関数の中にIOポートを制御するコードを追加します. 初期状態で入力されているmain関数を削除して, 下記のコードをコピペしてください.

/*******************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Return         : None
*******************************************************************************/
int main(void)
{
    u16 i=0;

    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n",SystemCoreClock);

    GPIO_INIT();

    while(1)
    {
        Delay_Ms(250);
        GPIO_WriteBit(GPIOE, GPIO_Pin_11, (i==0) ? (i=1) : (i=0));
        GPIO_WriteBit(GPIOE, GPIO_Pin_12, (i==1) ? 0 : 1);
    }
}

参考文献4より引用

入力後の状態

プログラムのビルド

ビルドは下記の画像に示す部分をクリックすることで実行されます.

ビルド

ビルドを実行すると下記のエラーが発生する事があります. 「Save as UTF-8」を選択してください.

Save Problemsエラー

ビルドが成功するとConsoleに下記の表示され, プロジェクトフォルダの下のOBJフォルダにプロジェクトファイル名のHEXファイルが生成されます.

ビルド結果

マイコンへの書き込み

CH32V307-EVT-R1のWCH-LinkインターフェースをUSBケーブルでPCと接続し, CH32V307-EVT-R1の電源をONします.

CH32V307V-EVT-R1のインターフェース

下記の赤枠部分に示すDownloadボタンをクリックすると書き込みが開始します.

Downloadボタン

書き込みが完了するとConsoleに下記の表示されます.

書き込み完了

動作確認のための配線

WCH社が公開している下記の回路図に記載されている通り, CH32V307V-EVT-R1にはユーザーが動作確認に使用できるLEDが2個実装されています.

LEDを使用するにはジャンパ線などを使用してLEDのピンとマイコンピンを接続する必要があります.

CH32V307V-EVT-R1の回路図

github.com

作成したサンプルプログラムではPE11, PE12をON/OFFさせているので, 開発ボードのPE11とLED1, PE12とLED2をジャンパ線で接続します.

配線

配線完了後にWCH-LinkインターフェースをUSBケーブルでPCと接続し, CH32V307-EVT-R1の電源をONして動作を確認します.

動作確認

補足情報

書き込み設定の変更

Download設定を変更する場合はDownloadボタン横の三角マークを選択してConfigrationをクリックしてください.

Configuration

設定画面ではプログラムの削除, Verifyなどが選択できます.

設定画面

おわりに

開発環境の構築が容易かつEclipseベースの統合開発環境で開発できるので非常に使い製品でした. 本記事で紹介したCH32V307は高機能な製品でしたが, 低価格版のCH32V203であればIC単体を¥100程度で購入できるので価格を重視する趣味用途にもお勧めです.

参考文献

[1] 电子电路开发学习, ‘‘RISC-V当真是中国处理器产业的最后一次机会?, ” https://mp.weixin.qq.com/s?__biz=MzUzNzk2NTMxMw==&mid=2247484055&idx=1&sn=149af2be86e491c7e0fbfb139834aa84&chksm=fadfa4f9cda82defc37ed5f51b5b5ef7d944296201e104e668cb6402e09a44a8250eb4eda10d&scene=21#wechat_redirect.

[2] openwch, ‘‘32-bit Interconnected RISC-V MCU CH32V307, ” https://github.com/openwch/ch32v307/blob/main/README.md.

[3] openwch, ‘‘Datasheet and Reference Manual, ” https://github.com/openwch/ch32v307/tree/main/Datasheet.

[4] Xy_, VeriMake, ‘‘CH32V307教程 [第一集] [开发环境-MRS], ” https://verimake.com/d/12-ch32v307-mrs.

[5] DengCJ96, ‘‘MounRiver Studio 笔记(1.IDE安装), ” https://www.bilibili.com/read/cv10971816.

[6] MounRiver Studio, ‘‘Embedded RISC-V IDE, ” http://mounriver.com/download.

EAC規格と安全規則(TRCU)について

はじめに

EACマークは電子機器などによく表示されており目にする事の多いマークですが, CEマークなどと比べると馴染みが薄く日本語の情報が少ない規格です. そこで, EACマークについて調べる際に役立つ情報を残します.

EACマークとは

EEU加盟国間(ロシア、ベラルーシカザフスタンアルメニアキルギス)で合意された「強制認証」としての安全規則(Technical Regulations of Customs Union: TRCU)に適合していることを示すマークで, 欧州連合EU)のCEマークと異なりいまだ「自己宣言制度」は導入されておらず, 第三者認証機関(認証業務の代行機関:notified body)による試験, もしくは, 認証が求められています[1].

EACマークの規定

EACマークの形状やサイズについての法令は2つ有り, 参考文献[2]から原文を閲覧する事が出来ます.

EACマークには2種類のカラーバリエーションがありますが, 色による意味の違いは無く, 製品に印字した際に見やすい方を製造者が選択します.

f:id:hakura03:20211217235646j:plain
EACマーク(黒文字)

f:id:hakura03:20211217235719j:plain
EACマーク(白抜き文字)

また, EACマークのサイズは5㎜以上とする事が求められており, 下記の図の様に同じ高さと幅にする必要があります[3].

f:id:hakura03:20211218000700j:plain
EACマークのサイズ

安全規則(TRCU)の種類

安全規則とはEACマークの適合性を証明するために達成が求められる規則で, 第三者機関による確認を受けます.

2021年現在発行されている規則を下記の表に示します. あくまで21年現在の情報ですので正確な情報を確認した方は参考文献[4]から最新情報をご確認ください.

分類 規格名称 規格番号(ロシア語表記)
鉄道関連 鉄道車両の安全性について ТР ТС 001/2011
鉄道関連 高速鉄道の安全性について ТР ТС 002/2011
鉄道関連 鉄道輸送インフラの安全性について ТР ТС 003/2011
自動車関連 交通安全 ТР ТС 014/2011
自動車関連 車輪付き車両の安全について ТР ТС 018/2011
自動車関連 農業トラクター、林業ラクター、及び同牽引車の安全 ТР ТС 031/2012
船舶関連 小型船舶の安全 ТР ТС 026/2012
設備・プラント 低電圧機器の安全性について(LVD) ТР ТС 004/2011
設備・プラント 機械設備の安全性について ТР ТС 010/2011
設備・プラント エレベータの安全性 ТР ТС 011/2011
設備・プラント 技術的手段の電磁適合性(EMC) ТР ТС 020/2011
設備・プラント エネルギー消費装置のエネルギー効率に関する要件について ТР ЕАЭС 048/2019
防爆規制 花火の安全性について ТР ТС 006/2011
防爆規制 爆発危険環境下で稼働する設備の安全 ТР ТС 012/2011
防爆規制 自動車燃料、航空燃料、軽油、船舶燃料、ケロシン重油の安全性 ТР ТС 013/2011
防爆規制 気体燃料で駆動する設備の安全 ТР ТС 016/2011
防爆規制 爆発物とその製品の安全 ТР ТС 028/2012
防爆規制 潤滑剤、潤滑油、及び特殊溶液の安全 ТР ТС 030/2012
防爆規制 過度の圧力下で動作する機器の安全性 ТР ТС 032/2013
防爆規制 液化炭化水素ガス燃料の安全 ТР ЕАЭС 036/2016
防爆規制 液化炭化水素ガス燃料の安全 ТР ЕАЭС 039/2016
防爆規制 火災安全および消火を確保する手段の要件 ТР ЕАЭС 043/2017
防爆規制 石油の輸送及び利用に関する安全 ТР ЕАЭС 045/2017
防爆規制 輸送および(または)使用のために準備された天然燃料ガスの安全性 ТР ЕАЭС 046/2018
化学全般 汎用樹脂等の梱包材料の安全 ТР ТС 005/2011
化学全般 香水、化粧品の安全 ТР ТС 009/2011
化学全般 軽工業品の安全 ТР ТС 017/2011
化学全般 電気・無線電子製品における有害物質使用制限電気製品、及び無線製品に組み込まれる危険物質に関わる制限規定(RoHS) ТР ЕАЭС 037/2016
化学全般 化学品の安全(REACH) ТР ЕАЭС 041/2017
食品, 他 穀物の安全 ТР ТС 015/2011
食品, 他 食品の安全 ТР ТС 021/2011
食品, 他 食品表示 ТР ТС 022/2011
食品, 他 フルーツ、野菜ジュースの安全 ТР ТС 023/2011
食品, 他 油脂製品の安全 ТР ТС 024/2011
食品, 他 個別特定食品(ダイエット治療、ダイエット予防等)の安全 ТР ТС 027/2012
食品, 他 食品添加物、香料、機能補助剤の安全 ТР ТС 029/2012
食品, 他 食肉、肉加工製品の安全 ТР ТС 034/2013
食品, 他 牛乳、及び乳製品の安全 ТР ТС 033/2013
食品, 他 タバコ製品の安全 ТР ТС 035/2014
食品, 他 魚、及び水産物の安全 ТР ЕАЭС 040/2016
食品, 他 パッケージ飲料水(ミネラルウオーター等)の安全 ТР ЕАЭС 044/2017
食品, 他 アルコール製品の安全 ТР ЕАЭС 047/2018
その他 未成年者・児童向け製品の安全 ТР ТС 007/2011
その他 玩具の安全 ТР ТС 008/2011
その他 個人保護用具の安全性 ТР ТС 019/2011
その他 家具の安全 ТР ТС 025/2012
その他 アトラクションの安全 ТР ЕАЭС 038/2016
その他 児童公園の遊具・設備類の安全 ТР ЕАЭС 042/2017

安全規則(TRCU)原文の確認方法

安全規則(TRCU)は参考文献[4]から取得する事も出来ますが, PDF化された文書(ロシア語)のみの提供で, 日本人が読み解くのは困難です.
しかし, コーデックス(参考文献[5]のサイト)ではロシア国内の法律をWebページ上で公開しているので, ブラウザの翻訳機能を使用することで日本語で閲覧する事が出来ます.

コーデックスの利用方法

コーデックスの利用方法は簡単でWebページ上の検索バーに法律の名称もしくは番号を入力して検索するだけです. 注意点としてはロシア語でしか検索する事ができないので, 「TRCU」を検索する際には「 ТР ТС 」などロシア語表記で検索する必要があります.

「安全規則(TRCU)の種類」の章に記載した表の右側にロシア語表記の規格名称を記入したので検索する際はその部分をコピペして検索すると効率的に探すことが出来ると思います.

f:id:hakura03:20211218095004p:plain
コーデックス

おわりに

EACマークの概要と安全規則(TRCU)の情報についてまとめました. しかし, これらの情報は21年時点での物なので, 将来的にEACマークの要件が変わったり, TRCUに追加の規則が加わる可能性も十分にあります. 本ブログに記載されている情報を鵜呑みにせず, 参考文献として記載させて頂いているページなどから正確な情報を確認して下さい.

参考文献

[1] 独立行政法人日本貿易振興機構 , ‘‘GOST-R(ロシア国家標準規格)認証取得:ロシア向け輸出, ” https://www.jetro.go.jp/world/qa/04J-110101.html.

[2] ユーラシア経済連合 , ‘‘Единый знак обращения продукции на рынке, ” http://www.eurasiancommission.org/ru/act/texnreg/deptexreg/coordination/Pages/EAC.aspx.

[3] ユーラシア経済連合 , ‘‘​Положение о едином знаке обращения продукции на рынке государств - членов Таможенного союза, ” http://www.eurasiancommission.org/ru/act/texnreg/deptexreg/coordination/Documents/PologenieEAC.pdf.

[4] ユーラシア経済連合 , ‘‘​Технические регламенты, вступившие в силу, ” http://www.eurasiancommission.org/ru/act/texnreg/deptexreg/tr/Pages/TRVsily.aspx.

[5]Акционерное общество"Информационная компания "Кодекс" , ‘‘​Кодекс , ” https://docs.cntd.ru/.

UL規格の概要

はじめに

近年様々な企業でULの不正取得などが話題になっていますが, ULの内容について自分が正確に把握できていないと感じたので調べた内容をまとめます.

ULとは

UL はアメリカの政府機関ではなく, 「公共安全」をミッションとし、安全規格の開発とそれに準じた製品試験・認証を活動の核としつつ、安全な世界作りに奉仕する民間の組織です[1].

民間の認証機関であるULが米国内で効力を持つ理由は, 安全規格を取りまとめる米国労働安全衛生当局(OSHA) が認定した試験機関であるからです[2].

米国における安全性審査について

アメリカ国内の労働環境で使われる製品を製造する製造者は, OSHAによって定められている電気安全規格に適合する必要があります. 自社製品が上記の規格に適合していることを裏づけするために, 製造者は国家指定認定機関(NRTL)の認証を受けなければなりません[3].

OSHAが認定している認証機関はULの他にもあり, 参考文献4を確認すると2021年8月現在は18の団体がNRTLとして認められているようです.

ULマークの形状と意味

ULマークの形状は流通する国や規格で異なるため本ブログでは代表的な6種類のマークを紹介します. マークについてより詳細に知りたい方は参考文献5をご参照ください.

f:id:hakura03:20210810133501p:plain
代表的なULマークの一覧

リスティング・マーク

リスティング・マークは, 一般的に最終製品につけられるマークで, いかなる条件のもとで使われても安全であるように製作された製品や部品がこの対象となります.

一般消費者も使用することを考慮して広範囲にわたって安全性について調査, 試験が実施され, 合格するとUL が発行する製品別リスト(グリーンブック)によって一般に公表されます[6].

レコグナイズド・コンポーネント・マーク

レコグナイズド・コンポーネント・マークは, 単体では機能しない, あるいはその機能が制限されているコンポーネント(部品・材料)に対するULの認証マークです[7]. 試験に合格するとULが発行する登録部品リスト(イエローブック)に記載されます[6].

レコグナイズド・コンポーネントには, Conditions of Acceptability(部品使用許可条件)が定められており, これを考慮して最終製品に組み込んだり, 使用する必要があります[7].

クラシフィケーション・マーク

クラシフィケーション・マークとは, 製品固有の性質を検査し, 特定条件下での使用が可能かどうか, また予測可能な事故に耐えうるかどうかを評価, 認証されたことを示すマークです[7]. 医療機器や工業用器具, 防火機器などが主に対象となります.

C-ULマーク(アメリカ‐カナダ相互認証)

アメリカとカナダには、MRA (Mutual Recognition Agreement)という安全に関する規格の相互認証制度があります.

ULにてカナダ向けに製品安全認証を受けた場合、CSA規格に適合していることを意味するC-ULマークを製品上に表示でき, カナダ国内ではCSA認証と同等に扱われます[8].

プロシージャ

製品の評価が完了した際に、プロシージャと呼ばれる文書が発行されます. プロシージャに記載されている内容と異なる製品を製造, 販売した場合にUL違反となります.

この文書には製品の継続的な適合性を検証するための要求事項が規定されており, ULの工場検査はこのプロシージャの内容に従い行われます[9]. プロシージャにどの様な内容が記載されるかを詳細に知りたい方は参考文献10のP103~P110をご確認ください.

UL規格の調べ方

UL取得の際に実施する試験の規格についてはULの公式サイトから無料で確認することができます[11]. 企業に所属している方はサイトに登録することでデータをダウンロードすることが可能ですが, 個人利用の場合はWEB上での閲覧のみになります.

企業向けのサイト使用方法は参考文献12を個人向けサイトの使用方法は参考文献13をご参照ください.

企業に所属している方向け

www.ulstandards.com

個人で規格を閲覧したい方向け

www.shopulstandards.com

おわりに

UL規格の概要をまとめました. ULマークの違いなど自分の知識があいまいになっていた部分を再確認する良い機会でした.

参考文献

[1] 株式会社 UL Japan, ‘‘1-1. ULについて・UL規格全般, ” https://japan.ul.com/faq-landing/1-1-ul%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%83%BBul%E8%A6%8F%E6%A0%BC%E5%85%A8%E8%88%AC/.

[2] 日本認証株式会社, ‘‘世界各国の規制・認証制度 北米, ” https://www.japan-certification.com/certification/world/north_america/.

[3]テュフズード, ‘‘NRTLが重要な理由, ” https://www.tuvsud.com/ja-jp/services/product-certification/nationally-recognized-testing-laboratories.

[4]Occupational Safety and Health Administration, ‘‘Current List of NRTLs, ” https://www.osha.gov/nationally-recognized-testing-laboratory-program/current-list-of-nrtls.

[5]UL, ‘‘UL Mark Artwork, ” https://marks.ul.com/about/ul-listing-and-classification-marks/downloadable-ul-marks/.

[6] 富士電機株式会社, ‘‘UL 規格認定取得機器, ” https://www.fujielectric.co.jp/fcs/pdf/standard/62B2-J-0009_ul.pdf.

[7] 株式会社 UL Japan, ‘‘1-2. 安全試験・認証, ” https://japan.ul.com/faq-landing/1-2-%e5%ae%89%e5%85%a8%e8%a9%a6%e9%a8%93%e3%83%bb%e8%aa%8d%e8%a8%bc/.

[8] 株式会社KEYENCE, ‘‘第1章 各国の製品安全規制について 北米, ” https://www.keyence.co.jp/global/special/other/export/products/03/.

[9] 株式会社 UL Japan, ‘‘2-1. フィールドサービス (工場検査), ” https://japan.ul.com/faq-landing/2-1-%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9-%E5%B7%A5%E5%A0%B4%E6%A4%9C%E6%9F%BB/.

[10] 株式会社 UL Japan, ‘‘002 申請ガイド - UL Japan, ” https://japan.ul.com/wp-content/uploads/sites/27/2014/03/0_application_guide-jpn.pdf.

[11] 株式会社 UL Japan, ‘‘UL規格提供サイトのご案内, ” https://japan.ul.com/resources/sccl/.

[12] 株式会社 UL Japan, ‘‘Standards Certification Customer Library (UL規格提供サイト) 登録手順, ” https://japan.ul.com/wp-content/uploads/sites/27/2014/06/0_sccl.pdf.

[13] 株式会社 UL Japan, ‘‘オンライン UL 規格閲覧手順, ” https://japan.ul.com/wp-content/uploads/sites/27/2019/11/1_Access_to_UL_Standards_Sales_Site.pdf.

ARM Cortex-M0搭載 PIC32CMでLチカ

はじめに

PIC32CMはマイクロチップ・テクノロジー社が販売しているARM Cortex-M0搭載のマイコンです[1]. このマイコンの特徴は2016年に買収されたAtmel社のSAMファミリをベースに開発されているためSAM C2xシリーズとピン配置などで互換性がある事です. また, 機能面はSAM C2xシリーズとほぼ同等ですがモータ制御機能などが追加されています[2].

開発環境

開発に使用するソフトウェアは下記のとおりです。導入方法については参考文献の[3], [4]をご参照ください.

・MPLAB X IDE統合開発環境

・MPLAB XC32:32bit用C言語コンパイラ

・MPLAB Harmony v3:ソースコード ジェネレータ

開発に使用するハードウェアは下記のとおりです. 今回はマイコン単品を購入してPIC KIT4で書き込みをおこなう方法で開発を行いましたが, PIC32CMの評価用ボードを使用すればPIC KIT4は必要ありません[5].

・PIC32CM1216MC00048:マイコン本体

・PIC KIT4:デバッガ/プログラマー

PIC KIT4とPIC32CMの接続

PIC KIT4とPIC32CMの通信はCORTEX SWD方式でおこなわれます[6]. SWDで使用するポートは下記の通りです[7].

f:id:hakura03:20210725124111p:plain
PIC KIT4の配線

f:id:hakura03:20210725135530j:plain
接続表

プロジェクトファイル作成

MPLAB X IDE, MPLAB XC32, MPLAB Harmony V3が導入されている事を前提に説明をします. File→New Project...を選択するとプロジェクト選択画面が出るので「32-bit MPLAB Harmony 3 Project」を選択します.

f:id:hakura03:20210725134219j:plain
プロジェクトファイル作成1

「Framework Selection」については変更の必要がないので次へを選択し, 「Project Settings」でプロジェクトファイルの名前を記入して次へを選択します.

f:id:hakura03:20210725134554j:plain
プロジェクトファイル作成2

「Configuration Settings」で「Target Device」を選択します. 使用するデバイスは「PIC32CM1216MC00048」なのでそれを選択します.

f:id:hakura03:20210725135134j:plain
プロジェクトファイル作成3

プロジェクトファイルの作成は以上で完了です。

次にPIC KIT4を使用するために設定の変更をおこないます. PCにPIC KIT4を接続した状態でProduction → Set Project Configuration → Customize...を選択します. 「Connected Hardware Tool」の設定が標準では「Simulator」になっているので「PICkit 4-SN:BURxxxxxxx」に変更します.

f:id:hakura03:20210725140612j:plain
プロジェクトファイル作成4

Harmony v3を使用したコード生成とプログラムの作成

Tools→ Embedded → MPLAB Harmony 3 Configuratorを選択します. 「MPLAB Harmony Launcher」,「Configuration Database Setup」の画面が表示されるのでどちらも「Launch」を選択します. するとMPLAB Harmony Configuratorのウィンドウが表示されます.

f:id:hakura03:20210725142339j:plain
Harmony v3 設定1

f:id:hakura03:20210725142402j:plain
Harmony v3 設定2

f:id:hakura03:20210725143945j:plain
Harmony v3 設定3

MPLAB Harmony ConfiguratorのTools→Pin Configurationを選択すると「Pin Settings」の画面が表示されるので, 今回はPA00を使用する設定をおこないます. 「Function」をGPIO, 「Direction」をOUT, 「Custom Name」をGPIO_PA00_LEDに設定します. 「Custom Name」については必ずしも変更する必要はありません.

編集が完了したら×ボタンで「Pin Settings」の画面を消してください. 「Pin Settings」の画面を消すと「Pin Table」と「Pin Diagram」の画面が表示されるので設定した内容が正しく反映されていることを確認して×ボタンで消してください.

f:id:hakura03:20210725144638j:plain
出力ピンの設定

f:id:hakura03:20210725145258j:plain
出力ピンの設定2

f:id:hakura03:20210725145322j:plain
出力ピンの設定3

次にLEDを点滅させるため, タイマ割り込みの設定をおこないます.

「Available Components」のPeripherais → TC → TC0を選択し, Project Graphに表示されるTC0を選択します.

「Select Prescaler」をGCLK_TC/1024, 「Time」を1,000に設定し, 「Enable Timer Period Interrupt」にチェックを入れます.

f:id:hakura03:20210725180031j:plain
タイマ割り込み設定

以上でHarmony v3を使用した設定は完了です.

「Generate Code」をクリックしプログラムを生成します.

f:id:hakura03:20210725180552j:plain
プログラム生成

次にプログラムの作成をおこないます.

「main.c」のファイルに赤枠で囲った部分のコードを追加します. プログラムの詳細は参考文献[8]で解説されているので, 詳細を知りたい方はそちらをご確認ください.

以上でプログラムの作成は完了したのでマイコンに書き込みLEDが点滅することを確認できれば完成です.

f:id:hakura03:20210725181024j:plain
プログラム

f:id:hakura03:20210725200626g:plain
動作確認結果

おわりに

PIC32CMを使ってみて「Harmony v3」に慣れれば効率的なプログラミングが可能だと感じました.

しかし, 「Harmony v3」を使用せずに「Standalone Project」で作成しようとすると, レジスタ関連を定義するヘッダファイルをすべて自分で探して参照する必要があり非常に面倒です. 従来のPICマイコンのように「xc.h」を読み込めばプログラムを作成できるような手軽さはなく「Harmony v3」の使用が前提となっている部分は改善してほしいと感じました.

参考文献

[1] MICROCHIP, ‘‘PIC32CM1216MC00048, ” https://www.microchip.com/wwwproducts/en/PIC32CM1216MC00048.

[2]CQ出版社, ‘‘トランジスタ技術2021年6月号, ” https://toragi.cqpub.co.jp/magazine/magazine-577/.

[3]サヌキテックネット, ‘‘MPLAB X IDEのインストール(Windows編), ” https://sanuki-tech.net/pic/development/install-mplab-x-ide/section/1/.

[4]MPLAB X IDE, XC16,XC8 コンパイラの使い方, ‘‘MPLAB Harmony v3 (1) ダウンロード, ” http://blog.livedoor.jp/mplab/archives/1076133535.html.

[5] MICROCHIP, ‘‘PIC32CM MC00 Curiosity Nano Evaluation Kit, ” https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/EV10N93A#additional-summary.

[6] MICROCHIP, ‘‘PIC32CM MC00 Family Data Sheet, ” https://ww1.microchip.com/downloads/en/DeviceDoc/PIC32CM-MC00-Family-Datasheet-DS60001638B.pdf.

[7] MICROCHIP, ‘‘MPLAB® PICkit™ 4 インサーキット デバッガ ユーザガイド, ” http://ww1.microchip.com/downloads/jp/DeviceDoc/50002751C_JP.pdf.

[8]MPLAB X IDE, XC16,XC8 コンパイラの使い方, ‘‘MPLAB Harmony v3 (9) 割り込み関数の記述(コールバック関数), ” http://blog.livedoor.jp/mplab/archives/1077465285.html.