SDCC 如何获取内部基准电压的值 | 问 doubao.com
用sdcc 一直无法获取到内部基准电压的值,而用keil c51 就没问题,
求助sdcc 该如何获取 idata 和 code 存储器存储的值?
{:4_196:}
你在 DEEPSEEK.COM / DOUBAO.COM 中问
KEIL C51 语句 如下:
......
SDCC 如何写 我们首先需要将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 系列芯片的内部参考电压。
【四合一】分享一个可同时编译Keil C251\Keil C51\SDCC\IAR工程模板 - SDCC, IAR C++ for 51, GCC, VSCode,Linux, MacOS 国芯人工智能技术交流网站 - AI32位8051交流社区
页:
[1]