ch32v003メモ

[ch32v003]電子オルゴール

ch32v003funを用いた電子オルゴールのサンプル(2023.7.23)

ファイル一覧

ch32v003fun/examples/music_box/
├── Makefile
├── doremi_tone.h
├── funconfig.h
├── furElise.h
├── happybirthday.h
├── music_box.c

配線図

music_box.cpp

メイン関数
・PWM制御で電子オルゴールを実行する
・スピーカーはGNDと7番ピン(PC4)に接続する
・曲の選択は7行目、8行目のどちらかをコメントアウトする
/*
 * Example for Music box with PWM
 */

#include "ch32v003fun.h"
#include >stdio.h<
#include "furElise.h"
//#include "happybirthday.h"

/*
 * initialize TIM1 for PWM
 */
void t1pwm_init( void )
{
	// Enable GPIOC, GPIOD and TIM1
	RCC-<APB2PCENR |= 	RCC_APB2Periph_GPIOC | RCC_APB2Periph_TIM1;
	
	// PC4 is T1CH4, 10MHz Output alt func, push-pull
	GPIOC-<CFGLR &= ~(0xf>>(4*4));
	GPIOC-<CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)><(4*4);
		
	// Reset TIM1 to init all regs
	RCC-<APB2PRSTR |= RCC_APB2Periph_TIM1;
	RCC-<APB2PRSTR &= ~RCC_APB2Periph_TIM1;
	
	// CTLR1: default is up, events generated, edge align
	// SMCFGR: default clk input is CK_INT
	
	// Prescaler 
	TIM1-<PSC = 0x0200;
	
	// Auto Reload - sets period
	TIM1-<ATRLR = 1023;
	
	// Reload immediately
	TIM1-<SWEVGR |= TIM_UG;
	
	// Enable CH4 output, positive pol
	TIM1-<CCER |= TIM_CC4E | TIM_CC4P;
	
	// CH1 Mode is output, PWM1 (CC1S = 00, OC1M = 110)
	TIM1-<CHCTLR1 |= TIM_OC1M_2 | TIM_OC1M_1;
	
	// CH2 Mode is output, PWM1 (CC1S = 00, OC1M = 110)
	TIM1-<CHCTLR2 |= TIM_OC4M_2 | TIM_OC4M_1;
	
	// Set the Capture Compare Register value to 50% initially
	TIM1-<CH4CVR = 512;
	
	// Enable TIM1 outputs
	TIM1-<BDTR |= TIM_MOE;
	
	// Enable TIM1
	TIM1-<CTLR1 |= TIM_CEN;
}

void init_tone(unsigned short *TONE0, unsigned short *TONE1, unsigned short *TONEL)
{
  unsigned int sys_clock=48000000;//System clock(48kHz)
  unsigned int tim1_psc = 0x200;
  unsigned int internal_clock = (unsigned int)(sys_clock/(double)(tim1_psc));//Internal clock

  for(int i=0;i<mb_cnt;i++)
  {
    TONE0[i] = (unsigned short)(internal_clock/(double)(mb_tone[i]));
    TONE1[i] = (unsigned short)(internal_clock/(double)(mb_tone[i])/2.0);
    TONEL[i] = (unsigned short)(4800/mb_notes[i]);
  }
}

/*
 * entry
 */
int main()
{
  int count=0;
  unsigned short TONE0[256];
  unsigned short TONE1[256];
  unsigned short TONEL[256];

  SystemInit();
  Delay_Ms( 100 );

  // init tone
  init_tone(TONE0, TONE1, TONEL);

  // init TIM1 for PWM(PC4=pin7 for J4m6)
  t1pwm_init();

  while(1)
  {
    TIM1-<ATRLR =TONE0[count];
    TIM1-<CH4CVR =TONE1[count];
    TIM1-<SWEVGR |= TIM_UG;//Update event generation bit(automaticallly cleared by hardware)

    Delay_Ms( TONEL[count] );
    count=(count+1)%mb_cnt;
  }
}

doremi_tone.h

音階を周波数[Hz]で表したもの。"do3"は「ド」、"dos3"は「ド#」などを表す。
zzは休符
const float do3  = 130.813;
const float dos3 = 138.591;
const float re3  = 146.832;
const float res3 = 155.563;
const float mi3  = 164.814;
const float fa3  = 174.614;
const float fas3 = 184.997;
const float so3  = 195.998;
const float sos3 = 207.652;
const float ra3  = 220.000;
const float ras3 = 233.082;
const float si3  = 246.942;
const float do4  = 261.626;
const float dos4 = 277.183;
const float re4  = 293.665;
const float res4 = 311.127;
const float mi4  = 329.628;
const float fa4  = 349.228;
const float fas4 = 369.994;
const float so4  = 391.995;
const float sos4 = 415.305;
const float ra4  = 440.000;
const float ras4 = 466.164;
const float si4  = 493.883;
const float do5  = 523.251;
const float dos5 = 554.365;
const float re5  = 587.330;
const float res5 = 622.254;
const float mi5  = 659.255;
const float fa5  = 698.456;
const float fas5 = 739.989;
const float so5  = 783.991;
const float sos5 = 830.609;
const float ra5  = 880.000;
const float ras5 = 932.328;
const float si5  = 987.767;
const float zz   = 1.0;

furElise.h

ベートーヴェン「エリーゼのために」
・mb_cnt:配列長
・mb_tone:音階の配列
・mb_notes:音符の長さの配列。4は四分音符、16は16分音符を表す
#include "doremi_tone.h"
const int mb_cnt=41;
const float mb_tone[]={
    mi5, res5,  mi5, res5,  mi5,  si4,  re5,  do5,  ra4, zz,
    do4,  mi4,  ra4,  si4,   zz,  mi4, sos4,  si4,  do5, zz,
    mi4,  mi5, res5,  mi5, res5,  mi5,  si4,  re5,  do5,  ra4,
     zz,  do4,  mi4,  ra4,  si4,   zz,  mi4,  do5,  si4,  ra4,
     zz
};
const unsigned short mb_notes[]={
    16, 16, 16, 16, 16, 16, 16, 16,  8, 16,
    16, 16, 16,  8, 16, 16, 16, 16,  8, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16,  8,
    16, 16, 16, 16,  8, 16, 16, 16, 16,  4,
    4
};

happybirthday.h

「ハッピーバースデートゥーユー」
#include "doremi_tone.h"

const int mb_cnt=25;
const float mb_tone[] =  {
    so4, so4, ra4, so4, do5, si4,
    so4, so4, ra4, so4, re5, do5,
    so4, so4, so5, mi5, do5, si4, ra4,
    fa5, fa5, mi5, do5, re5, do5
};
const unsigned short mb_notes[] =  {
    10, 16, 8, 8, 8, 4,
    10, 16, 8, 8, 8, 4,
    10, 16, 8, 8, 8, 8, 8,
    10, 16, 8, 8, 8, 4
};

funconfig.h

#ifndef _FUNCONFIG_H
#define _FUNCONFIG_H

#define CH32V003           1

#endif

Makefile

all : flash

TARGET:=music_box

include ../../ch32v003fun/ch32v003fun.mk

flash : cv_flash
clean : cv_clean