PlatformIOで40円マイコン CH32V003J4M6を動かす

最近よく見かける、40円程度で入手できる安いマイコン
CH32V003J4M6をPlatwormIOのarduino環境で動かしてみました。
ちなみにエミュレータのソフトがWindows用しか用意されていないようなので、
下記ではWindowsでのみの対応となります。

また、現時点ではAnalogRead(),Serial,new, mallocなど、
使用できない関数もたくさんあります。

### 用意するもの
1\. [CH32V003J4M6](https://akizukidenshi.com/catalog/g/gI-18062/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/e744621f-9c99-5680-b613-b5665828833c.png)
2\. [SOP8 DIP変換基板](https://akizukidenshi.com/catalog/g/gP-05154/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/5078ae53-e1a0-7002-6cc1-9f3482dbd8a5.png)
3\. [WCH=LinkEエミュレータ](https://akizukidenshi.com/catalog/g/gM-18065/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/463b886a-ea64-106e-fa60-a3d79930cb8c.png)
4\.ブレッドボード

　書き込み装置（エミュレータ）を合わせても1000円以下です。安い！
　（2023/11月現在）


### 書き込み準備
まず、エミュレータを書き込みができる状態にする必要があります。

1\. https://www.wch.cn/downloads/WCH-LinkUtility_ZIP.html
からUtilityをダウンロードして解凍

2\. WCH-LinkUtility.exe を起動。 **不用意にボタンを押さないでください(後述)** 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/7391b8d1-39b3-53f4-832a-cc8e937491ac.png)

3\.下のほうにある、Active WCH-Link Mode の横の[Get]ボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/5a050790-2765-f58b-fc56-066126f07932.png)

4\. モードが WCH-LinkRV 以外になっていた場合は WCH-LinkRV に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/39f43ad7-19f4-3436-0cbf-2a996ffd73a6.png)

5\. [Set]ボタンを押して Succeed! の表記が出たらUtilityを終了します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/0a8b9cac-81c1-5ccb-a700-4fa24de8e6ce.png)
**この時、ヘタなボタンを押すとupdateを促され、うかつにOKするとPCからエミュレータが認識されなくなります。ご注意ください。** 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/e13c8a04-1485-827c-8ccb-8507ec46a7d2.png)

### PlatformIOの準備
~~[こちら](https://github.com/Community-PIO-CH32V/platform-ch32v/tree/develop)で用意されているものを使用します。~~

1\. まず、PlatformIOで適当なプロジェクトを用意します。
　~~board,frameworkは適当に選んで構いません。~~


[追記]
 ```
 platform = ch32v
board = genericCH32V003J4M6
 ```
が選択できるようになりました。 


~~2\.[readme](https://github.com/Community-PIO-CH32V/platform-ch32v/tree/develop#readme)にあるように、platform.iniを書き換えます。~~
```[platform.ini]
; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:genericCH32V003J4M6]
;platform = https://github.com/Community-PIO-CH32V/platform-ch32v.git #ch32v
platform = ch32v
board = genericCH32V003J4M6
framework = arduino
```

### 書き込み準備
[こちら](https://kanpapa.com/today/2023/06/blink-risc-v-ch32v003-arduino.html)の記事を参考に、エミュレータとマイコンを接続します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/379e1ad7-19db-c4bc-9c32-ed54bb4ff023.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/25f3e4ca-76b7-5308-4315-7c79dcb8c526.png)

### プログラム作成＆書き込み
準備ができたら適当なプログラムを用意します。

```
#include <Arduino.h>

// ___________
//1|A2   SWIO|8
//2|GND    C4|7
//3|--     C2|6
//4|VDD    C1|5
// ~~~~~~~~~~~
#define LED1 C2
#define LED2 C4

void setup(){
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
}

void loop(){
  digitalWrite(LED1, HIGH);
  digitalWrite(LED2, LOW);
  delay(1000);
  digitalWrite(LED1, LOW);
  digitalWrite(LED2, HIGH);
  delayMicroseconds(50000);
}


```

PlatformIOのUploadボタンを押して下記のように出力されれば
無事書き込み終了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/88ed8f3d-acd9-254c-32b1-daa64dc7143d.png)

https://www.youtube.com/watch?v=puPyi9fhmJ4



超音波センサーも試してみました。
```
#include <Arduino.h>

// ___________
//1|A2   SWIO|8
//2|GND   PC4|7
//3|--    PC2|6
//4|VDD   PC1|5
// ~~~~~~~~~~~
//!!Serialを使用すると次回から書き込みできなくなるので注意
#define LED_PIN C4
#define MOTOR_PIN A2
#define TRIG_PIN C1
#define ECHO_PIN C2
#define TRIG_US (15)
#define TIMEOUT_US (100000)
#define MAX_DIST_MM (4000)

bool isOn=false;
uint32_t m_sumMillis;

unsigned long getPulseMicros(uint8_t _trigPin, uint8_t _echoPin, unsigned long timeout);

void setup() {
  isOn = false;
  m_sumMillis = 0;
  pinMode(LED_PIN, OUTPUT);
  pinMode(MOTOR_PIN, OUTPUT);
  pinMode(TRIG_PIN,OUTPUT);
  pinMode(ECHO_PIN,INPUT);
}

void loop() {
  unsigned long pulseMicros = getPulseMicros(TRIG_PIN, ECHO_PIN, TIMEOUT_US);
  if(pulseMicros>0){
    digitalWrite(LED_PIN, HIGH);
    digitalWrite(MOTOR_PIN, HIGH);
    delay(10);
    digitalWrite(LED_PIN, LOW);
    digitalWrite(MOTOR_PIN, LOW);
    delayMicroseconds(pulseMicros * 50);
  }

  delayMicroseconds(1000);
}

unsigned long getPulseMicros(uint8_t _trigPin, uint8_t _echoPin, unsigned long timeout)
{
    //digitalWrite(TRIG_PIN, LOW);
    //delayMicroseconds(TRIG_US);
    digitalWrite(TRIG_PIN, HIGH);
    delayMicroseconds(TRIG_US);
    digitalWrite(TRIG_PIN, LOW);
    unsigned long start = micros();
    unsigned long end = start+TIMEOUT_US;
    long timer = (long)(end-start);
    unsigned long pulseLen = 0;
    unsigned long pulseStart = 0;
    while (digitalRead(_echoPin) != HIGH && timer>0) {
      delayMicroseconds(1);
      timer = (long)(end-micros());
    }
    if(timer<=0){
      return 0;
    }
    pulseStart = micros();
    while (digitalRead(_echoPin) == HIGH && timer>0) {
      pulseLen = micros() - pulseStart;
      timer = (long)(end-micros());
    }
    if(timer<=0){
      return 0;
    }else{
      return pulseLen;
    }
}

```
https://youtu.be/N9lr7IzgLVc


### ピンアサインについて
CH32V003J4M6の8本あるピンのうち、書き込みに使用する
**8ピンを使用すると次回から書き込みができなくなります。**

[ＷＣＨ－ＬｉｎｋＥエミュレーターの質問と回答](https://akizukidenshi.com/catalog/faq/goodsfaq.aspx?goods=M-18065)

マイコンをリセットすれば再度書き込みができるようになるようですが、
前述のように、Utilityで書き込み設定変更以外のことを行うと
ファームの書き換えが発生してしまい、PCから認識されなくなります。
Serialも8ピンを使用しているようで、書きこみができなくなりました。

また、3ピンについても使用できるピンアサインがわからず使用できていません。
ピンアサインについては
```.platformio/packages/framework-arduinoch32v003/variants/CH32V003/pins_arduino.h```
にあるのですが、積極的に適当なピンアサインを試してみることはしていません。
[データシート](https://akizukidenshi.com/download/ds/wch/CH32V003.pdf)とピンアサインが微妙に違うし、
**うっかり8ピンを使ってしまうと悲しいので。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/ae6f4d91-dce8-14ce-2968-5d6828f6f99c.png)


```
#pragma once

// GPIO A1~A2
static const uint8_t A1 = 0u;
static const uint8_t A2 = 1u;
// GPIO C0~C7
static const uint8_t C0 = 2u;
static const uint8_t C1 = 3u;
static const uint8_t C2 = 4u;
static const uint8_t C3 = 5u;
static const uint8_t C4 = 6u;
static const uint8_t C5 = 7u;
static const uint8_t C6 = 8u;
static const uint8_t C7 = 9u;
// GPIO D0~D7
static const uint8_t D0 = 10u;
static const uint8_t D1 = 11u;
static const uint8_t D2 = 12u;
static const uint8_t D3 = 13u;
static const uint8_t D4 = 14u;
static const uint8_t D5 = 15u;
static const uint8_t D6 = 16u;
static const uint8_t D7 = 17u;
```

### 以上
現場からは以上です。

PCから認識しなくなってしまったエミュレータや
書き込みができなくなってしまったマイコンを回復させる手段
を知って言いる方がいたら教えてください！