yuanquan12345
发表于 2015-4-24 11:40
收藏学习。谢谢。
AFCA
发表于 2015-4-24 15:11
ok!!!!!!!!!!!!!
zhang2015yi
发表于 2015-4-28 09:52
赞
liuziyue
发表于 2015-4-28 20:43
ucuo
lrk2016
发表于 2015-4-30 13:42
学习,突然发现要学的太多了,PID,C语言,MATLAB、、、好多好多不会的
jianhong_wu
发表于 2015-5-2 10:59
本帖最后由 jianhong_wu 于 2015-6-3 17:11 编辑
第十六节:加法运算的5种常用格式。 根据上一节的预告,本来这节应该讲判断语句的,但是考虑到后续章节的连贯性,决定先讲运算语法。 在讲运算语法之前,先讲一个我在前面忘了讲的知识点,那就是注释语句。何谓注释语句?在我前面一些章节的main函数中,经观察,发现一个规律,凡是中文解说的文字,要么前面有符号”//”,要么就是被包含在“/*”和”*/”之间。符号“//”和“/**/”都是注释语句。注释语句是用来添加文字备忘,方便程序员阅读**的。在注释语句里的文字是不会被编译器翻译成机器码的,也就是说即使注释里面的文字再多,也不会增加单片机的程序容量,它是被编译器过滤忽略的,仅仅方便程序员做备注文字而已。符号“//”和“/**/”都是注释语句,但应用方面有点小差异。符号“//”是用来注释一行文字。而“/**/”往往是用来注释一段文字,当然“/**/”也可以注释一行文字。但是符号“//”仅仅能注释一行文字,却不能注释一段文字。 讲完注释语句,继续回到本节正题。单片机本身具备了简单的加减乘除运算能力,我们只需要通过C语言调用相关的运算语法,即可指示单片机按我们的要求进行简单的运算。至于内部具体的运算细节我们可以不管,除非是涉及到大数据的运算才需要我们额外编写算法。请先看以下的加法语法格式: “保存变量”=“加数1”+“加数2”+...+“加数N”; 含义是:右边的“加数”与“加数”相加,并且把最终的运算结果赋值给左边的“保存变量”。注意,这里的符号“=”不是等于号的意思,而是赋值的意思。左边的“保存变量”必须是变量,不能是常量,否则编译时会报错。而右边的“加数”既可以是变量,也可以是常量,也可以是“保存变量”本身自己。多说一句,何谓变量和常量?变量就是可以在程序中被更改的,是分配的一个RAM空间。而常量往往就是数字,或者是被分配在ROM空间的一个具体数值。下面根据右边“被加数”与“加数”的不同组合,列出了加法运算的5种常用格式。 第1种:“加数1”是常量,“加数2”是常量。比如:unsigned char a;a=3+15;数字“3”和“15”都是常量。执行上述语句后,保存变量a变成了18。
第2种:“加数1”是变量,“加数2”是常量。比如:unsigned char b;unsigned char x=10;b=x+15;x是变量,“15”是常量。由于原来x变量里面的数值是10,执行上述语句后,保存变量b变成了25。而变量x则保持不变,x还是10。
第3种:“加数1”是变量,“加数2”是变量。比如:unsigned char c;unsigned char x=10;unsigned char y=6;c=x+y;x是变量,y也是变量。由于原来x变量里面的数值是10,y变量里面的数值是6,执行上述语句后,保存变量c变成了16。而变量x和y则保持不变,x还是10,y还是6。
第4种:“加数1”是保存变量本身,“加数2”是常量。比如:unsigned char d=2;d=d+18;d=d+7;d是保存变量,“18”是常量。这类语句有一个特点,具备了自加功能,可以更改自己本身自己的数值。比如原来保存变量d的数值是2,执行“d=d+18;”语句后,d变成了20,接着再执行完“d=d+7;”语句后,d最后变成了27。
第5种:“加数1”是保存变量本身,“加数2”是变量。比如:unsigned char e=2;unsigned char x=10;unsigned char y=6;e=e+x;e=e+y;e是保存变量,x与y都是变量。这类语句有一个特点,具备了自加功能,可以更改自己本身自己的数值。比如原来保存变量e的数值是2,执行“e=e+x;”语句后,e变成了12,接着再执行完“e=e+y;”语句后,e最后变成了18。
现在编写一个程序来练习上述5种格式的加法语句,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
unsigned char a; //定义一个变量a,并且分配了1个字节的RAM空间。
unsigned char b; //定义一个变量b,并且分配了1个字节的RAM空间。
unsigned char c; //定义一个变量c,并且分配了1个字节的RAM空间。
unsigned char d=2; //定义一个变量d,并且分配了1个字节的RAM空间。初始化默认为2.
unsigned char e=2; //定义一个变量e,并且分配了1个字节的RAM空间。初始化默认为2.
unsigned char x=10; //定义一个变量x,并且分配了1个字节的RAM空间。初始化默认为10.
unsigned char y=6; //定义一个变量y,并且分配了1个字节的RAM空间。初始化默认为6.
//第1种:“加数1”是常量,“加数2”是常量。
a=3+15;
//第2种:“加数1”是变量,“加数2”是常量。
b=x+15;
//第3种:“加数1”是变量,“加数2”是变量。
c=x+y;
//第4种:“加数1”是保存变量本身,“加数2”是常量。
d=d+18;
d=d+7;
//第5种:“加数1”是保存变量本身,“加数2”是变量。
e=e+x;
e=e+y;
GuiWdData0=a; //把变量a这个数值放到窗口变量0里面显示
GuiWdData1=b; //把变量b这个数值放到窗口变量1里面显示
GuiWdData2=c; //把变量c这个数值放到窗口变量2里面显示
GuiWdData3=d; //把变量d这个数值放到窗口变量3里面显示
GuiWdData4=e; //把变量e这个数值放到窗口变量4里面显示
/*---C语言学习区域的结束---------------------------------------------------------------------------*/
while(1)
{
initial();
key_service();
display_service();
}
}
如何在坚鸿51学习板上观察a,b,c,d,e这5个变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。上坚鸿51学习板观察程序执行的结果如下:变量a为18。变量b为25。变量c为16。变量d为27。变量e为18。 下节预告:加法的连写和自加运算的简写。(未完待续)
佳人难再得
发表于 2015-5-6 22:21
在莫坛看过吴老师的帖子,感谢分享!
火狐free
发表于 2015-5-8 11:46
好好
jianhong_wu
发表于 2015-5-10 08:06
本帖最后由 jianhong_wu 于 2015-6-3 17:13 编辑
第十七节:连加以及自加运算的简写。 上一节我列举的加法例子中,右边的加数个数都是两个。实际上,C语言规则没有限制加数的个数,它的通用格式如下:“保存变量”=“加数1”+“加数2”+...+“加数N”; 当右边的加数个数超过两个的时候,这种情况就是我所说的“连加”,每个加数的属性没有限定,可以是常量,也可以是变量。比如:a=1+69+102; //加数全部是常量。b=q+x+y+k+r; //加数全部是变量。c=3+x+y+5+k; //加数有的是常量,有的是变量。 连加的运行顺序是,赋值符号“=”右边的加数挨个相加,把每一次的运算结果放在一个临时的隐蔽变量里,这个隐蔽的变量我们看不到,是单片机系统内部参与运算时的专用寄存器,等右边所有的加数连加的计算结果出来后,再把这个隐蔽变量所保存的计算结果赋值给左边的“保存变量”。 讲完了连加的格式,接着讲自加的简写。何谓自加?当右边的加数只要其中有一个是“保存变量”本身时,这种情况就是我所说的“自加”。比如:“保存变量”=“保存变量”+“加数1”;“保存变量”=“保存变量”+“加数1”+“加数2”+...+“加数N”; 当这类自加计算式中,右边的加数有且仅有一个是“保存变量”本身时,那么上述自加计算式可以简写成如下格式:“保存变量”+=“加数1”;“保存变量”+=“加数1”+“加数2”+...+“加数N”; 这种格式就是我所说的自加简写。现在举几个例子如下:d+=6;//相当于d=d+6;e+=x;//相当于e=e+x;f+=18+y+k; //相当于f=f+18+y+k; 这些例子都是很常规的自加简写,再跟大家讲一种很常用的特殊简写。当右边只有2个加数,当一个加数是“保存变量”,另一个是常数1时,格式如下:“保存变量”=“保存变量”+1; 这时候,可以把上述格式简写成如下两种格式:“保存变量”++;++“保存变量”; 这两种格式也是俗称的“自加1”操作。比如:g++;//相当于g=g+1或者g+=1;++h;//相当于h=h+1或者h+=1; 也就是说自加1符号“++”可以在变量的左边,也可以在变量的右边,它们在这里本质是一样的,没有差别。当然,如果是在循环条件语句中,这时自加1符号“++”在左边还是在右边是有一点点微弱的差别,这方面的内容以后再讲。
现在编写一个程序来练习刚才讲到的内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
unsigned char a; //定义一个变量a,并且分配了1个字节的RAM空间。
unsigned char b; //定义一个变量b,并且分配了1个字节的RAM空间。
unsigned char c; //定义一个变量c,并且分配了1个字节的RAM空间。
unsigned char d=5; //定义一个变量d,并且分配了1个字节的RAM空间。初始化默认为5.
unsigned char e=5; //定义一个变量e,并且分配了1个字节的RAM空间。初始化默认为5.
unsigned char f=5; //定义一个变量f,并且分配了1个字节的RAM空间。初始化默认为5.
unsigned char g=5; //定义一个变量g,并且分配了1个字节的RAM空间。初始化默认为5.
unsigned char h=5; //定义一个变量h,并且分配了1个字节的RAM空间。初始化默认为5.
unsigned char q=1; //定义一个变量q,并且分配了1个字节的RAM空间。初始化默认为1.
unsigned char x=3; //定义一个变量x,并且分配了1个字节的RAM空间。初始化默认为3.
unsigned char y=6; //定义一个变量y,并且分配了1个字节的RAM空间。初始化默认为6.
unsigned char k=2; //定义一个变量k,并且分配了1个字节的RAM空间。初始化默认为2.
unsigned char r=8; //定义一个变量r,并且分配了1个字节的RAM空间。初始化默认为8.
//第1个知识点:连加。
a=1+69+102; //加数全部是常量。a的结果为:172。
b=q+x+y+k+r; //加数全部是变量。b的结果为:20。
c=3+x+y+5+k; //加数有的是常量,有的是变量。c的结果为:19。
//第2个知识点:自加的常规格式。
d+=6;//相当于d=d+6;d的结果为:11。
e+=x;//相当于e=e+x;e的结果为:8。
f+=18+y+k; //相当于f=f+18+y+k;f的结果为:31。
//第3个知识点:自加的特殊格式。
g++;//相当于g=g+1或者g+=1;g的结果为:6。
++h;//相当于h=h+1或者h+=1;h的结果为:6。
GuiWdData0=a; //把变量a这个数值放到窗口变量0里面显示
GuiWdData1=b; //把变量b这个数值放到窗口变量1里面显示
GuiWdData2=c; //把变量c这个数值放到窗口变量2里面显示
GuiWdData3=d; //把变量d这个数值放到窗口变量3里面显示
GuiWdData4=e; //把变量e这个数值放到窗口变量4里面显示
GuiWdData5=f; //把变量f这个数值放到窗口变量5里面显示
GuiWdData6=g; //把变量g这个数值放到窗口变量6里面显示
GuiWdData7=h; //把变量h这个数值放到窗口变量7里面显示
/*---C语言学习区域的结束---------------------------------------------------------------------------*/
while(1)
{
initial();
key_service();
display_service();
}
}
如何在坚鸿51学习板上观察a,b,c,d,e,f,g,h这8个变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。上坚鸿51学习板观察程序执行的结果如下:
变量a为172。变量b为20。变量c为19。变量d为11。变量e为8。变量f为31。变量g为6。变量h为6。 下节预告:加法的溢出和优先级(未完待续)
shmilyzlp
发表于 2015-5-11 21:40
菜鸟学习中,感谢分享:lol
向阳花开的春天
发表于 2015-5-12 15:49
期待
gurong60
发表于 2015-5-14 08:01
mark
zrb5688
发表于 2015-5-14 17:11
初学者,有的看的似懂非懂,不过得谢谢楼主提供了一些有用的思路。
1031565585
发表于 2015-5-16 19:10
顶起,写的很好!
jianhong_wu
发表于 2015-5-17 00:01
本帖最后由 jianhong_wu 于 2015-6-3 17:14 编辑
第十八节:加法运算的溢出。 我前面介绍的三种数据类型unsigned char ,unsigned int ,unsigned long,都是有最大范围限制的,它们最大范围分别是255,65535,4294967295,如果加法运算的结果超过了参与运算的变量本身,会出现什么结果,有什么规律,这就是本节要讲解的溢出问题。 (1)何谓溢出?比如以下例子:unsigned char a;a=0x8536;分析:因为a是unsigned char变量,位数是8位,也就是1个字节,而0x8536是16位,2个字节,这种情况下,把0x8536赋值给单字节变量a,变量a只能接收到最低位的一个字节0x36,而高位字节的0x85就被丢失了,这个就是本节所说的“溢出”了。 (2)再看一个例子如下:unsigned char b=0xff;b=b+1;分析:b默认值是0xff,再加1后,变成了0x0100保存在一个隐藏的中间变量,然后再把这个中间变量赋值给单字节变量b,b只能接收到低位字节0x00,所以运算后b的数值由于溢出变成了0x00。 (3)再看一个例子如下:unsigned char c=0xff;c=c+2;分析:c默认值是0xff,再加2后,变成了0x0101保存在一个隐藏中间变量,然后再把这个中间变量赋值给单字节变量c,c只能接收到低位字节0x01,所以运算后c的数值由于溢出变成了0x01。 (4)再看一个例子如下:Unsigned int d=0xfffe;d=d+5;分析:d默认值是0xfffe,再加5后,变成了0x10003保存在一个隐藏中间变量,由于这个隐藏的中间变量是unsigned int类型,只能保存2个字节的数据,所以在中间变量这个环节就溢出了,实际上隐藏的中间变量只保存了0x0003,然后再把这个中间变量赋值给双字节变量d,d理所当然也是0x0003。 (5)再看一个例子如下:unsigned long e=0xfffffffe;e=e+5;分析:e默认值是0xfffffffe,再加5后,变成了0x100000003保存在一个隐藏中间变量,由于这个隐藏的中间变量是unsigned long类型,只能保存4个字节的数据,所以在中间变量这个环节就溢出了,实际上隐藏的中间变量只保存了0x00000003,然后再把这个中间变量赋值给4字节变量e,e理所当然也是0x00000003。 现在编写一个程序来练习上述前面4个例子,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
unsigned char a;
unsigned char b=0xff;
unsigned char c=0xff;
unsigned intd=0xfffe;
a=0x8536;
b=b+1;
c=c+2;
d=d+5;
GuiWdData0=a; //把变量a这个数值放到窗口变量0里面显示
GuiWdData1=b; //把变量b这个数值放到窗口变量1里面显示
GuiWdData2=c; //把变量c这个数值放到窗口变量2里面显示
GuiWdData3=d; //把变量d这个数值放到窗口变量3里面显示
/*---C语言学习区域的结束---------------------------------------------------------------------------*/
while(1)
{
initial();
key_service();
display_service();
}
}
如何在坚鸿51学习板上观察a,b,c,d这4个变量的十六进制?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量,只要按住S9按键不放,此时显示的就是该变量的十六进制。上坚鸿51学习板观察程序执行的结果如下:
变量a为0x36。变量b为0x00。变量c为0x01。变量d为0x0003。
这一节提到了一个“隐藏中间变量”的概念,这个神秘的“隐藏中间变量”到底是unsigned int类型还是unsigned long类型?有什么规律?如果运算中存在多种不同变量类型该怎么办,实际应用中有解决的办法吗?预知详情,请看一节内容。 下节预告:加法运算中,神秘中间变量的类型以及解决“掺杂多种变量类型”的办法。(未完待续)
jianhong_wu
发表于 2015-5-22 07:09
第十九节:加法运算中,神秘中间变量的类型以及解决“掺杂多种变量类型”的办法。
在开始本节内容之前,先告诉大家前面第十一节内容有一处笔误,unsigned long的数据长度应该是4个字节,而不是3个字节。
上一节提到了一个“隐藏中间变量”的概念,两个加数相加,其结果先保存在一个“隐藏中间变量”里,然后再把这个“隐藏中间变量”赋值给左边的“保存变量”。这里的“隐藏中间变量”到底是unsigned int类型还是unsigned long类型?为了研究它的规律,在keil自带的C51编译环境下,我专门编写了好几个测试程序来观察实际运行的结果。
“保存变量”=“加数1”+“加数2”;
我测试的程序如下:
(1)“保存变量”为 unsigned int类型,“加数1”为unsigned char类型,“加数2”为unsigned char 类型。
unsigned int a;
unsigned char x=0x12;
unsigned char y=0xfe;
a=x+y;
运行结果:a等于0x0110。
分析过程:两个char类型的数相加,当运算结果大于char本身时,并没有发生溢出现象,int型的“保存变量”a最终得到了完整的结果。
初步结论:这种情况,“隐藏中间变量”应该为unsigned int 类型。
(2)“保存变量”为 unsigned long类型,“加数1”为unsigned int类型,“加数2”为unsigned char 类型。
unsigned long a;
unsigned int x=0xfffe;
unsigned char y=0x12;
a=x+y;
运行结果:a等于十六进制的0x0010。
分析过程:一个int类型的数与一个char类型的数相加,当运算结果大于其中最大加数int类型本身时,本来以为运算结果应该是long类型的0x00010010,结果是int类型的0x0010,发生了溢出现象。
初步结论:这种情况,“隐藏中间变量”应该为unsigned int 类型。
(3)“保存变量”为 unsigned long类型,“加数1”与“加数2”都为常量。
unsigned long a;
a=50000+50000;
运行结果:a等于100000。
分析过程:int的最大数据范围是65535,而两个常量相加,其结果超过了65535还能完整保存下来。
初步结论:这种情况,“隐藏中间变量”等于左边的“保存变量”类型。
(4)“保存变量”为 unsigned long类型,“加数1”为unsigned int类型,“加数2”为常量。
unsigned long a;
unsigned long b;
unsignedint x=50000;
a=x+30000;
b=x+50000;
运行结果:a等于14464,b等于100000。
分析过程:本来以为a应该等于80000的,结果是14464发生了溢出。而b是100000没有发生溢出。
初步结论:这是一种很怪异的现象,为什么同样的类型,因为常量的不同,一个发生了溢出,另外一个没有发生溢出?这时的“隐藏中间变量”到底是int类型还是long类型我无法下结论。
经过上述简单的测试,我发现规律是模糊的,模糊的规律就不能成为规律。如果真要按这种思路研究下去,那真是没完没了,因为还有很多情况要研究,当超过3个以上加数相加,同时存在long,int,char,常量这4种类型时又是什么规律?在不同的C编译器里又会是什么现象?即使把所有情况的规律摸清楚了又能怎么样,因为那么繁杂很容易忘记导致出错。有什么解决的办法吗?现在跟大家分享一种很简单的解决办法。
当遇到有争议的问题时,还有一种解决思路是:与其参与争议越陷越深,还不如想办法及时抽身绕开争议。在上述运算中,只要经过简单的变换,让它们遵循“所有参与运算的变量,左边的变量类型必须跟右边的保存变量类型一致”这个原则,那么就不会存在这些争议了。
(5)比如上述第(4)个例子,其转换方法如下:
unsigned long a;
unsigned long b;
unsignedint x=50000;
Unsignedlong t;//多增加一个long类型的变量,用来变换类型
t=0;//把变量的高位和低位全部清零。
t=x; //把x的数值先放到一个long类型的变量里,让”加数”跟”保存变量”类型一致。
a=t+30000;
b=t+50000;
运行结果:a等于80000,b等于100000。都没有发生溢出。
(6)比如上述第(2)个例子,其转换方法如下:
unsigned long a;
unsigned int x=0xfffe;
unsigned char y=0x12;
unsignedlong t;//多增加一个long类型的变量,用来变换类型。
unsignedlong r;//多增加一个long类型的变量,用来变换类型。
t=0;//把变量的高位和低位全部清零。
t=x; //把x的数值先放到一个long类型的变量里,让”加数”跟”保存变量”类型一致。
r=0;//把变量的高位和低位全部清零。
r=y //把y的数值先放到一个long类型的变量里,让”加数”跟”保存变量”类型一致。
a=t+r;
运行结果:a等于十六进制的0x00010010,没有发生溢出现象。
下节预告:减法运算的常见格式。
(未完待续)
yuanquan12345
发表于 2015-5-22 13:23
学习 。
e08610318
发表于 2015-5-22 15:12
先会用,才能激起你的欲望去进一步了解其更深入的原理。
lgr164622819
发表于 2015-5-23 11:49
支持用ATMEL的SAMD20系列芯片,M0+内核,带电容触摸按键功能,通过工业级测试,稳定性一流,欢迎加Q:164622819,或拨打:15817111671,一起讨论交流。
allwind20nn
发表于 2015-5-27 11:33
留个名,方便以后学习。
页:
1
2
3
[4]
5
6
7
8
9
10
11
12