初试AI8051U,感觉251指令比51强大很多,可惜被Keil限制了手脚。
keil c51用着一直没问题,c251用一下感觉让人有点怀疑。有几个小例子请专家帮忙指点
问题1
void test1(void)
{
unsigned char i8;
unsigned int i16;
unsigned long i32;
i8 = 255;
i16 = 12345;
i32 = 70000;
printf("%bu %u %lu\n", i8, i16, i32);
}
上面的printf输出结果是错误的,printf的参数u8类型不可用%bu输出,会导致后续所有输出出错。
u8和u16均用%d才可正确输出。
在c51中,单字节变量在printf中要用%bd。C251即使弃用b前缀也可以,但是在keil c251的帮助文件和例子中,都是规定用%bd。
Note
[*]The optional characters l or L may immediately precede the type character to respectively specify long types for d, i, u, o, x, and X.
[*]The optional characters b or B may immediately precede the type character to respectively specify char types for d, i, u, o, x, and X.
问题2
函数内局部变量不能用code属性。
void test(void)
{
unsigned char code TAB = {1,2,3,4,5,6,7,8};
unsigned char i, value;
for(i=0; i<8; i++)
{
value = TAB;
printf("TAB[%d] = %d\n", i, value);
}
}
上述程序在C51中运行无问题,在C251中编译通过但运行出错,看C编译后的汇编代码就很离谱,其向FF地址区域即CODE区域写数据。
将这句unsigned char code TAB = {1,2,3,4,5,6,7,8};放在函数外,即变为全局变量,结果就对了。
另外,在函数内用const unsigned char TAB = {1,2,3,4,5,6,7,8};这样运行结果是对的,但是不会将数组放在code区,而是放在data区然后用代码逐个赋初值。
问题3
sbit LED1 = P1^0;
LED1 = !LED1;
LED1 = ~LED1;
关于两种取反的区别,之前已有专家提过了,这里就不多做解释了。
感觉现在STC,内部人才济济,能够做出异常强大的芯片设计,但受限于编译器落后,很多技能无法施展。
C51好歹有bug还修复一下。 从 SDCC-AI8051U-8Bit 出发,到 SDCC-AI8051U-32Bit
===总会有代替 KEIL C251 的路
C51 C251没有long long类型,32位整数乘以32位整数结果只保留低32位。
MDU32应该是为了兼容keil的接口,把MDU32的设计也带偏了。
32位*32位结果应该是64位,丢弃高32位,只保留低32位,算得再快也没用。
就比如1位数乘1位数,结果应该保留十位和个位。
只保留1位结果,
就像9 x 9 = 1;(81保留个位)
7 x 8 = 6;(56保留个位)
结果不对,没啥价值。 第2个问题应该这样:const unsigned char code TAB = {1,2,3,4,5,6,7,8};
251架构和51不同,code空间也是可写的,想不可写就要加const,完全用51的方式代入就可能会出错 code区域可写应该不可能。这种情况编译器直接在常量区定义数据就可以,没必要编译出来一大坨代码。 health 发表于 2024-8-30 18:04
code区域可写应该不可能。这种情况编译器直接在常量区定义数据就可以,没必要编译出来一大坨代码。 ...
没什么不可能,251指令集架构是可以写code代码区的,甚至RAM区也可以运行代码 code区只是指FF0000-FFFFFF这段区域,这段区域在251架构中又没规定不可写,并且还提供有可写指令,以前无内置闪存的251这段区域就是可写的 本帖最后由 health 于 2024-8-30 19:50 编辑
keil软仿真,如果写ROM区域,它会报错,停在那里。
实物芯片没法弹出窗口报错,一般就忽略过去。 感觉C251强大,但是BUG有点多啊
页:
[1]
2