首页编程单片机c语言编程代码?单片机编程

单片机c语言编程代码?单片机编程

编程之家2026-05-31677次浏览

很多朋友对于单片机c语言编程代码和单片机编程不太懂,今天就由小编来为大家分享,希望可以帮助到大家,下面一起来看看吧!

单片机c语言编程代码?单片机编程

如何写出高效的单片机C语言程序代码

由于单片机的性能同电脑的性能是天渊之别的,无论从空间资源上、内存资源、工作频率,都是无法

与之比较的。PC机编程基本上不用考虑空间的占用、内存的占用的问题,最终目的就是实现功能就可以了。

对于单片机来说就截然不同了,一般的单片机的Flash和Ram的资源是以KB来衡量的,可想而知,单片

机的资源是少得可怜,为此我们必须想法设法榨尽其所有资源,将它的性能发挥到最佳,程序设计时必须

遵循以下几点进行优化:

1.使用尽量小的数据类型

单片机c语言编程代码?单片机编程

能够使用字符型(char)定义的变量,就不要使用整型(int)变量来定义;能够使用整型变量定义的变

量就不要用长整型(long int),能不使用浮点型(float)变量就不要使用浮点型变量。当然,在定义变

量后不要超过变量的作用范围,如果超过变量的范围赋值,C编译器并不报错,但程序运行结果却错了,

而且这样的错误很难发现。

2.使用自加、自减指令

通常使用自加、自减指令和复合赋值表达式(如a-=1及a+=1等)都能够生成高质量的

单片机c语言编程代码?单片机编程

程序代码,编译器通常都能够生成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关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素

更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码

就不再进行优化,从而可以提供对特殊地址的稳定访问。

51单片机C语言编程

// 51单片机C语言编程,这个时钟+秒表可以参考一下。

#include<reg51.h>

#define uchar unsigned char

#define uint unsigned int

sbit qingling=P1^0;//清零

sbit tiaofen=P1^1;//调分

sbit tiaoshi=P1^2;//调时

sbit sounder=P1^7;//naozhong

uint a,b;

uchar hour,minu,sec,//时钟

hour0,minu0,sec0,//秒表

hour1,minu1,sec1;

h1,h2,m1,m2,s1,s2,//显示位

k,s;//状态转换标志

uchar code select[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};

uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

/*****************函数声明***********************/

void keyscan();

void init();

void delay(uchar z);

void display(uchar,uchar,uchar);

void sounde();

/*****************主函数*************************/

void main()

{

init();

while(1)

{

while(TR1)

{

keyscan();//扫描函数

while(s==1)//s是状态标志,当s=0时,闹钟取消。s=1时,设定闹钟时间(也是通过调时,调分函数);

{//s=2时,闹钟工作,时间与设定时刻一致时,闹钟响(一分钟后自动关闭,可手动关闭)。再次切换,s=0.

keyscan();//s状态切换(0-》1-》2-》0)通过外部中断1实现。

display(hour1,minu1,sec1);//闹钟时刻显示

}

display(hour0,minu0,sec0);//时钟表显示

while(k)/*k是秒表状态(0-》1-》2-》0)通过外部中断0实现。0秒表关;1秒表从零计时;2秒表停,显示计时时间*/

{

display(hour,minu,sec);//秒表显示

}

}

}

}

/*****************初始化函数***********************/

void init()

{

a=0;

b=0;

k=0;

s=0;

hour0=0;

minu0=0;

sec0=0;

hour=0;

minu=0;

sec=0;

hour1=0;

minu1=0;

sec1=0;

TMOD=0x11;//定时器0,1工作于方式1;赋初值

TH0=(65536-5000)/256;

TL0=(65536-5000)%256;

TH1=(65536-50000)/256;

TL1=(65536-50000)%256;

EA=1;

EX0=1;//秒表中断

EX1=1;//闹钟设定中断

ET0=1;

ET1=1;

IT0=1;//边沿触发方式

IT1=1;

PX0=1;

PX1=1;

TR0=0;//初始,秒表不工作

TR1=1;//时钟一开始工作

}

/*****************定时器0中断*************/

void timer0_int() interrupt 1//秒表

{

TH0=(65536-5000)/256;

TL0=(65536-5000)%256;

a++;

if(a==2)

{

a=0;

sec++;

if(sec==100)

{

sec=0;//毫秒级

minu++;

if(minu==60)

{

minu=0;//秒

hour++;

if(hour==60)//分

{

hour=0;

}

}

}

}

}

/*************外部中断0中断函数************/

void ex0_int() interrupt 0

{

k++;

if(k==3)

k=0;

if(k==1)

{

TR0=~TR0;

if(TR0==1)

{

hour=0;

minu=0;

sec=0;

}

}

if(k==2)

{

TR0=~TR0;

}

}

/*************外部中断1中断函数************/

void ex1_int() interrupt 2

{

s++;

if(s==3)

s=0;

}

/*************定时器1中断****************/

void timer1_int() interrupt 3//控制时钟工作

{

TH1=(65536-50000)/256;

TL1=(65536-50000)%256;

if(s==2)

{

if(hour1==hour0&& minu0==minu1)

sounde();

}

b++;

if(b==20)

{

b=0;

sec0++;

if(sec0==60)

{

sec0=0;

minu0++;

if(minu0==60)

{

minu0=0;

hour0++;

if(hour0==24)

hour0=0;

}

}

}

}

/*************键盘扫描****************/

void keyscan()

{

if(s==1)

{

if(qingling==0)

{

delay(10);

if(qingling==0)

{

sec1=0;

minu1=0;

hour1=0;

}

}

if(tiaofen==0)

{

delay(10);

if(tiaofen==0)

{

minu1++;

if(minu1==60)

{

minu1=0;

}

while(!tiaofen);

}

}

if(tiaoshi==0)

{

hour1++;

if(hour1==24)

{

hour1=0;

}

while(!tiaoshi);

}

}

else//调整时钟时间

{

if(qingling==0)

{

delay(10);

if(qingling==0)

{

sec0=0;

minu0=0;

hour0=0;

}

}

if(tiaofen==0)

{

delay(10);

if(tiaofen==0)

{

minu0++;

if(minu0==60)

{

minu0=0;

}

while(!tiaofen);

}

}

if(tiaoshi==0)

{

hour0++;

if(hour0==24)

{

hour0=0;

}

while(!tiaoshi);

}

}

}

/*************显示函数****************/

void display(uchar hour,uchar minu,uchar sec)

{

h1=hour/10;

h2=hour%10;

m1=minu/10;

m2=minu%10;

s1=sec/10;

s2=sec%10;

P0=0xff;

P2=table[h1];

P0=select[7];

delay(5);

P0=0xff;

P2=table[h2];

P0=select[6];

delay(5);

P0=0xff;

P2=0x40;;

P0=select[5];

delay(5);

P0=0xff;

P2=table[m1];

P0=select[4];

delay(5);

P0=0xff;

P2=table[m2];

P0=select[3];

delay(5);

P0=0xff;

P2=0x40;

P0=select[2];

delay(5);

P0=0xff;

P2=table[s1];

P0=select[1];

delay(5);

P0=0xff;

P2=table[s2];

P0=select[0];

delay(5);

}

/*************闹钟函数****************/

void sounde()

{

sounder=~sounder;

}

/*************延时函数****************/

void delay(uchar z)

{

int x,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--);

}

C语言怎么写进单片机

1:先把写好的C语言进行编译,生成*.hex或*.bin文件,推荐用keil C。

然后:

1:根据你单片机的型号买一个烧录器,与PC连接好后,把单片机放在烧录器的插座上(看你的单片机封装,新手尽量用DIP的),根据烧录器软件提示把上述文件烧到单片机里,缺点:价格较高

2:用下载线,用法与烧录器差不多,缺点:比较麻烦,要有一定经验。

3:用学习板,一般学习板上面的单片机可以直接在线烧录(如STC,SST系列的单片机),也就是说单片机不用拆下来,板子上做好了烧录电路,可以在板子上烧录,然后就可以直接验证了。

4:自已做一个,用STC的单片机,只要用一个RS232的转换电路(一片232IC,几个电解电容就行了),STC的单片机可以通过串口烧录程序,具体参见STC官网或其DATASHEET,有详细介绍。缺点:要一定动手能力

推荐新手用第3方法,可以很快上手。

单片机c语言编程代码和单片机编程的问题分享结束啦,以上的文章解决了您的问题吗?欢迎您下次再来哦!

童程在线少儿编程(少儿编程哪个教育平台比较好)struts是什么(struts1和struts2的区别)