创隆科技 发表于 2024-5-10 16:22:52

C251(KEIL5)和C51(KEIL4),写程序要注意那些问题?两者有啥不同

以前用Keil4写8位单片机程序时发现“随心所欲”例如
voidting ()
{
   unsigned char code SJH[]=
   {
         0x00,…………………
      
      };
}
这段程序用到8位单片机(KEIL4),种运行没有问题
用在KEIL5(32单片机),出现问题卡死在数组中
把数组定义在函数外就没有问题了!
发现KEIL5好严格,例如赋值定时器等寄存器时必须先高八位后低八位,否则就不正常
还有例如s=x<<8+y,KEIL4中可以完成代替
s=x*256+y,
在KEIL5中严格按符号优先级处理,这么写就不行必须是s=(x<<8)+y

本人小学毕业学历,不知道还有哪些严格的东西,
从8位到32位软件特别注意的有哪些!欢迎告知

jwg 发表于 2024-5-10 17:21:53

我小学肄业,一起学习、成长{:4_196:}

soma 发表于 2024-5-10 19:02:36

没涉及到单片机寄存器等的操作,都是编程规范的问题。

jwd 发表于 2024-5-10 20:25:16

stc8h的改stc32按手册来就可以啊

angmall 发表于 2024-5-10 20:42:46

移植 C51 代码的技巧
移植 C51 代码时必须考虑 C51 和 C251 之间的一些细微差别。 以下是您可能遇到的典型问题的列表:

C251 生成的代码独立于当前选择的寄存器组,并且不再需要 C51 指令 NOAREGS 和 REGISTERBANK。
内存类型说明符必须设置在变量类型后面,如下例所示:


int xdata value;    /* correct in both C51 and C251   C51 和 C251 均正确         */
xdata int value;    /* illegal: old C51 form; not supported by C251非法:旧的C51表格; C251 不支持 */



pdata 内存类型通常在 251 MCU 的 PAGE 模式下出现问题,在新应用中应忽略。
printf 库函数和变量参数列表默认提升为 int,即使对于 char 和 unsigned char 变量也是如此。 以下 printf 语句在 C251 中生成不正确的结果。


unsigned char c1;

   /* works in C51, but gives wrong output in C251:在 C51 中工作,但在 C251 中给出错误的输出:      */
printf ("%bx %bi", c1, 1);

   /* C251 defaults to int and does not need the b prefix:C251默认为int,不需要b前缀:*/
printf ("%x %i", c1, 1);

   /* the following two forms work in both C51 and C251:以下两种形式在 C51 和 C251 中均适用:*/
printf ("%bx %bi", (unsigned char) c1, (char) 1);/* optimal code */
printf ("%x %i", (unsigned int) c1, (int) 1);      /* passes int   */



const 常量
在 ANSI C 中,const 类型限定符用于定义和访问常量且不可更改的对象。 用 const 声明的变量不能在程序中赋值。

C251 编译器符合 const 对象的 ANSI 定义。

单独使用 const 类型限定符声明的变量存储在与其定义关联的内存区域(data、idata、xdata 等)中。
要在 ROM 中定位的变量必须使用代码内存类型进行声明。 例如:

code char test[] = "This is a text string";

用 const 声明的变量存储在 xCONST 内存类中(内存类型 data、idata、xdata 除外)。 有关详细信息,请参阅段命名约定。

对于使用 const 声明的变量,编译器会生成存储在 ROM 中的映像。 不会为此类变量生成运行时初始化记录。

常量对象通常在定义时(在源文件中)进行初始化。 以下变量定义显示了创建常量对象的不同方法:

/* table is stored in the default memory class */
const int table =
{ 0, 2, 4, 8 };

/* pi is stored in the HCONST memory class */
const float far pi = 3.1415927;

/* The string is stored in the HCONST memory class */
printf("This is a string\n");

当使用指向 const 对象的指针时,可以在指针定义中排除 const 类型限定符。 例如:

const unsigned char mask [] =
{ 0x01, 0x02, 0x04, 0x08 };

const unsigned char *cp = mask;
      unsigned char*p = mask;/* same as cp */

.
.
.

*p = 'a';    // This has no effec.
             // It causes no error or warning

*cp = 'a';   // This causes an error


如上所示,可以将 const 对象(mask)的地址分配给非常量指针(p),然后使用该指针更改 const 对象。 在这种情况下,编译器确实会生成写入 const 对象的代码。 此代码的效果未定义,可能会或可能不会按预期工作。

不可能使用 const 指针来更改它指向的 const 对象。 尝试这样做将导致编译器错误。

const 的一个有趣的用途是定义一个不可更改的指针。 例如:

char text [] = "This is a string.";
char *const textp = text;
.
.
.
*textp = 'A';    // This is OK (it changes text)
textp++;         // This causes an error (textp is const)
textp = 'B';// This is OK (it changes text)

wan123456 发表于 2024-5-10 21:30:41

对着手册避开差异就行了…

小飞侠 发表于 2024-5-11 07:34:46

死机是不是数组占用内存溢出了

创隆科技 发表于 2024-5-12 22:52:21

angmall 发表于 2024-5-10 20:42
移植 C51 代码的技巧
移植 C51 代码时必须考虑 C51 和 C251 之间的一些细微差别。 以下是您可能遇到的典型 ...

谢谢你的付出,又学习了点
也提醒大家从8位到32位的朋友
1.寄存器赋值严格做到先赋值高八位
再赋值低八位
2.函数名哪怕是乱写,也不要和单片机头文件里已经定义的名字一样
3.定义在程序区的数组,一定要先在使用函数外定义好再使用,否则用不了卡死在数组里

创隆科技 发表于 2024-5-12 22:54:31

小飞侠 发表于 2024-5-11 07:34
死机是不是数组占用内存溢出了

不是,改为临时变量型数组也可以,或在函数外先定义好也可以

angmall 发表于 2024-5-13 08:01:46

创隆科技 发表于 2024-5-12 22:52
谢谢你的付出,又学习了点
也提醒大家从8位到32位的朋友
1.寄存器赋值严格做到先赋值高八位


很高兴能帮助到你。
页: [1] 2
查看完整版本: C251(KEIL5)和C51(KEIL4),写程序要注意那些问题?两者有啥不同