前回に引き続き、ch32funのライブラリーの1つであるGPIOライブラリーを使用してADCに挑戦して行きたいと思います。
GPIOライブラリーを使用するには、"ch32v003_GPIO_branchless.h"をインクルードすることと、Makefileの中に”CH32FUN=$(HOME)/ch32fun/ch32fun”を設定することです。
では早速GPIOを使用したADCのプログラムを書いてみましょう。今回は、ADCを使用したSW入力をやってみたい思います。
使用したデバイスは、CH32V003J4M6 8pinタイプです。
PD6(1pin)に入力される電圧を、10Kオームとスイッチを介して接続される抵抗の分圧比を読み込むことによりIFで範囲をして、押されたSWを特定するものです。押されたスイッチにより、2つのLEDで動作を確認します。
回路図は下記のとおりです。
PC1(5pin)、PC2(6pin)をLED出力ポートに、PD6(1pin)をアナログ入力ポートに定義
// 該当LEDと出力PINとの関連付け
#define LED1 GPIOv_from_PORT_PIN(GPIO_port_C, 1) //C1 port output
#define LED2 GPIOv_from_PORT_PIN(GPIO_port_C, 2) //C2 port output
#define ADC_IN1 GPIOv_from_PORT_PIN(GPIO_port_D, 6) //D6 port ADC
C、Dポートを活性化し、PC1/PC2を出力ポートに、PD6ポートをアナログ入力として設定し、ADCを初期化します。
SystemInit(); // デバイスの初期化
GPIO_port_enable(GPIO_port_C); // gpio Cポートを活性化
GPIO_port_enable(GPIO_port_D); // gpio Dポートを活性化
GPIO_pinMode(LED1, GPIO_pinMode_O_pushPull, GPIO_Speed_10MHz); // gpioの補給クロックとpinを出力に設定
GPIO_pinMode(LED2, GPIO_pinMode_O_pushPull, GPIO_Speed_10MHz); // gpioの補給クロックとpinを出力に設定
GPIO_pinMode(ADC_IN1, GPIO_pinMode_I_analog, GPIO_Speed_In); // gpioの補給クロックとpinをアナログ入力に設定
GPIO_ADCinit();
LED1、LED2を相互点滅するための"tenmetu_led”の関数を作成します。
void tenmetu_led(void){
for(uint8_t i=0; i <= 4;i++){
GPIO_digitalWrite(LED1, high); // 該当のpin出力をHレベルにする
GPIO_digitalWrite(LED2, low); // 該当のpin出力をLレベルにする
Delay_Ms( 200 );
GPIO_digitalWrite(LED1, low); // 該当のpin出力をLレベルにする
GPIO_digitalWrite(LED2, high); // 該当のpin出力をHレベルにする
Delay_Ms( 200 );
}
GPIO_digitalWrite(LED1, low); // 該当のpin出力をLレベルにする
GPIO_digitalWrite(LED2, low); // 該当のpin出力をLレベルにする
}
入力されたADCの分圧比をIF文で分類します。分類した結果をnamberに格納します。
analog_data = GPIO_analogRead(GPIO_Ain6_D6); // 該当のpinにアナログ入力する
// printf("data = %d \n\r",analog_data);
if(analog_data >= 911 ){
number=0;
} else if(analog_data <= 910 && analog_data >= 756){
number=1;
} else if(analog_data <= 755 && analog_data >= 606){
number=2;
} else if(analog_data <= 605 && analog_data >= 421){
number=3;
} else if(analog_data <= 421 && analog_data >= 258){
number=4;
} else if(analog_data <= 257){
number=5;
}
どのSWも押されていなければ(number=0)待機に、それ以外は、numberに格納された値に応じてswitch文で振り分けLED1、LED2の動作を行います。
if ( number != 0){
switch(number){
case 1: GPIO_digitalWrite(LED1, high); GPIO_digitalWrite(LED2, high); break; //LED1or LED2 点灯
case 2: GPIO_digitalWrite(LED1, low); GPIO_digitalWrite(LED2, high); break; //LED2 点灯
case 3: GPIO_digitalWrite(LED1, high); GPIO_digitalWrite(LED2, low); break; //LED1 点灯
case 4: GPIO_digitalWrite(LED1, low); GPIO_digitalWrite(LED2, low); break; //LED1 or LED2 消灯
case 5: tenmetu_led();break; //LED1 LED2 交互点滅
default:break;
}
}
全体のプログラムは下記の通りです。
//CH32V003J4M6 8pin GPIO LED ADC SW プログラム
#include "ch32fun.h"
#include "ch32v003_GPIO_branchless.h"
#include <stdio.h>
#include <stdint.h>
// 該当LEDと出力PINとの関連付け
#define LED1 GPIOv_from_PORT_PIN(GPIO_port_C, 1) //C1 port output
#define LED2 GPIOv_from_PORT_PIN(GPIO_port_C, 2) //C2 port output
#define ADC_IN1 GPIOv_from_PORT_PIN(GPIO_port_D, 6) //D6 port ADC
void tenmetu_led(void){
for(uint8_t i=0; i <= 4;i++){
GPIO_digitalWrite(LED1, high); // 該当のpin出力をHレベルにする
GPIO_digitalWrite(LED2, low); // 該当のpin出力をLレベルにする
Delay_Ms( 200 );
GPIO_digitalWrite(LED1, low); // 該当のpin出力をLレベルにする
GPIO_digitalWrite(LED2, high); // 該当のpin出力をHレベルにする
Delay_Ms( 200 );
}
GPIO_digitalWrite(LED1, low); // 該当のpin出力をLレベルにする
GPIO_digitalWrite(LED2, low); // 該当のpin出力をLレベルにする
}
int main() {
SystemInit(); // デバイスの初期化
GPIO_port_enable(GPIO_port_C); // gpio Cポートを活性化
GPIO_port_enable(GPIO_port_D); // gpio Dポートを活性化
GPIO_pinMode(LED1, GPIO_pinMode_O_pushPull, GPIO_Speed_10MHz); // gpioの補給クロックとpinを出力に設定
GPIO_pinMode(LED2, GPIO_pinMode_O_pushPull, GPIO_Speed_10MHz); // gpioの補給クロックとpinを出力に設定
GPIO_pinMode(ADC_IN1, GPIO_pinMode_I_analog, GPIO_Speed_In); // gpioの補給クロックとpinをアナログ入力に設定
GPIO_ADCinit();
uint16_t analog_data;
uint8_t number;
printf("Start GPIO !\n\r");
GPIO_digitalWrite(LED1, low); // 該当のpin出力をHレベルにする
while(1){
Delay_Ms( 15 );
analog_data = GPIO_analogRead(GPIO_Ain6_D6); // 該当のpinにアナログ入力する
// printf("data = %d \n\r",analog_data);
if(analog_data >= 911 ){
number=0;
} else if(analog_data <= 910 && analog_data >= 756){
number=1;
} else if(analog_data <= 755 && analog_data >= 606){
number=2;
} else if(analog_data <= 605 && analog_data >= 421){
number=3;
} else if(analog_data <= 421 && analog_data >= 258){
number=4;
} else if(analog_data <= 257){
number=5;
}
if ( number != 0){
switch(number){
case 1: GPIO_digitalWrite(LED1, high); GPIO_digitalWrite(LED2, high); break; //LED1or LED2 点灯
case 2: GPIO_digitalWrite(LED1, low); GPIO_digitalWrite(LED2, high); break; //LED2 点灯
case 3: GPIO_digitalWrite(LED1, high); GPIO_digitalWrite(LED2, low); break; //LED1 点灯
case 4: GPIO_digitalWrite(LED1, low); GPIO_digitalWrite(LED2, low); break; //LED1 or LED2 消灯
case 5: tenmetu_led();break; //LED1 LED2 交互点滅
default:break;
}
}
}
}
上記プログラムをGPIO_adc_sw.cとして保存します。
all : flash
TARGET:=GPIO_adc_sw
CH32FUN=$(HOME)/ch32fun/ch32fun
TARGET_MCU?=CH32V003
include ~/ch32fun/ch32fun/ch32fun.mk
flash : cv_flash
clean : cv_clean
Makefileとして保存します。
funconfig.hを~/ch32fun/examples/GPIOからコピーします。何も編集はしません。
これで必要なファイルが揃いました。
~/prog/ch32v003/ch32fun/GPIO_ADC_SW $ ls
GPIO_adc_sw.c Makefile funconfig.h
WCH-LinkEをusbに差して、makeします。
~/prog/ch32v003/ch32fun/GPIO_ADC_SW $ make
riscv64-unknown-elf-gcc -E -P -x c -DTARGET_MCU=CH32V003 -DMCU_PACKAGE=1 -DTARGET_MCU_LD=0 -DTARGET_MCU_MEMORY_SPLIT= /home/rika/ch32fun/ch32fun/ch32fun.ld > /home/rika/ch32fun/ch32fun/generated__.ld
riscv64-unknown-elf-gcc -o GPIO_adc_sw.elf /home/rika/ch32fun/ch32fun/ch32fun.c GPIO_adc_sw.c -g -Os -flto -ffunction-sections -fdata-sections -fmessage-length=0 -msmall-data-limit=8 -march=rv32ec -mabi=ilp32e -DCH32V003 -static-libgcc -I/usr/include/newlib -I/home/rika/ch32fun/ch32fun/../extralibs -I/home/rika/ch32fun/ch32fun -nostdlib -I. -Wall -Wl,--print-memory-usage -Wl,-Map=GPIO_adc_sw.map -L/home/rika/ch32fun/ch32fun/../misc -lgcc -lgcc -T /home/rika/ch32fun/ch32fun/generated__.ld -Wl,--gc-sections
Memory region Used Size Region Size %age Used
FLASH: 1956 B 16 KB 11.94%
RAM: 0 GB 2 KB 0.00%
riscv64-unknown-elf-objdump -S GPIO_adc_sw.elf > GPIO_adc_sw.lst
riscv64-unknown-elf-objcopy -O binary GPIO_adc_sw.elf GPIO_adc_sw.bin
riscv64-unknown-elf-objcopy -O ihex GPIO_adc_sw.elf GPIO_adc_sw.hex
make -C /home/rika/ch32fun/ch32fun/../minichlink all
make[1]: ディレクトリ '/home/rika/ch32fun/minichlink' に入ります
make[1]: 'all' に対して行うべき事はありません.
make[1]: ディレクトリ '/home/rika/ch32fun/minichlink' から出ます
/home/rika/ch32fun/ch32fun/../minichlink/minichlink -w GPIO_adc_sw.bin flash -b
Found WCH Link
WCH Programmer is LinkE version 2.18
Detected CH32V003
Flash Storage: 16 kB
Part UUID: 57-5f-ab-cd-c0-80-bd-54
Part Type: 00-33-05-10
Read protection: disabled
Interface Setup
Writing image
Image written.
書き込みが終了すると、
SW1 でLED1、LED2が相互点滅(4回)
SW2でLED1、LED2が消灯
SW3でLED2が点灯
SW4でLED1が点灯
SW5でLED1、LED2が点灯
となると思います。