Author Topic: [Solved] STC8 (8051): PWM output stuck floating  (Read 1487 times)

0 Members and 1 Guest are viewing this topic.

Offline WhalesTopic starter

  • Super Contributor
  • ***
  • Posts: 1899
  • Country: au
    • Halestrom
[Solved] STC8 (8051): PWM output stuck floating
« on: December 24, 2023, 05:40:16 am »
I am trying to use PWM6 (fed by the counter PWMB) to generate a simple PWM waveform and output it on P5.4.

- P5.4 looks like it's stuck floating.  It doesn't do anything.
- PWMB's internal counter is definitely counting, I can see its values printed over the UART.

Things I've tried:

- If I remove the PWMB_ENO line then P5.4 works like a normal output (strong push/pull that I can control by setting its bit in P5).
- P5.4 works fine as an MCLK0 output (beautiful high-freq square waves)
- Reading someone's HAL for this family and following their exact order & pattern of reg writes (they used a descending counter + different PWM comparison mode, but still P5.4 stayed floating at around 2.7V)
- Checking to make sure EAXFR_MAP & UNMAP are working as expected (I can't read PWMB_CNTR in the UART printing code if they're omitted)

Chip: STC8H1K08 (datasheet link).  Pin 7 is "MCLK0/RST/PWM6_2/P5.4".

Any ideas?

Code: [Select]
void main()
{
// Serial comms: UART1 T2
SCON  = 0x50; // 8 bit variable baudrate (no parity)
AUXR |= 0b00000001; // clock UART from T2
AUXR |= 0b00000100; // T2 in 1T mode
AUXR |= 0b00010000; // T2 run
T2L = UART1_TIMER_PRELOAD % 256;   
T2H = UART1_TIMER_PRELOAD>>8;
ES = 1; // UART1 interrupt enable

// Clock display brightnessPWM: P5.4 PWMB PWM6
EAXFR_MAP;
RSTCFG = 0b01000000;                     // P5.4: Make it a normal IO pin (disable chip reset functionality)
P5M1 &= 0b11101111; P5M0 |= 0b00010000;  // P5.4: strong push-pull
PWMB_CCER1 = 0;          // PWM6: Disable (required before writing to CCMR2)
PWMB_CCMR2 = 0b01101000; // PWM6: PWM mode 1 and enable preload of PWMB_CCR6 (smoother PWM level changes)
PWMB_CCER1 = 0b00010000; // PWM6: Enable
PWMB_ENO   = 0b00000100; // PWM6: Enable output
PWMB_PS    = 0b00000100; // PWM6: Send to pin P5.4
PWMB_PSCR = 1;          // PWMB: Clock at 1/(X+1) of system clock
PWMB_CCR6 = 1000;       // PWMB: ratio (out of 65536)
PWMB_CR1 |= 0b00000001; // PWMB: enable
PWMB_BKR  = 0x10000000; // PWMB: enable (disable brake)  <-- might not be needed as brake not enabled?
EAXFR_UNMAP;

EA = 1; // global interrupt enable

while(1)
{
EAXFR_MAP;
uint16_t curtime = ((uint16_t)PWMB_CNTRH << 8) | PWMB_CNTRL;
EAXFR_UNMAP;

uart1_writeStr("Current PWMB_CNTR value: ");
uart1_writeHex16(curtime);
uart1_write('\r');
uart1_write('\n');
}
}

« Last Edit: January 08, 2024, 05:52:37 am by Whales »
 

Offline amyk

  • Super Contributor
  • ***
  • Posts: 8276
Re: STC8 (8051): PWM output stuck floating
« Reply #1 on: December 24, 2023, 06:03:48 am »
What's P_SW1 set to? Bits 3:2 there may map the SPI peripheral to P5.4.
 
The following users thanked this post: Whales

Offline IOsetting

  • Regular Contributor
  • *
  • Posts: 56
  • Country: cn
Re: STC8 (8051): PWM output stuck floating
« Reply #2 on: December 24, 2023, 04:47:13 pm »
I just tried with the code below. This can output PWM on P5.4.

Code: [Select]
/**
 * Demo: P5.4 pwm with duty cycle changed by timer2 interrupt
 *
 * P5.4  -> 1k Ω resistor -> LED1+
 * GND   -> LED1-
 *
 * Note: PWM6 = PWMB_PWM2
*/
#include "fw_hal.h"

__BIT dir = SET;
uint8_t dc = 0;

INTERRUPT(Timer2_Routine, EXTI_VectTimer2)
{
    PWMB_PWM2_SetCaptureCompareValue(dc);
    UART1_TxHex(dc);
    UART1_TxString("\r\n");
    if (dir)
    {
        dc++;
        if (dc == 0xFF) dir = !dir;
    }
    else
    {
        dc--;
        if (dc == 0) dir = !dir;
    }
}

void main(void)
{
    SYS_SetClock();
    // UART1, baud 115200, baud source Timer1, 1T mode
    UART1_Config8bitUart(UART1_BaudSource_Timer1, HAL_State_ON, 115200);

    // Set GPIO pins output mode
    GPIO_P5_SetMode(GPIO_Pin_4, GPIO_Mode_Output_PP);
    // Turn off PWMB.2 before change its mode
    PWMB_PWM2_SetPortState(HAL_State_OFF);
    // Set PWMB.2 port direction output
    PWMB_PWM2_SetPortDirection(PWMB_PortDirOut);
    // Set PWMB.2 output low voltage when counter is less than target value
    PWMB_PWM2_ConfigOutputMode(PWM_OutputMode_PWM_LowIfLess);
    // Enable comparison value preload to make duty cycle changing smooth
    PWMB_PWM2_SetComparePreload(HAL_State_ON);
    // Turn on PWMB.2
    PWMB_PWM2_SetPortState(HAL_State_ON);

    // Set highest PWM clock
    PWMB_SetPrescaler(0);
    // PWM width = Period + 1 (side alignment), or AutoReloadPeriod * 2 (center alignment)
    PWMB_SetPeriod(0xFF);
    // Counter direction, down:from [PWMA_ARRH,PWMA_ARRL] to 0
    PWMB_SetCounterDirection(PWM_CounterDirection_Down);
    // Enable preload on reload-period
    PWMB_SetAutoReloadPreload(HAL_State_ON);
    // Enable output on PWMB.2
    PWMB_SetPinOutputState(PWM_Pin_2, HAL_State_ON);
    // Set PWMB.2 alternative ports to P5.4
    PWMB_PWM2_SetPort(PWMB_PWM6_AlterPort_P54);
    // Enable overall output
    PWMB_SetOverallState(HAL_State_ON);
    // Start counter
    PWMB_SetCounterState(HAL_State_ON);

    // 1T mode, prescaler:255+1, frequency: 100
    TIM_Timer2_Config(HAL_State_ON, 0xFF, 100);
    // Timer2 interrupt: ON
    EXTI_Timer2_SetIntState(HAL_State_ON);
    EXTI_Global_SetIntState(HAL_State_ON);
    TIM_Timer2_SetRunState(HAL_State_ON);

    while(1);
}

Compiled with https://github.com/IOsetting/FwLib_STC8

Makefile
Code: [Select]
MCU                 ?= STC8H1K08
MCU_IRAM            ?= 256
# 1024, 2048, 3072, 4096, 8192
MCU_XRAM            ?= 1024
# 8192, 16384, 32768, 65536
MCU_CODE_SIZE       ?= 8192

##### Project #####

PROJECT             ?= app
# The path for generated files
BUILD_DIR           = build

TOOCHAIN_PREFIX     ?= /opt/sdcc/sdcc-4.1.0/bin/

# C source folders
USER_CDIRS          := user
# C source single files
USER_CFILES         :=
USER_INCLUDES       := user


LIB_FLAGS           := __CONF_FOSC=36864000UL \
          __CONF_MCU_MODEL=MCU_MODEL_STC8H1K08 \
          __CONF_CLKDIV=0x00 \
          __CONF_IRCBAND=0x01 \
          __CONF_VRTRIM=0x1F \
          __CONF_IRTRIM=0xB5 \
          __CONF_LIRTRIM=0x00

include ./rules.mk

rules.mk
Code: [Select]
ARCH_FLAGS    := -mmcs51 --model-large
« Last Edit: January 07, 2024, 01:21:38 pm by IOsetting »
 
The following users thanked this post: Whales

Offline WhalesTopic starter

  • Super Contributor
  • ***
  • Posts: 1899
  • Country: au
    • Halestrom
Re: STC8 (8051): PWM output stuck floating
« Reply #3 on: January 07, 2024, 07:48:15 am »
Sorry for the late reply.  Got a bad flu over Xmas and new year :|

IOsetting: thankyou for your code, I'm successfully seeing the pin sweep a range of PWM ratios.  I'll pick through the assembly and compare it with what I'm doing to see if there is something obviously different.

I didn't end up using your Makefile (what version of make is it?) but putting all of the dep .h and .c files in the same directory and using sdcc directly got me a working ihx/hex :)

amyk: I'll have a look, thankyou.

Offline IOsetting

  • Regular Contributor
  • *
  • Posts: 56
  • Country: cn
Re: STC8 (8051): PWM output stuck floating
« Reply #4 on: January 07, 2024, 01:38:14 pm »
I didn't end up using your Makefile (what version of make is it?) but putting all of the dep .h and .c files in the same directory and using sdcc directly got me a working ihx/hex :)
Sorry to hear that, this year's cold season is really bad, many people here have a bad flu too.
I just noticed the "include ./rules.mk" is missing at the end of Makefile, adding that should make the Makefile work. I am using make 4.2.1

Code: [Select]
$ make --version
GNU Make 4.2.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
« Last Edit: January 07, 2024, 01:41:02 pm by IOsetting »
 

Offline WhalesTopic starter

  • Super Contributor
  • ***
  • Posts: 1899
  • Country: au
    • Halestrom
Re: STC8 (8051): PWM output stuck floating
« Reply #5 on: January 08, 2024, 05:50:56 am »
I found the error and it's not what I expected in the slightest.  It has taken many hours to track down.

I bisected the problem by replacing lines of your code with my code (they're mostly compatible).  The issue exists in these two lines:

PWMB_CR1 |= 0b00000001; // PWMB: enable
PWMB_BKR  = 0x10000000; // PWMB: enable (disable brake)  <-- might not be needed as brake not enabled?


Can you spot the error?  I'll give a hint: it's not the fault of the micro.






PWMB_CR1 |= 0b00000001; // PWMB: enable
PWMB_BKR  = 0x10000000; // PWMB: enable (disable brake)  <-- might not be needed as brake not enabled?


Changing that constant to format 0b instead of 0x magically fixes everything.  My pin is now wiggling.

It looks like SDCC doesn't complain when you try to write a large constant somewhere too small.  In my header file PWMB_BKR is defined as:

Code: [Select]
#define     PWMB_BKR                (*(unsigned char volatile __xdata *)0xfefd)
The SDCC manual doesn't seem to list any flags to enable more warnings (like -Wall, which it rejects).  I might try contacting the project and asking, but for now I'll have to replace my font with something that draws pulsating coloured beacons for the ligatures 0b and 0x  ;)

Thankyou IOsetting and amyk for your help, muchly appreciated.
« Last Edit: January 08, 2024, 05:55:52 am by Whales »
 

Offline IOsetting

  • Regular Contributor
  • *
  • Posts: 56
  • Country: cn
Re: [Solved] STC8 (8051): PWM output stuck floating
« Reply #6 on: January 09, 2024, 11:06:27 am »
Who would notice that :palm: PWMB_BKR is an unsigned char so it would be better if SDCC can raise a warning on this.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf