Giter Club home page Giter Club logo

fwlib_stc8's Introduction

About

FwLib_STC8 is a lite firmware library for STC8G/STC8H series MCU.

Official Datasheets, User Manuals

Features

  • Compatible with SDCC and Keil C51
  • Optimized for constrained 8-bit MCU resources
  • Readable code for on-chip resources operation
  • Demos for quick start

SDCC Makefile Quick Start

  1. Clone this repository to local file system
# GitHub
git clone https://github.com/IOsetting/FwLib_STC8.git FwLib_STC8
# or Giteee (for Chinese users)
git clone https://gitee.com/iosetting/fw-lib_-stc8.git FwLib_STC8
  1. Edit Makefile

Change according to your MCU part

## STC8H1K08 STC8H8K64U
MCU                 ?= STC8H1K08
MCU_IRAM            ?= 256
# 1024, 2048, 3072, 4096, 8192
MCU_XRAM            ?= 1024
# 8192, 16384, 32768, 65536
MCU_CODE_SIZE       ?= 8192

And the SDCC path

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

And the compile flags

## STC8H1K08 36.864MHz
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 
  1. Compile
make clean; make

PlatformIO Quick Start

  1. Clone this repository to local file system
# GitHub
git clone https://github.com/IOsetting/FwLib_STC8.git FwLib_STC8
# or Giteee (for Chinese users)
git clone https://gitee.com/iosetting/fw-lib_-stc8.git FwLib_STC8
  1. Copy(or move) it to your PlatformIO project library, the file structure
├── include
├── lib
│   └── FwLib_STC8
│       ├── demo
│       ├── include
│       └── src
├── src
└── test
  1. Add compile arguments in platformio.ini
build_flags =
    -D__CONF_FOSC=36864000UL                       ;The osc/irc frequency you MCU will be running on
    -D__CONF_MCU_MODEL=MCU_MODEL_STC8H3K32S2       ;change this to your MCU type
    -D__CONF_CLKDIV=0x02                           ;frequency trimming
    -D__CONF_IRCBAND=0x03
    -D__CONF_VRTRIM=0x19
    -D__CONF_IRTRIM=0x28
    -D__CONF_LIRTRIM=0x00
  1. Include fw_hal.h in your code
#include "fw_hal.h"

then it's ready to go.

VS Code Syntax Problem

VS Code doesn't support some of SDCC syntax for Intel 8051 (issue 7146), if you want to eliminate syntax errors in code editor, add a separate env for code editing and add __SDCC_SYNTAX_FIX in build_flags:

build_flags =
    -D__SDCC_SYNTAX_FIX
    -D__CONF_FOSC=36864000UL
    -D__CONF_MCU_MODEL=MCU_MODEL_STC8H3K32S2
    ...

This special env is for code editing only, building and uploading should use the normal env.

Keil C51 Quick Start

  1. Clone this repository to local file system
# GitHub
git clone https://github.com/IOsetting/FwLib_STC8.git FwLib_STC8
# or Giteee (for Chinese users)
git clone https://gitee.com/iosetting/fw-lib_-stc8.git FwLib_STC8
  1. Copy(or move) it to your Keil C51 project directory,
  2. Add it to project through Project -> Manage -> Project Items,
  3. Open project option dialog by clicking Project -> Options for Target ... , switch to C51 tab, and input following content in Preprocessor Symbols -> Define:
__CX51__, __CONF_MCU_MODEL=MCU_MODEL_STC8H3K32S2,__CONF_FOSC=36864000UL

The explanation of these arguments

   __CX51__ This will tell the macros to switch to Keil C51 keywords
   __CONF_MCU_MODEL, change this to your MCU type, please look into FwLib_STC8/include/fw_conf.h for all available types.
   __CONF_FOSC The osc/irc frequency you MCU will be running on. It equals to the frequency this MCU will be trimmed to in STC-ISP.
  1. Include fw_hal.h in your code
#include "fw_hal.h"

then it's ready to go.

Macros

Some macros were introduced for code compatibility with Keil C51 and SDCC.

The naming is from sdcc compiler.h. If you want your code to work with both compilers, you need to stick to these macros instead of the compiler specific keywords:

Here is a list of the macros:

Macro Keil C51 SDCC
__BIT bit __bit
__DATA data __data
__IDATA idata __idata
__PDATA pdata __pdata
__XDATA xdata __xdata
__CODE code __code
SBIT(name, addr, bit) sbit name = addr^bit __sbit __at(addr+bit) name
SFR(name, addr) sfr name = addr __sfr __at(addr) name
SFRX(addr) (*(unsigned char volatile xdata *)(addr)) (*(unsigned char volatile __xdata *)(addr))
SFR16X(addr) (*(unsigned int volatile xdata *)(addr)) (*(unsigned int volatile __xdata *)(addr))
INTERRUPT(name, vector) void name (void) interrupt vector void name (void) __interrupt (vector)
INTERRUPT_USING(name, vector, regnum) void name (void) interrupt vector using regnum void name (void) __interrupt (vector) __using (regnum)
NOP() nop() __asm NOP __endasm

The definition of these macros can be found in include/fw_reg_base.h

License

Copyright (c) 2021-present IOsetting [email protected]

The FwLib_STC8 is licensed under the permissive Apache 2.0 license, you can use it in both commercial and personal projects with confidence.

fwlib_stc8's People

Contributors

csharpermantle avatar eeyrw avatar iosetting avatar liux-pro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

fwlib_stc8's Issues

Keil环境下RTC demo编译问题

FwLib_STC8\FwLib_STC8\demo\rtcrtc_interrupt.c中定义的中断服务函数:
INTERRUPT(RTC_Routine, EXTI_VectRTC) { .............. }

  • 📝目前Keil各个版本的C51和C251编译器均只支持32个中断号(0~31),后面的中断需要经过添加汇编调整指令跳转实现。

🛠调整方法:

  • 🌿将中断号指向13号中断:EXTI_VectUser
    INTERRUPT(RTC_Routine, EXTI_VectUser) { .............. }
  • 🌿在fw_exti.h头文件中修改限定宏
    `
    //#if (__CONF_MCU_TYPE == 1 )
    #define EXTI_VectUser 13
    //#endif

`

  • 🌿新建Isr.asm汇编文件,内容如下:
    `
    CSEG AT 0123H ;36号RTC中断入口地址
    LJMP 006BH ;借用 13 号006BH中断的入口地址

END

`

✨以上是对该demo工程的完善,已经在STC8H8K64U B版本单片机上验证。

  • 🌴Keil项目结构树:
    `
    Project:RTC
    Target 1
    ├ Source Group 1
    + rtc_interrupt.c
    + fw_util.c
    + fw_uart.c
    + fw_sys.c
    + fw_tim.c
    - Isr.asm

`

Thanks and a fix

First, a huge thanks for you library.
I never used a STC8 MCU before and your work greatly helped me :)

I made a "helper" file to compute and reverse compute some values related to prescalers.
If you are interested, you can borrow the file or any parts of it ;)
https://github.com/porcinus/NNS-Ambiclone-Mono/blob/main/code/src/FwLib_STC8_helper.h

During coding, I also notice an error (I think, haven't tried but this generate a error) in https://github.com/IOsetting/FwLib_STC8/blob/master/include/fw_rcc.h
In macro RCC_SetPowerDownWakeupTimerCountdown(16BIT_COUNT):
(16BIT_COUNT << 8) should be (16BIT_COUNT >> 8)

Keil编译环境下使用定时器1作为串口波特率发生器报错

在uart1_timer1_tx.c文件中原外部变量引入:

extern __CODE uint16_t ticks_ms; extern __CODE uint8_t ticks_us, clkdiv;

需要如下修改:
`
#if defined (SDCC) || defined (__SDCC)
extern __CODE uint16_t ticks_ms;
extern __CODE uint8_t ticks_us; //clkdiv (include fw_reg_stc8h.h)
#elif defined CX51
extern uint16_t code ticks_ms;
extern uint8_t code ticks_us;
#endif

……

UART1_TxHex(CLKDIV);//改成大写

fw_sys.c文件中调整如下:
#if defined (SDCC) || defined (__SDCC)
__CODE uint16_t ticks_ms = (__CONF_FOSC / ((__CONF_CLKDIV == 0)? 1 : __CONF_CLKDIV) / __CLK_REF);
__CODE uint8_t ticks_us = (__CONF_FOSC / ((__CONF_CLKDIV == 0)? 1 : __CONF_CLKDIV) / __CLK_REF / 1000);
#elif defined CX51
uint16_t code ticks_ms = (__CONF_FOSC / ((__CONF_CLKDIV == 0)? 1 : __CONF_CLKDIV) / __CLK_REF);
uint8_t code ticks_us = (__CONF_FOSC / ((__CONF_CLKDIV == 0)? 1 : __CONF_CLKDIV) / __CLK_REF / 1000);
#endif
`

Have simple code GPIO input/output led ?

Hello

i try codeing gpio input/output for STC8G1K08A
but i can't send output port like arduino

#include "fw_hal.h"

void GPIO_Init()
{
    GPIO_P3_SetMode(GPIO_Pin_0, GPIO_Mode_Output_PP);
}

void main()
{
    GPIO_Init();
    SYS_SetClock();
    while (1)
    {
        SYS_Delay(10);
    }
}

can add simple basic code GPIO input/output led ?
image

thankyou

Compile error when use PWM B

compile error when call function PWMB_PWM1_SetCaptureCompareValue, missing PWMB_CCR1H andPWMB_CCR1H .

src\main.c:89: error 20: Undefined identifier 'PWMB_CCR1H'
src\main.c:89: error 20: Undefined identifier 'PWMB_CCR1L'

FwLib_STC8/include/fw_pwm.h

Lines 455 to 460 in bdd2237

#define PWMB_PWM1_SetCaptureCompareValue(__16BIT_VAL__) do{ \
SFRX_ON(); \
(PWMB_CCR1H = ((__16BIT_VAL__) >> 8)); \
(PWMB_CCR1L = ((__16BIT_VAL__) & 0xFF)); \
SFRX_OFF(); \
}while(0)

There is no PWMB_CCR1H in fw_reg_stc8h.h,but i do found PWMB_CCR5H. May be it should be PWMB_CCR5 since PWMB.1 equals pwm5

#define PWMB_CCR5 (*(unsigned int volatile __XDATA *)0xfef5)
#define PWMB_CCR5H (*(unsigned char volatile __XDATA *)0xfef5)
#define PWMB_CCR5L (*(unsigned char volatile __XDATA *)0xfef6)

Multiple definition error when using stdint.h

The new C51 compiler such as SDCC supports stdint.h which contains platform independent definition such as int8_t, uint8_t 8,etc. However the FwLib_STC8 defines same things at fw_types.h, which finally make a lot errors when compiling the code using stdint.h. Could we rewrite the part of fw_types.h like this:

.............
#if defined (SDCC) || defined (__SDCC)
#include <stdint.h>
#else
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
typedef uint32_t uint64_t[2];

typedef signed char int8_t;
typedef short int16_t;
typedef long int32_t;
typedef int32_t int64_t[2];
#endif
............

关于i2c中的demo mpu6050例程原始数据处理

  • 例程路径:FwLib_STC8\FwLib_STC8\demo\i2c\mpu6050:
  • mpu6050.c内容:
uint16_t swap(uint16_t num)
{
    return (num >> 8) | (num << 8);
}

void MPU6050_ReadAll(uint16_t *buf)
{
    uint8_t i;
    I2C_Read(MPU6050_ADDR, MPU6050_REG_ACCEL_XOUT_H, (uint8_t *)buf, 14);
    for (i = 0; i < 7; i++)
    {
        *(buf + i) = swap(*(buf + i));
    }
}

MPU6050 设备是以大端模式存储的,即高字节在前,低字节在后,在读取原始数据出来后,将高字节的数据左移8位,再或上低字节的数据。

  • 是否应该这样处理才合理:
uint16_t swap(uint16_t num)
{
	 return (num << 8);
}

void MPU6050_ReadAll(uint16_t *buf)
{
    uint8_t i;
    I2C_Read(MPU6050_ADDR, MPU6050_REG_ACCEL_XOUT_H, (uint8_t *)buf, 14);
    for (i = 0; i < 7; i++)
    {
        *(buf + i) = swap(*(buf + 2*i))|(*(buf + 2*i+1));
    }
}

Question regarding PWM DAC example

I have been trying out the "pwm_dac_voice" example from the Demo folder on a STC8H8K64U chip, not too sure if I am doing anything wrong but I am just getting screeching noise from pin P1.0 instead of the "fire" alert.

Would anyone have any advice on where I should start looking?

Thanks :)

FwLib_STC8\src\fw_i2c.c封装函数简化想法

  • 针对读取AT24Cxx函数简化,对于AT24C32以下容量的读写是8位地址,AT24C32及以上容量的16位地址位,直接使用宏来区分所需操作的AT24Cxx器件的地址位。可以将现有区分的读写操作函数,合成通用的读写函数。

源文件:FwLib_STC8\src\fw_i2c.c

// Copyright 2021 IOsetting <iosetting(at)outlook.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "fw_i2c.h"


uint8_t I2C_Write(uint8_t devAddr, uint8_t memAddr, uint8_t *dat, uint16_t size)
{
    SFRX_ON();
    I2C_MasterStart();
    I2C_MasterSendData(devAddr & 0xFE);
    I2C_MasterRxAck();
    I2C_MasterSendData(memAddr);
    I2C_MasterRxAck();
    while(size--)
    {
        I2C_MasterSendData(*dat++);
        I2C_MasterRxAck();
    }
    I2C_MasterStop();
    SFRX_OFF();
    return HAL_OK;
}

uint8_t I2C_Read(uint8_t devAddr, uint8_t memAddr, uint8_t *buf, uint16_t size)
{
    SFRX_ON();
    I2C_MasterStart();
    I2C_MasterSendData(devAddr & 0xFE);
    I2C_MasterRxAck();
    I2C_MasterSendData(memAddr);
    I2C_MasterRxAck();
    I2C_MasterStart();
    I2C_MasterSendData(devAddr | 0x01);
    I2C_MasterRxAck();
    while(size--)
    {
        I2C_SendMasterCmd(I2C_MasterCmd_Recv);
        *buf++ = I2CRXD;
        if (size == 0)
        {
            I2C_MasterNAck();
        }
        else
        {
            I2C_MasterAck();
        }
    }
    I2C_MasterStop();
    SFRX_OFF();
    return HAL_OK;
}

uint8_t I2C_Write16BitAddr(uint8_t devAddr, uint16_t memAddr, uint8_t *dat, uint16_t size)
{
    SFRX_ON();
    I2C_MasterStart();
    I2C_MasterSendData(devAddr & 0xFE);
    I2C_MasterRxAck();
    I2C_MasterSendData(memAddr >> 8);
    I2C_MasterRxAck();
    I2C_MasterSendData(memAddr & 0xFF);
    I2C_MasterRxAck();
    while(size--)
    {
        I2C_MasterSendData(*dat++);
        I2C_MasterRxAck();
    }
    I2C_MasterStop();
    SFRX_OFF();
    return HAL_OK;
}

uint8_t I2C_Read16BitAddr(uint8_t devAddr, uint16_t memAddr, uint8_t *buf, uint16_t size)
{
    SFRX_ON();
    I2C_MasterStart();
    I2C_MasterSendData(devAddr & 0xFE);
    I2C_MasterRxAck();
    I2C_MasterSendData(memAddr >> 8);
    I2C_MasterRxAck();
    I2C_MasterSendData(memAddr & 0xFF);
    I2C_MasterRxAck();
    I2C_MasterStart();
    I2C_MasterSendData(devAddr | 0x01);
    I2C_MasterRxAck();
    while(size--)
    {
        I2C_SendMasterCmd(I2C_MasterCmd_Recv);
        *buf++ = I2CRXD;
        if (size == 0)
        {
            I2C_MasterNAck();
        }
        else
        {
            I2C_MasterAck();
        }
    }
    I2C_MasterStop();
    SFRX_OFF();
    return HAL_OK;
}
  • 简化通用操作函数:
#include "fw_i2c.h"

/* EERPOM DATA ADDRESS Length Definition */
#define Address_8bit  0
#define Address_16bit  1
/* EERPOM DATA ADDRESS Length Selection */
//#define Address_Lenth   Address_8bit
#define Address_Lenth   Address_16bit

uint8_t I2C_Write(uint8_t devAddr, uint8_t memAddr, uint8_t *dat, uint16_t size)
{
    SFRX_ON();
    I2C_MasterStart();
    I2C_MasterSendData(devAddr & 0xFE);
    I2C_MasterRxAck();
#if (Address_Lenth  == Address_8bit)
    I2C_MasterSendData(memAddr);
    I2C_MasterRxAck();
#elif (Address_Lenth  == Address_16bit)
 I2C_MasterSendData(memAddr >> 8);
    I2C_MasterRxAck();
    I2C_MasterSendData(memAddr & 0xFF);
    I2C_MasterRxAck();
 #endif   
    while(size--)
    {
        I2C_MasterSendData(*dat++);
        I2C_MasterRxAck();
    }
    I2C_MasterStop();
    SFRX_OFF();
    return HAL_OK;
}

uint8_t I2C_Read(uint8_t devAddr, uint8_t memAddr, uint8_t *buf, uint16_t size)
{
    SFRX_ON();
    I2C_MasterStart();
    I2C_MasterSendData(devAddr & 0xFE);
    I2C_MasterRxAck();
    #if (Address_Lenth  == Address_8bit)
    I2C_MasterSendData(memAddr);
    I2C_MasterRxAck();
    I2C_MasterStart();
    I2C_MasterSendData(devAddr | 0x01);
    I2C_MasterRxAck();
    #elif (Address_Lenth  == Address_16bit)
    I2C_MasterSendData(memAddr >> 8);
    I2C_MasterRxAck();
    I2C_MasterSendData(memAddr & 0xFF);
    I2C_MasterRxAck();
    I2C_MasterStart();
    I2C_MasterSendData(devAddr | 0x01);
    I2C_MasterRxAck();
     #endif  

    while(size--)
    {
        I2C_SendMasterCmd(I2C_MasterCmd_Recv);
        *buf++ = I2CRXD;
        if (size == 0)
        {
            I2C_MasterNAck();
        }
        else
        {
            I2C_MasterAck();
        }
    }
    I2C_MasterStop();
    SFRX_OFF();
    return HAL_OK;
}

Endianness problem when using SDCC

The SDCC apply different endianness when accessing variable more than 1 byte. The SDCC apply little-endian which is different from KEIL C51's big-endian (https://stackoverflow.com/a/2477501) . Using memory map 16bit register, like #define PWMA_CCR4 (*(unsigned int volatile __XDATA *)0xfedb), will encounter problem. Because 16bit registers are big-endianness.

Endianness issue in USB demo when compiled by SDCC

Here the code apply intentional endianness swap due to KEIL C51 using big endian. But SDCC using small endian so no intentional swap is needed.

((uint8_t *)&usb_ep0_stag.wResidue)[0] = usb_request.wLength.bb.bh;
((uint8_t *)&usb_ep0_stag.wResidue)[1] = usb_request.wLength.bb.bl;

Further more if you do not modify the __CODE and __XDATA marco the code can not be compiled by SDCC.

串口2无法打印问题

  • 串口2demo:FwLib_STC8\FwLib_STC8\demo\uart\uart2_timer2_tx.c

在使用串口2的情况下必须要对IO进行配置,否则无法输出。在STC8H手册上(321页)有这么一段话:
*** 关于 I/O 的注意事项:
1、 P3.0 和 P3.1 口上电后的状态为弱上拉/准双向口模式
2、 除 P3.0 和 P3.1 外,其余所有 IO 口上电后的状态均为高阻输入状态,用户在使用 IO 口
前必须先设置 IO 口模式
3、 芯片上电时如果不需要使用 USB 进行 ISP 下载, P3.0/P3.1/P3.2 这 3 个 I/O 口不能同时
为低电平,否则会进入 USB 下载模式而无法运行用户代码
4、 芯片上电时,若 P3.0 和 P3.1 同时为低电平, P3.2 口会短时间由高阻输入状态切换到双
向口模式,用以读取 P3.2 口外部状态来判断是否需要进入 USB 下载模式。


所以在使用串口2时,需要对串口2的引脚进行配置。
`
void main(void)
{
// SYS_SetClock();//SDCC编译器使用
// UART2, baud 115200, baud source Timer2, 1T mode, no interrupt
// P_SW2 |= 0x80;//使能访问 XFR
// P4M0=0x00;
// P4M1=0x00;
P1M0=0x00;//准双向
P1M1=0x00;
// P_SW2 |= 0x00; //RXD2/P1.0, TXD2/P1.1
// P_SW2 |= 0x01; //RXD2_2/P4.6, TXD2_2/P4.7
UART2_Set8bitUART();
UART2_Config(HAL_State_ON, 115200);
UART2_TxString("Uart Test !\r\n");
while(1)
{
UART2_TxChar('T');
UART2_TxHex(0x41);
UART2_TxString("U");
UART2_TxString(" string\r\n");
SYS_Delay(1000);
}
}

`

USB Clocking

Can USB be clocked from an external oscillator in STC8H8K64U?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.