zrislyvg 发表于 2026-1-2 09:41:35

SDCC 如何获取内部基准电压的值 | 问 doubao.com

用sdcc 一直无法获取到内部基准电压的值,
而用keil c51 就没问题,
求助sdcc 该如何获取 idata 和 code 存储器存储的值?
{:4_196:}

神农鼎 发表于 2026-1-2 10:29:01

你在 DEEPSEEK.COM / DOUBAO.COM 中问

KEIL C51 语句 如下:
......

SDCC 如何写

angmall 发表于 2026-1-4 22:08:15

我们首先需要将Keil C51的代码转换为SDCC的代码。主要注意以下几点:

头文件:SDCC中通常使用#include <8051.h>或对应芯片的头文件,但这里我们使用STC8H,可能需要特定的头文件,但原代码使用的是reg51.h,我们可能需要替换为SDCC兼容的STC8头文件,或者使用通用方法。

特殊功能寄存器(SFR)的定义:在SDCC中,SFR的定义方式与Keil不同。SDCC使用__sfr、__sbit等关键字,或者使用绝对地址定位。

中断函数:SDCC中使用__interrupt关键字,并且中断号可能有所不同。

内存空间:在Keil中,使用code关键字表示程序存储区,而在SDCC中,使用__code或者const,并且访问方式可能不同。

位变量:SDCC支持位变量,但声明方式可能不同,使用__bit。

由于原代码中使用了STC8G1K08等芯片的内部参考电压地址,这些地址位于代码区(code),在SDCC中访问代码区需要使用__code关键字。

另外,原代码中定义了一个指向int的指针BGV,并将其指向代码区的某个地址。在SDCC中,我们需要将BGV声明为指向__code int的指针。

由于SDCC的标准库中没有intrins.h,但原代码中并没有使用该头文件中的函数,所以可以去掉。

我们假设使用SDCC编译STC8系列芯片,并且使用对应的头文件。但是,如果没有合适的头文件,我们可以使用绝对地址定义SFR。

下面我们开始转换:

步骤:

替换头文件:由于SDCC没有reg51.h,我们可以使用8051.h,但为了支持STC8的扩展SFR,我们需要自定义SFR。

定义SFR:使用__sfr定义AUXR以及PxM0、PxM1。

修改中断函数为SDCC格式。

修改BGV的声明,使用__code int *。

修改主函数中的初始化部分。

注意:SDCC中,中断函数使用__interrupt(中断号)的方式,且中断号可能与Keil不同。对于UART中断,在51系列中通常是中断4,但需要确认。

由于原代码是针对STC8G1K08,我们假设使用SDCC编译,并且使用large或huge模式,因为代码地址可能超过2K。

下面给出转换后的代码:

以下是转换后的 SDCC 代码:


#include <8051.h>
#include <stdint.h>

#define FOSC      11059200UL
#define BRT         (65536 - FOSC / 115200 / 4)

// 定义特殊功能寄存器
__sfr __at (0x8E) AUXR;
__sfr __at (0x93) P0M1;
__sfr __at (0x94) P0M0;
__sfr __at (0x91) P1M1;
__sfr __at (0x92) P1M0;
__sfr __at (0x95) P2M1;
__sfr __at (0x96) P2M0;
__sfr __at (0xB1) P3M1;
__sfr __at (0xB2) P3M0;
__sfr __at (0xB3) P4M1;
__sfr __at (0xB4) P4M0;
__sfr __at (0xC9) P5M1;
__sfr __at (0xCA) P5M0;

__bit busy;
uint16_t __code *BGV;// 指向代码存储区的指针

void UartIsr() __interrupt(4)
{
    if (TI)
    {
      TI = 0;
      busy = 0;
    }
    if (RI)
    {
      RI = 0;
    }
}

void UartInit()
{
    SCON = 0x50;
    TMOD = 0x00;
    TL1 = BRT;
    TH1 = BRT >> 8;
    TR1 = 1;
    AUXR = 0x40;
    busy = 0;
}

void UartSend(char dat)
{
    while (busy);
    busy = 1;
    SBUF = dat;
}

void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;

    // 根据芯片型号选择正确的地址
    BGV = (uint16_t __code *)0x1FF7;   // STC8G1K08
    // BGV = (uint16_t __code *)0x3FF7;   // Ai8H1K16
    // BGV = (uint16_t __code *)0x7FF7;   // Ai8H8K32U
    // BGV = (uint16_t __code *)0xBFF7;   // Ai8H8K48U
    // BGV = (uint16_t __code *)0xEFF7;   // Ai8H8K60U
    // BGV = (uint16_t __code *)0xFDF7;   // Ai8H8K64U
    // BGV = (uint16_t __code *)0x2FF7;   // Ai8H1K12
    // BGV = (uint16_t __code *)0x43F7;   // Ai8H1K17
    // BGV = (uint16_t __code *)0x5FF7;   // Ai8H1K24
    // BGV = (uint16_t __code *)0x6FF7;   // Ai8H1K28
    // BGV = (uint16_t __code *)0x83F7;   // Ai8H1K33

    UartInit();
    ES = 1;
    EA = 1;
   
    // 读取内部1.19V参考信号源
    UartSend(*BGV >> 8);   // 高字节
    UartSend(*BGV);      // 低字节

    while (1);
}





**主要修改点:**

1. **头文件**:
   - 替换 `reg51.h` 为 `8051.h`
   - 替换 `intrins.h` 为 `stdint.h`(用于标准整数类型)

2. **SFR 定义**:
   - SDCC 使用 `__sfr __at (地址)` 语法定义特殊功能寄存器
   - 所有扩展的 SFR 都需要用这种方式定义

3. **位变量**:
   - SDCC 使用 `__bit` 定义位变量

4. **代码区指针**:
   - Keil C51: `int code *`
   - SDCC: `uint16_t __code *`
   - 使用 `uint16_t` 确保处理 16 位数据

5. **编译命令**:
   ```bash
   sdcc -mmcs51 --model-large --stack-auto main.c
   ```
   - `--model-large`:适合较大的 STC8 系列芯片
   - `--stack-auto`:启用自动栈管理

6. **生成的文件**:
   - SDCC 会生成多个文件,主要是 `main.ihx`(Intel HEX 格式)
   - 可以使用 `packihx` 转换为标准 HEX 文件:
   ```bash
   packihx main.ihx > main.hex
   ```

**注意事项:**

1. **芯片型号选择**:根据实际使用的芯片取消注释对应的地址行
2. **头文件路径**:确保 SDCC 能找到 `8051.h` 头文件
3. **内存模型**:对于 STC8 系列,通常需要 `--model-large` 或 `--model-huge` 选项
4. **中断向量**:SDCC 的中断向量表与 Keil 不同,但 UART 中断号 4 是通用的

这个转换后的代码应该可以在 SDCC 中正常编译和运行,用于读取 STC8 系列芯片的内部参考电压。



ercircle 发表于 2026-1-5 17:46:24

【四合一】分享一个可同时编译Keil C251\Keil C51\SDCC\IAR工程模板 - SDCC, IAR C++ for 51, GCC, VSCode,Linux, MacOS 国芯人工智能技术交流网站 - AI32位8051交流社区
页: [1]
查看完整版本: SDCC 如何获取内部基准电压的值 | 问 doubao.com