单片机c语言pdf(单片机原理及应用电子书)
这篇文章给大家聊聊关于单片机c语言pdf,以及单片机原理及应用电子书对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。
51单片机C语言程序
//你原来的b2,b2都是死循环,这是不行的,只有主函数才可以死循环。
//你的主函数结构也有问题。
//为你增加了一个按键检测的函数。
//下列程序通过了实验测试。
//b1输出的周期大约0.9s。
//b2输出的周期大约0.6s。
//K为触动开关,reg为红灯,bice为绿灯,b1、b2各为一个方波,
//按第一次触动开关时红灯亮、b1输出,
//按第二次绿灯亮、为b2输出,
//按第三次都关闭.
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
uint a;
void b1();
void b2();
sbit t= P1^0;
sbit k= P3^5;
sbit reg= P3^3;
sbit bice= P3^2;
void delay(uchar z)
{
uint x,y;
for(x= z; x> 0; x--) for(y= 110; y> 0; y--);
}
bit key()
{
bit kkk;
kkk= k;//读入按键.
if(kkk== 1) return 0;//没有按下.
delay(5);//延时.
if(k== kkk) return 1;//两次相等.
return 0;
}
void main()
{
while(1){
P3= 0xff;
while(!key());//静等按下第一次.
reg= 0;
bice= 1;
while(!key()) b1();//没有按下第二次就循环等待.
reg= 1;
bice= 0;
while(!key()) b2();//没有按下第三次就循环等待.
}
}
void b1()
{
P1= 0xfe; a= 50000; while(a--);
P1= 0xff; a= 50000; while(a--);
}
void b2()
{
P1= 0xfe; a= 30000; while(a--);
P1= 0xff; a= 30000; while(a--);
}
一段单片机C语言,求大神逐句翻译一下。
#include<REGX51.H>//头文件
#define uchar unsigned char//变量关键字更改
#include<intrins.h>//头文件
uchar code tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xC0};
//字符数组定义
void delay()//子函数定义
{ uchar i,j;//变量定义
for(i=0;i<15;i++)//for语句,执行15次
for(j=0;j<250;j++)//执行250次
{_nop_();}//共执行250*15次空函数,延时操作
}
uchar seg7(uchar a)//子函数定义
{return tab[a];}//返回tab数组内第a个变量的值
void main(void)//主函数
{ uchar i,j,k,x,y;//变量定义
P1=0xff;//port1全部置位
P0=0xff;//port0全部置位
y=0;//y赋0
while(1)//无限循环
{ j=0xf7;//j赋11110111
k=y;//y赋给k
for(i=0;i<4;i++)//4次循环
{
P0=seg7(k);//P0=第K个元素的值
k++;//k=k+1
P1=_cror_(j,i);//P1口带返回的移位操作
delay();//延时
P1=0xff;//P1全部置高
}
x++;//x=x+1
if(x==15){x=0;y++;}//如果15次,x=0,y=y+1
if(y==8)y=0;//8*15次,y=0,重新开始循环
}
}
如何写出高效的单片机C语言程序代码
由于单片机的性能同电脑的性能是天渊之别的,无论从空间资源上、内存资源、工作频率,都是无法
与之比较的。PC机编程基本上不用考虑空间的占用、内存的占用的问题,最终目的就是实现功能就可以了。
对于单片机来说就截然不同了,一般的单片机的Flash和Ram的资源是以KB来衡量的,可想而知,单片
机的资源是少得可怜,为此我们必须想法设法榨尽其所有资源,将它的性能发挥到最佳,程序设计时必须
遵循以下几点进行优化:
1.使用尽量小的数据类型
能够使用字符型(char)定义的变量,就不要使用整型(int)变量来定义;能够使用整型变量定义的变
量就不要用长整型(long int),能不使用浮点型(float)变量就不要使用浮点型变量。当然,在定义变
量后不要超过变量的作用范围,如果超过变量的范围赋值,C编译器并不报错,但程序运行结果却错了,
而且这样的错误很难发现。
2.使用自加、自减指令
通常使用自加、自减指令和复合赋值表达式(如a-=1及a+=1等)都能够生成高质量的
程序代码,编译器通常都能够生成inc和dec之类的指令,而使用a=a+1或a=a-1之类
的指令,有很多C编译器都会生成二到三个字节的指令。
3.减少运算的强度
可以使用运算量小但功能相同的表达式替换原来复杂的的表达式。
(1)求余运算
N= N%8可以改为N= N&7
说明:位操作只需一个指令周期即可完成,而大部分的C编译器的“%”运算均是调用子程序来
完成,代码长、执行速度慢。通常,只要求是求2n方的余数,均可使用位操作的方法来代替。
(2)平方运算
N=Pow(3,2)可以改为N=3*3
说明:在有内置硬件乘法器的单片机中(如51系列),乘法运算比求平方运算快得多,因为浮点数
的求平方是通过调用子程序来实现的,乘法运算的子程序比平方运算的子程序代码短,执行速度快。
(3)用位移代替乘法除法
N=M*8可以改为N=M<<3
N=M/8可以改为N=M>>3
说明:通常如果需要乘以或除以2n,都可以用移位的方法代替。如果乘以2n,都可以生成左移
的代码,而乘以其它的整数或除以任何数,均调用乘除法子程序。用移位的方法得到代码比调用乘除法子
程序生成的代码效率高。实际上,只要是乘以或除以一个整数,均可以用移位的方法得到结果。如N=M*9
可以改为N=(M<<3)+M;
(4)自加自减的区别
例如我们平时使用的延时函数都是通过采用自加的方式来实现。
void DelayNms(UINT16 t)
{
UINT16 i,j;
for(i=0;i<t;i++)
for(j=0;i<1000;j++)
}
可以改为
void DelayNms(UINT16 t)
{
UINT16 i,j;
for(i=t;i>=0;i--)
for(j=1000;i>=0;j--)
}
说明:两个函数的延时效果相似,但几乎所有的C编译对后一种函数生成的代码均比前一种代码少1~3
个字节,因为几乎所有的MCU均有为0转移的指令,采用后一种方式能够生成这类指令。
4. while与do...while的区别
void DelayNus(UINT16 t)
{
while(t--)
{
NOP();
}
}
可以改为
void DelayNus(UINT16 t)
{
do
{
NOP();
}while(--t)
}
说明:使用do…while循环编译后生成的代码的长度短于while循环。
5. register关键字
void UARTPrintfString(INT8*str)
{
while(*str&& str)
{
UARTSendByte(*str++)
}
}
可以改为
void UARTPrintfString(INT8*str)
{
register INT8*pstr=str;
while(*pstr&& pstr)
{
UARTSendByte(*pstr++)
}
}
说明:在声明局部变量的时候可以使用register关键字。这就使得编译器把变量放入一个多用途的寄存
器中,而不是在堆栈中,合理使用这种方法可以提高执行速度。函数调用越是频繁,越是可能提高代码的
速度,注意register关键字只是建议编译器而已。
6. volatile关键字
volatile总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在
哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以死代码消除。一般来
说,volatile关键字只用在以下三种情况:
a)中断服务函数中修改的供其它程序检测的变量需要加volatile(参考本书高级实验程序)
b)多任务环境下各任务间共享的标志应该加volatile
c)存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义
总之,volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素
更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码
就不再进行优化,从而可以提供对特殊地址的稳定访问。
OK,本文到此结束,希望对大家有所帮助。