0、
起因是最近在玩AMOLED屏幕的时候,由于它的SH8501A芯片只支持竖屏显示,所以尝试自己写转换成横屏的显示程序。
竖屏转换横屏的过程涉及到了坐标转换,其中于是需要对设置区域的函数进行修改
void LCD_Address_Set_H( uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye )
{
uint16_t xsH, xeH, ysH, yeH;
ys = (ys+3)/4*4;
ye = (ye+3)/4*4-1;
xsH = 119 - ye; /* 新左上角 x */
xeH = 119 - ys; /* 新右下角 x */
ysH = xs; /* 新左上角 y */
yeH = xe; /* 新右下角 y */
/* 以下省略 */
}
结果在编译这个函数的时候,Keil(C51和C251)都报错:error C11: internal error: (asmgen - triple=t030)
1、
将函数代码和错误提示发给AI助手
立刻指出了问题所在:原因不是出在代码上,而是 Keil编译器的内部BUG
从函数 LCD_Address_Set_H 触发了 asmgen 的编译器 bug该函数独有的特征是: - 声明了 4 个额外的局部变量 xsH, xeH, ysH, yeH;
- 还声明了 tmp;
- 同时又要调用 LCD_WR_REG / LCD_WR_DATA8 这类带形参的函数;
- 变量在 8 位机上做 16 位减法赋值。
局部变量 + 形参 + 函数调用 + 16 位运算这一组合,触发了 Keil C51 版本特有的 asmgen triple 分配 bug(triple=t01C 就是编译器内部临时寄存三元组编号),编译器在给临时值分配寄存器/存储时算错了,于是抛出 internal error。 也就是说:这是 Keil C51 编译器(特定版本)的 bug,不是您代码的 bug。
并且还给出了解决方法
方法 1:改写为等价但更"编译器友好"的形式把临时中间量显式拆开,避免编译器自己做复杂的临时分配,例如: tmp = 119 - ye;xsH = tmp;tmp = 119 - ys;xeH = tmp;ysH = xs;yeH = xe;📋
方法 2:把 4 个局部变量"提升"为函数入参的就地运算模仿 LCD_Address_Set 的写法,直接对参数赋值,减少局部变量数量: void LCD_Address_Set_H(uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye){ uint16_t tmp; tmp = xs; // 暂存原 xs xs = 119 - ye; // 新左上角 x ye = xe; // 新右下角 y xe = 119 - ys; // 新右下角 x ys = tmp; // 新左上角 y LCD_WR_REG(0x2A); ...}
[td]问题 | 回答 | | 119 - ye 写法错了吗? | 没错,是合法 C 语句 | | 为什么主函数能写、从函数报错? | 因为报错是 Keil 编译器 internal error(asmgen bug),由两函数不同的局部变量/临时值结构触发,不是这行算式的语法差异 | | 怎么解决? | 用 tmp 拆开中间量、减少局部变量、升级编译器版本,或将该函数独立成文件 |
引用两种方法的代码,均顺利通过并正常运行。
2、
既然AI助手提到了编译器,于是把函数放进STC-IDE里试了一下,结果顺利编译通过了。
按照AI助手的解释
为什么换成 STC-IDE 就不报错了?关键在于 编译器后端不同: [td]编译环境 | 编译器 | 结果 | | Keil(旧版 C51) | Keil C51 | 触发 asmgen 内部 bug,报 error C11: internal error (asmgen - triple=t01C) | | STC-IDE | 内置/更新的编译工具链 | 正常编译通过
|
给您的两点建议继续使用 STC-IDE 即可,这也正是我们 STC 官方推荐并持续维护的开发环境,内置的编译器经过验证,能避开这类历史遗留的编译后端 bug。 如果您出于某些原因仍要在 Keil 下编译,可以用前面提到的规避方法:
- 把中间量用 tmp 显式拆开(您注释里那两版写法就是这个思路);
- 或减少局部变量、直接对形参就地赋值;
- 或升级 Keil C51 版本。
补充一点:如果您的工程最终目标芯片是 STC32G / STC32G144K246 这类 32 位 MCU,那么在 Keil 下应使用 Keil C251 编译(不是 C51),C251 的代码生成机制与 C51 完全不同,一般也不会出现 C51 这种 asmgen bug。而 STC-IDE 对 C51 和 C251 工程都能很好地支持。
总之,您遇到的报错不是代码写错了,换用 STC-IDE 后能正常编译就是最好的证明。👍
========================================================================
3、
针对这个问题,又写了一个相同结构的函数进行了实验
uint16_t TEST( uint16_t a, uint16_t b )
{
uint16_t c, d;
c = 10-a;
d = 10-b;
return c + d;
}
结果在Keil里编译,会报出同样的错误提示
而在 STC-IDE里则同样可以编译通过
顺便还发现了一个惊喜的地方,【自动改写】功能
当把这个函数的数据类型替换为无符号字符型
在编译的时候,居然自动对代码进行了修正
并且还指出了可能存在的隐患,以及更正方案的说明
简直太贴心了 
引用AI助手的说法:
“ STC-IDE(您已验证可行)——这也是当前最省心的方式,STC 官方持续维护,能规避这类历史遗留的工具链问题。”
|