写KeilC遇到的坑

写KeilC遇到的坑

1、跟vs中不同,keilC中的的变量必须声明在最前,不然就出错。

2、KeilC中的错误提示功能实在是很弱。没有办法精确到具体是哪个具体的变量或标点符号出问题。

3、KeilC中的unsigned int能表示的数太小,只能有五位数,导致烧到单片机上的时候,数码管显示有问题。

unsigned char,8位,最大值255
unsigned int,16位,最大值65535

4、8针的引脚只要用unsigned char就可以控制,因为unsigned char 是8位的。

5、在LCD1602输出了脏数据。

 1 #include<reg51.h>
 2 #define uchar unsigned char
 3 #define uint unsigned int
 4 uchar code table[]="Hello World!";
 5 uchar code table1[]="I am a boy!";
 6 ///此处省略了一系列的函数定义
 7 void main()
 8 {
 9         int num;
10     init();
11     write_command(0x80+0x10);
12     for(num=0;num<20;num++)
13     {
14         write_data(table[num]);
15         delay(5);
16     }
17     //此处省略了一些无关内容
18 }

在以上代码段中,我们期望在LCD1602的第一行输出”Hello World!       “,注意这个输出后面是空白的,但是输出了”Hello World!       **** I am a”(***代表乱码)。这就有点无奈了。调了好久,一开始以为是ram里面有暂存的数据,单片机断电后,再试还是不行。后面联想到编译原理中,两个字符串table和table1都是用code定义的数组,他们存储位置是程序存储器。又因为table1定义的位置正好在table的下面,所以当以上代码行12对应处遍历table数组超出table本身的索引时,自然就输出了table1的内容,从而造成脏数据。

 

6、头文件的定义。

①当我们定义头文件的时候,最后不要在头文件里面定义define uchar unsigned char 这类的东西,因为当引用了两次头文件或者不同的头文件里面都有同样的define的时候,程序会出问题。

②当定义头文件的时候,为了避免二次引用造成重复定义,最好在头文件上#ifndef __I2C_H__  #define __I2C_H__ 、#endif(其中__I2C_H__是自己定义的一个名称如以下代码段所示参考链接

 

 1 #ifndef __I2C_H__
 2 #define __I2C_H__
 3 
 4 //========函数区============================================
 5 extern void I2C_start();  //开始信号
 6 extern void I2C_stop();   //停止
 7 extern void I2C_respons();  //应答
 8 extern void I2C_write_byte(unsigned char date);
 9 extern unsigned char I2C_read_byte();
10 extern void I2C_write_address(unsigned char address,unsigned char date);
11 extern unsigned char I2C_read_address(unsigned char address);
12 //========函数区结束============================================
13 #endif

 

 7、按键反应很慢。

下面的程序是一个按下独立按键,然后在LED屏幕上显示当前计数值的程序。程序要实现:当按下独立按键1的时候,等待。当再次按下,程序往下运行。我发现当我按下,程序可以很快地反应;但是再次按下想让他运行的时候,却要等待大概3~5秒的时间。细看以下代码段加灰的地方和中断函数,终于发现了原因。原来,当忙等待的时候,中断函数int0()中的Count还在不断计数,也就是Count可能大于20,那么就不满足Count==20这个条件。而要等再次满足Count==20,则要等待Count计满重新归零(注意Count是无符号数,无符号数计满的时候自动归零)。

#include<reg51.h>
unsigned char Count=0;
/***********************************************************
    重新计数
***********************************************************/
void ReCount(){
    Count=0;  //开始下一轮1s的计时
    TH0=T_High_50ms;// 计算初值,并将其写入TH0、TL0或TH1、TL1。
    TL0=T_Low_50ms;
}
void main()
{
    
//去掉不必要的初始化函数
while(1){
Waiting();
//一个忙等待函数,当按下独立按键1的时候,等待。当再次按下, //程序往下运行 if(Count==20){ //定时器0 1s时间到 ReCount(); //……省略做其他事情的函数 } } } void int0() interrupt 1//定时/计数器T0中断 { Count++; }

 8、强制转化的问题

除了强制转化成bit型是取高位外(代码段1),其他从位数少到位数多类型的强制类型转换都是取低位。

 1 unsigned char aChar=0x00;//除了强制转化成bit型是取高位外
 2 unsigned int aInt=0xaa55;
 3 aChar=(unsigned char)aInt;
 4 //结果:aChar=0x55
 5 
 6 ///
 7 bit aBit;
 8 unsigned char aChar=0x01; //其他从位数少到位数多类型的强制类型转换都是取低位。
 9 aBit=(bit)aChar;
10 //结果:aBit=0;

9、全局变量定义在头文件(*.h)或源文件(*.c)的思考。

看了一些代码,似乎在头文件的定义中都尽量地避免了对全局变量的定义。我想头文件是给人引用的,也就是这部分的内容必须暴露,为了函数的封装性更好,更好的方法就是将全局变量尽可能封装在源文件 (*.c)。这样,使用者不会因为头文件中含有全局变量而感到困惑,也不用因为全局变量而去了解整个C语言函数库的实现细节。

10、C#和Java都是支持函数的重载的,但是C语言中不支持函数的重载。

1 int add(int a,int b);             //函数1
2 int add(int a,int b,int c);       //函数2

C语言中,如果你定义了函数1,那么就不能再定义函数2.不然编译就不通过了。究其原因,可能是因为C语言中有函数指针这东西(见一下代码段,重载会让C编译器不知道将哪个函数地址赋给函数指针)。

#include <stdio.h>
int add(int a,int b);
//int add(int a , int b , int c);
int sub(int a,int b);
void result(int (* pf)() , int a , int b);
main(){
   int i,j=1;
   int (* pf)();
   pf=add;        //这里如果重载了add函数,那么这里编译器就不知道要把哪个add
   result(pf,i,j);//赋值给pf
   pf=sub;
   result(pf,i,j);
}

int add(int a , int b){
     return a+b;
}
int sub(int a,int b){
     return a-b;
}
void result(int (*pf)() , int a , int b){
   int value;
   value = (*pf)(a , b);
   printf("%d\t",value);
}

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/110120.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • webstorm好用的插件_谷歌浏览器插件推荐

    webstorm好用的插件_谷歌浏览器插件推荐安装插件codeglance可以实现VSCode的右侧小地图

    2022年9月8日
    2
  • excel.workbook函数(使用java实现记事本(超详细解释))

    excel.workbook函数(使用java实现记事本(超详细解释))1、异常java.lang.NoClassDefFoundError:org/apache/poi/UnsupportedFileFormatException  解决方法:使用的poi的相关jar包一定版本一定要相同!!!!!2、maven所使用jar包,没有使用maven的话,就用poi-3.9.jar和poi-ooxml-3.9.jar(这个主要是用于Excel2007以后的版本…

    2022年4月18日
    256
  • js垃圾处理机制_java中垃圾回收有什么目的

    js垃圾处理机制_java中垃圾回收有什么目的文章目录前置知识堆栈栈堆执行上下文与作用域链执行上下文作用域链一、JavaScript中怎么被定义为垃圾使用局部变量使用对象概括二、两种回收策略标记清理引用计数概括三、什么时候执行垃圾回收关于ChromeV8引擎的GC分代回收指针与活跃对象的区分回收的执行周期四、内存问题五、Es6WeakMap参考文章前置知识堆栈栈什么是栈栈其实是一种数据结构,有着先进后出,后进先出的特性,用生活中的事物来理解最形象的就是汉诺塔了。我们在栈中存储的数据就像汉诺塔的盘子一样,最先放进去在最下面,最后放入的盘.

    2022年10月9日
    2
  • excel vba 解密

    excel vba 解密PrivateSubVBAPassword()’你要解保护的Excel文件路径Filename=Application.GetOpenFilename(“Excel文件(*.xls&*.xla&*.xlt),*.xls;*.xla;*.xlt”,,”VBA激活成功教程”)IfDir(Filename)=””ThenMsgBox”没找到相关文件,清重新设置。”

    2022年6月28日
    48
  • android缩放动画中心缩放_安卓动画缩放调到多少比较好

    android缩放动画中心缩放_安卓动画缩放调到多少比较好什么是ScaleAnimationScaleAnimation即缩放动画,应用场景特别多,比如常见的隐藏菜单点击显示下面我分两种方式来介绍ScaleAnimation如何使用。1.xml文件形式文件名:anim_scale_in.xml效果:呈现view放大显示效果源码:<?xmlversion=”1.0″encoding=”utf-8″?><setxmlns:android=”http://schemas.android.com/apk/res/

    2022年10月15日
    3
  • 线程 、进程、协程 三者区别

    线程 、进程、协程 三者区别

    2021年11月10日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号