Top
ch32v003 - 2023年8月16日更新

Arduino(arduino_core_ch32)を使って開発しています。
ここでは作成したコードを公開しています。
※最新情報や一部のソースはX(twitter) @inunyannで公開しています。ソースは画像になっていますが…
Amazonのほしいものリスト🎁お願いします!!

試作例:neopixel(ws2812)での文字スクロール
NeoPixel::show()関数
pwm
ロータリエンコーダ(Encoder mode)
タッチセンサ
DMA ADC


●試作例:neopixel(ws2812)での文字スクロール

今日も1日がんばるぞぃ!
昨日の日記。ch32v003でも、いぬにゃん表示と、ロータリエンコーダ(Encoder mode)での速度変更出来たので満足です。twitterくんの制限でお返しできずにすみません!リプも出来ませんでした…今日も引っかかるかもしれません…が、今週もよろしくお願い致します! pic.twitter.com/EL7VG18AyA

— いぬにゃん (@inunyann) July 2, 2023

●NeoPixel::show()関数

void Adafruit_NeoPixel::show(void) {
  if (!pixels) return;
  while (!canShow());

  uint8_t *ptr, *end, p, bitMask;
  uint16_t pinMask;
  ptr = pixels;
  end = ptr + numBytes;
  p = *ptr++;
  bitMask = 0x80;

  GPIO_TypeDef *GPIOx = digitalPinToPort(pin);
  pinMask = digitalPinToBitMask(pin);
  __disable_irq();

//#define SYSCLK_FREQ_48MHZ_HSx 1

#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
  if (is800KHz) {
#endif
    for (;;) {
      if (p & bitMask) { // ONE
        // High 600ns
        GPIOx->BSHR = pinMask;
        asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"); // 1nop = 41.7ns? @ 24MHz
#if defined(SYSCLK_FREQ_48MHZ_HSx)
        asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"); // 1nop = 20.8ns? @ 48MHz
#endif
        // Low 300ns
        GPIOx->BCR = pinMask;
        asm volatile ("");
#if defined(SYSCLK_FREQ_48MHZ_HSx)
        asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
#endif
      } else { // ZERO
        // High 300ns
        GPIOx->BSHR = pinMask;
        asm volatile ("nop; nop; nop; nop; nop;");
#if defined(SYSCLK_FREQ_48MHZ_HSx)
        asm volatile ("nop; nop; nop; nop; nop; nop; nop;");
#endif
        // Low 600ns
        GPIOx->BCR = pinMask;
        asm volatile ("nop; nop; nop; nop; nop;");
#if defined(SYSCLK_FREQ_48MHZ_HSx)
        asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
#endif
      }
      if (bitMask >>= 1) {
        asm volatile ("nop; nop; nop; nop; nop;");
      } else {
        if (ptr >= end) break;
        p = *ptr++;
        bitMask = 0x80;
      }
    }
#if defined(NEO_KHZ400)
  } else { // 400 KHz bitstream
    // ToDo!
  }
#endif
  __enable_irq();

  endTime = micros(); // Save EOD time for latch on next call
}

●pwm

void analogWrite(uint8_t duty) { // PD0(8) or PD2(19), ch4:PC4(14)
  TIM_SetCompare1(TIM1, duty); // ,4
}

void analogInit(uint16_t freq = 1000) { // PD0(8) or PD2(19), ch4:PC4(14)
  SystemCoreClockUpdate();
  uint32_t psc = SystemCoreClock / 256 / freq;
  if (psc >> 16) psc = 0xffff;
  else if (psc) psc--;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); // ,C

  GPIO_InitTypeDef gpioD0;
  gpioD0.GPIO_Pin = GPIO_Pin_0; // or 2, 4
  gpioD0.GPIO_Speed = GPIO_Speed_2MHz;
  gpioD0.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOD, &gpioD0); // ,C

  TIM_TimeBaseInitTypeDef tim1;
  tim1.TIM_Period = 255;
  tim1.TIM_Prescaler = psc;
  tim1.TIM_ClockDivision = TIM_CKD_DIV1;
  tim1.TIM_CounterMode = TIM_CounterMode_Up;
  tim1.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM1, &tim1);

  TIM_OCInitTypeDef oc1;
  oc1.TIM_OCMode = TIM_OCMode_PWM1;
  oc1.TIM_OutputState = TIM_OutputState_Disable; // or En, En
  oc1.TIM_OutputNState = TIM_OutputNState_Enable; // or Dis, Dis
  oc1.TIM_Pulse = 0;
  oc1.TIM_OCPolarity = TIM_OCPolarity_High;
  oc1.TIM_OCNPolarity = TIM_OCPolarity_High;
  oc1.TIM_OCIdleState = TIM_OCIdleState_Reset;
  oc1.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
  TIM_OC1Init(TIM1, &oc1); // ,4

  TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable); // ,4
  TIM_ARRPreloadConfig(TIM1, ENABLE);
  TIM_CtrlPWMOutputs(TIM1, ENABLE);
  TIM_Cmd(TIM1, ENABLE);
}

void analogStop() {
  TIM_Cmd(TIM1, DISABLE);
  TIM_CtrlPWMOutputs(TIM1, DISABLE);
  pinMode(PD0, INPUT_PULLUP); // or PD2, PC4
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, DISABLE);
}

●ロータリエンコーダ(Encoder mode)

#define getEncoderCount() TIM_GetCounter(TIM2)

void encoderInit() {
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  pinMode(PD4, INPUT_PULLUP); // T2CH1 : PD4(1)
  pinMode(PD3, INPUT_PULLUP); // T2CH2 : PD3(20)

  TIM_TimeBaseInitTypeDef tim2;
  tim2.TIM_Period = 0xffff;
  tim2.TIM_Prescaler = 1;
  tim2.TIM_ClockDivision = TIM_CKD_DIV1;
  tim2.TIM_CounterMode = TIM_CounterMode_Up;
  tim2.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM2, &tim2);

  TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI1, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

  TIM_SetCounter(TIM2, 0);
  TIM_Cmd(TIM2, ENABLE);
}

void encoderStop() {
  TIM_Cmd(TIM2, DISABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, DISABLE);
}

●タッチセンサ

#define TOUCH_THRESHOLD 20

uint16_t MeasureTouch(int16_t pin) {
  uint32_t starttime, endtime;
  GPIO_TypeDef *GPIOx = digitalPinToPort(pin);
  uint16_t pinMask = digitalPinToBitMask(pin);

  pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);

  GPIOx->CFGLR = 0x00000008 << 4 * digitalPinToPinName(pin);
  GPIOx->BSHR = pinMask;
  starttime = SysTick->CNT;

  while (!(GPIOx->INDR & pinMask));
  endtime = SysTick->CNT;

  return (uint16_t)(endtime - starttime);
}

bool isTouched(int16_t pin) {
  SystemCoreClockUpdate();
  uint32_t clk = SystemCoreClock;
  if (clk != 24000000) SetSysClockTo_24MHZ_HSI();
  uint16_t touch = MeasureTouch(pin);
  if      (clk ==   93750) SetSysClockTo_94KHz_HSI();
  else if (clk ==  750000) SetSysClockTo_750KHz_HSI();
  else if (clk == 6000000) SetSysClockTo_6MHZ_HSI();
  return touch > TOUCH_THRESHOLD ? true : false;
}

●DMA ADC

volatile uint16_t adcDmaData[4]; // 4 chs

void startAdcDma() {
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  RCC_ADCCLKConfig(RCC_PCLK2_Div128);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);

  DMA_InitTypeDef dma;
  dma.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->RDATAR;
  dma.DMA_MemoryBaseAddr = (uint32_t)&adcDmaData;
  dma.DMA_DIR = DMA_DIR_PeripheralSRC;
  dma.DMA_BufferSize = sizeof(adcDmaData) / sizeof(adcDmaData[0]);
  dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
  dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  dma.DMA_Mode = DMA_Mode_Circular;
  dma.DMA_Priority = DMA_Priority_Medium;
  dma.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &dma);
  DMA_Cmd(DMA1_Channel1, ENABLE);

  GPIO_InitTypeDef gpio;
  gpio.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_4; // PD2(A3), PD3(A4), PD6(A6), PD4(A7)
  gpio.GPIO_Speed = GPIO_Speed_2MHz;
  gpio.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOD, &gpio);

  ADC_InitTypeDef adc;
  adc.ADC_Mode = ADC_Mode_Independent;
  adc.ADC_ScanConvMode = ENABLE;
  adc.ADC_ContinuousConvMode = ENABLE;
  adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  adc.ADC_DataAlign = ADC_DataAlign_Right;
  adc.ADC_NbrOfChannel = sizeof(adcDmaData) / sizeof(adcDmaData[0]);
  ADC_Init(ADC1, &adc);

  ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_241Cycles); // PD2(A3)
  ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 2, ADC_SampleTime_241Cycles); // PD3(A4)
  ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 3, ADC_SampleTime_241Cycles); // PD6(A6)
  ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 4, ADC_SampleTime_241Cycles); // PD4(A7)
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_Vrefint, 5, ADC_SampleTime_241Cycles);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_Vcalint, 6, ADC_SampleTime_241Cycles);

  ADC_DMACmd(ADC1, ENABLE);
  ADC_Cmd(ADC1, ENABLE);

  ADC_ResetCalibration(ADC1);
  while (ADC_GetResetCalibrationStatus(ADC1));
  ADC_StartCalibration(ADC1);
  while (ADC_GetCalibrationStatus(ADC1));

  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

void stopAdcDma() {
  ADC_SoftwareStartConvCmd(ADC1, DISABLE);
  ADC_Cmd(ADC1, DISABLE);
  ADC_DMACmd(ADC1, DISABLE);
  DMA_Cmd(DMA1_Channel1, DISABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, DISABLE);
}


ibunyan.com