Author Topic: Ch32v003 sop8 version, pin mapping issue?  (Read 1119 times)

0 Members and 1 Guest are viewing this topic.

Offline Nout1Topic starter

  • Newbie
  • Posts: 2
  • Country: be
Ch32v003 sop8 version, pin mapping issue?
« on: January 27, 2025, 10:17:21 pm »
I'm struggling to get a correct behaviour from PA1 and PA2. Likely it has to do with my code but can't recognize the problem.
Through debugging i notice that PA2 always reads a zero, while it should be a pull-up input. PA1 on the other hand works correctly. So delay and other functions do work correctly.
PC1 does show a PWM and work correctly
PC2 does drive a led and works correctly
PC4 does drive a led and after the debounce time goes active, which is expected when PA2 reads always zero.
I actively disable PA1 and PA2 to be mapped as oscillator pins, but maybe i'm doing it wrong? PA2 seem to be stuck to zero.
I'm not using any board, just a bare chip, directly programmed by link-e. I'm also 100% sure there is no short between PA2 and GND.
I've tried on 2 samples and both show the same behaviour. So very likely my code is the reason and in some way PA2 always reads a zero.

Any help in solving this is appreciated.

Here is my code:

/***************************************************************
 * File Name          : main.c
 * for ch32v003j4g6, soic8 package
 * Description        : create 50Hz pwm on pc1, with 2 buttons on pa1 and pa2, increment or decrement the pulse time of the pwm
 * also control 2 leds, connected to pc2 and pc4
 *
 * programming pin connections
 * pin 2 = gnd
 * pin 4 = 3v3
 * pin 8 = swdio
 **************************************************************/


#include "ch32v00x.h"
#include "delay.h"

#include <stdint.h>

#define PWM_TIMER          TIM2
#define PWM_FREQ           50                // 50Hz for servo
#define ZERO_ANGLE_PULSE   1500              // 1.5ms pulse width for 0 degrees
#define FULL_ANGLE_PULSE   2500              // 2.5ms pulse width for 180 degrees
#define MOVE_DURATION_MS   5000              // 5 seconds for full 90-degree motion


// Button pins
#define UP_PIN             GPIO_Pin_1        // PA1
#define DOWN_PIN           GPIO_Pin_2        // PA2

//PWM pin PC1 (mapping TIM2 CH4)
#define PWM_PIN            GPIO_Pin_1        // PC1

// LED pins
#define GREEN_LED_PIN      GPIO_Pin_2        // PC2
#define RED_LED_PIN        GPIO_Pin_4        // PC4


/* Global Variable */
volatile uint8_t button1_state = 0xff;  //0xff is the "not pushed" state
volatile uint8_t button2_state = 0xff;  //0xff is the "not pushed" state

/*

// Initialize PWM on PA1 (default mapping is Timer 1 Channel 2 to PA1)
void pwm_init(void) {
    // Enable clocks for TIM1 and GPIOA
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE);

    // Enable AF clock to get to tim1 + undo any possible pin mapping for PA1 and PA2 back to default mapping
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_PA1_2, DISABLE);

    // Configure PA1 as alternate function push-pull
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;  // PA1
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // Configure TIM1 for PWM
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0};
    TIM_TimeBaseStructure.TIM_Prescaler = SystemCoreClock / (PWM_FREQ * 20000) - 1;
    TIM_TimeBaseStructure.TIM_Period = 20000;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //no division
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

    TIM_OCInitTypeDef TIM_OCInitStructure = {0};
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = ZERO_ANGLE_PULSE;
    TIM_OC2Init(TIM1, &TIM_OCInitStructure);  // Use Channel 2

    // Enable TIM1 outputs and start the timer
    TIM_CtrlPWMOutputs(TIM1, ENABLE);
    TIM_Cmd(TIM1, ENABLE);
}

// Initialize GPIO for buttons and LEDs
void gpio_init(void) {
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure = {0};

    // Buttons: PC1 (UP) and PA2 (DOWN) as inputs with pull-up
    GPIO_InitStructure.GPIO_Pin = GPIO_PIN_UP;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DOWN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // LEDs: PC2 (Green) and PC4 (Red) as outputs
    GPIO_InitStructure.GPIO_Pin = GREEN_LED_PIN | RED_LED_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_ResetBits(GPIOC, GREEN_LED_PIN | RED_LED_PIN);  // Turn off LEDs initially
}

*/

// Function to configure GPIO
void gpio_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    // activate GPIO clocks + Alternate Function clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);

    // make sure PA1 and PA2 are not remapped to OSC
    GPIO_PinRemapConfig(GPIO_Remap_PA1_2, DISABLE);

    //LEDS on PA1 and PA2
    GPIO_InitStructure.GPIO_Pin = UP_PIN | DOWN_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //LEDS on PC2 and PC4
    GPIO_InitStructure.GPIO_Pin = RED_LED_PIN | GREEN_LED_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    // Turn off LEDs initially
    GPIO_ResetBits(GPIOC, GREEN_LED_PIN | RED_LED_PIN);
}

// Function to configure PWM
void pwm_init(void)
{
     GPIO_InitTypeDef GPIO_InitStructure = {0};
     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0};
     TIM_OCInitTypeDef TIM_OCInitStructure = {0};

     // Enable Timer2 clock and gpioc clock
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE );

     // set PC1 as AF to TIM2 CH4 => Pin as Alternate Function Push-Pull
     GPIO_InitStructure.GPIO_Pin = PWM_PIN;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_30MHz;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_Init(GPIOC, &GPIO_InitStructure);

    // Timer2 base configuration for PWM
    TIM_TimeBaseStructure.TIM_Prescaler = SystemCoreClock / (PWM_FREQ * 20000) - 1;
    TIM_TimeBaseStructure.TIM_Period = 20000;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //no division
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(PWM_TIMER, &TIM_TimeBaseStructure);

    // PWM Channel 1 configuration
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = ZERO_ANGLE_PULSE + 500; // Initial duty cycle
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init(PWM_TIMER, &TIM_OCInitStructure);  // Channel 1 for PWM

    TIM_CtrlPWMOutputs(PWM_TIMER, ENABLE );
    TIM_OC1PreloadConfig(PWM_TIMER, TIM_OCPreload_Enable); // Channel 1 for PWM

    // Enable TIM2 Preload register on ARR
    TIM_ARRPreloadConfig(PWM_TIMER, ENABLE);

    // Enable PWM_TIMER
    TIM_Cmd(PWM_TIMER, ENABLE);

    //remap PC1 as TIM2 CH1
    GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2, ENABLE);

}


int main(void)
{
    SystemCoreClockUpdate(); // Initialize system clocks and peripherals at 48MHz
    delay_init();
    gpio_init();
    pwm_init();

    uint32_t lastmills_button = getmills();
    uint32_t lastmills_servo = getmills();
    uint16_t pulse_width = 500;

    while(1) {
        //debounce the buttons
        if ((getmills() - lastmills_button) > 1){
            button1_state = (button1_state<<1) | GPIO_ReadInputDataBit(GPIOA, UP_PIN);
            button2_state = (button2_state<<1) | GPIO_ReadInputDataBit(GPIOA, DOWN_PIN);
            lastmills_button = getmills();
        }
        if ((getmills() - lastmills_servo) > 50) {
            //act on button state. 0x00 means the button is pressed. 0xff means the button is released. any other value is debouncing noise
            if (button1_state == 0x00) {  //button is pressed
                GPIO_SetBits(GPIOC, GREEN_LED_PIN);
                pulse_width++;
            } else if (button1_state == 0xff) {
                GPIO_ResetBits(GPIOC, GREEN_LED_PIN);
            }
            if (button2_state == 0x00) {   //button is pressed
                GPIO_SetBits(GPIOC, RED_LED_PIN);
                pulse_width--;
            } else if (button2_state == 0xff) {
               GPIO_ResetBits(GPIOC, RED_LED_PIN);
            }
            if (pulse_width > 999) { pulse_width = 0; }
       //     TIM_SetCompare1(PWM_TIMER, ZERO_ANGLE_PULSE + pulse_width);  // Channel 1
            lastmills_servo = getmills();
        }
    }
}
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6463
  • Country: es
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: voltsandjolts

Offline corgon

  • Contributor
  • Posts: 13
  • Country: cz
Re: Ch32v003 sop8 version, pin mapping issue?
« Reply #2 on: January 28, 2025, 08:39:32 pm »
No problem with your config. It works fine.
I’ve tested it. Here’s an example:
Code: [Select]
#include "ch32v00x.h"

void gpio_init(void){
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    // activate GPIO clocks + Alternate Function clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // make sure PA1 and PA2 are not remapped to OSC
    GPIO_PinRemapConfig(GPIO_Remap_PA1_2, DISABLE);

    //LEDS on PA1 and PA2
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // GPIOC Setup
    RCC->APB2PCENR |= (1 << 4);
    GPIOC->CFGLR = 0x22222222;
}

int main(void) {
    gpio_init();
    GPIOC->BCR = 0x0FF;
    while (1) {
  (GPIOA->INDR & (1 << 1)) ? (GPIOC->BSHR |= (1 << 18)) : (GPIOC->BSHR |= (1 << 2)); // GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1), LED on C2
  (GPIOA->INDR & (1 << 2)) ? (GPIOC->BSHR |= (1 << 20)) : (GPIOC->BSHR |= (1 << 4)); // GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2), LED on C4
    }
}

Do you have in "ch32v00x.h" set to the internal oscillator?
Code: [Select]
#define SYSCLK_FREQ_48MHZ_HSI   48000000
« Last Edit: January 28, 2025, 09:05:24 pm by corgon »
 

Offline corgon

  • Contributor
  • Posts: 13
  • Country: cz
Re: Ch32v003 sop8 version, pin mapping issue?
« Reply #3 on: January 29, 2025, 04:06:56 pm »
So, I tested it, and I'm 100% sure that your problem is in the settings where you have an external crystal selected.
The code does work, but it behaves exactly as in your case.
Set HSI as I mentioned in my previous message, and it will work.
 

Offline Nout1Topic starter

  • Newbie
  • Posts: 2
  • Country: be
Re: Ch32v003 sop8 version, pin mapping issue?
« Reply #4 on: January 29, 2025, 04:08:31 pm »
Hi Corgon ,

You made my day!
Your code did show exactly the same problem, but after adding the sysclk definition to ch32v00x.h, all works fine
And also my code works now fine.
I've limited experience with this framework and would never have found this by myself.

Thanks a lot!
 
The following users thanked this post: corgon

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 14158
  • Country: gb
    • Mike's Electric Stuff
Re: Ch32v003 sop8 version, pin mapping issue?
« Reply #5 on: January 29, 2025, 05:20:14 pm »
Something to be be aware of on the 8 pin is that some pins are bonded to multiple pads on the chip, so you need to be careful to set them to compatible modes
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf