单片机编程格式.docx
《单片机编程格式.docx》由会员分享,可在线阅读,更多相关《单片机编程格式.docx(10页珍藏版)》请在冰豆网上搜索。
![单片机编程格式.docx](https://file1.bdocx.com/fileroot1/2022-11/16/af2bf623-b8c6-4172-9bc2-13c82610b7c5/af2bf623-b8c6-4172-9bc2-13c82610b7c51.gif)
单片机编程格式
单片机编程格式
单片机编程是基于C语言的一种简单实用的编程语言,跟C语言编程类似。
开头都是要加上头文件预处理命令:
#include
当然还要加上所有用得到的函数库,同样是#include<>格式。
然后是一些针脚的位变量定义,格式是:
sbit位变量名=位地址。
位地址如P0^1口。
然后以后的位地址都可以用上述为变量名代替。
主函数一般都是无返回值的,所以多数情况下主函数定义格式为:
voidmain()
{主函数
}
当要做流水灯,数码管什么的时候,可能你会选择数组形式,假设咱用的是P0口,说明一下,可以直接给P0赋值八位二进制,也就是两位十六进制的数,且P0口从P0^1-P0^7是从最低位到最高位的,当二极管是共阳极时,只有P0口是低电平时才能点亮二极管,所以,注意当P0口输出电平是0(默认为1,所以开始时不亮的)的时候才行。
从P0^0到P0^7口依次亮的话,代码分别是:
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f.
当是数码管的时候,有两种情况,就是数码管的个数分类。
当数码管个数为1的时候,这时候是最简单的。
从0到F的代码分别是:
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71.
这代码是要记住的,当然,这也是共阴极的。
当数码管不再是单个的时候,就涉及到了位选和段选的问题了它们就像是一个电路中的单刀双向的开关,打向那边就向那边赋值,然后断开之后,前面的赋值就被锁存在相应的数上了,不再改变,直到下一次打向相应的位选或段选。
在这里可能有一些同学会有点糊涂,我就简单的解释一下,当位选值为1时,就相当于开关打向了选择哪个数码管的位置,用来决定哪个数码管亮,哪个不亮,但是它不管显示的是多少。
同样的,当打到段选时,只决定显示多少,但不管哪个数码管亮。
这就像是直角坐标系中的x于y的关系,用他俩就能确定哪个数码管显示哪个数了。
当然,有同学说同一时刻数码管显示的数值不一样,不是像上述那样简单。
恩,开始我也有这样的迷惑,但是想想以前的背投式电视机就明白了,它是一遍一遍的扫描着显示的,也就是说同一时科显示的数字是一样的,当然哪个显示是位选中所决定的,当扫描速度相对够大和荧光余辉的作用,超出了人眼的自然反应,那么我们就看不出闪烁来了。
于是我们看到的就好像是一连串的数字,而不闪烁。
举个例子吧,上一个数码管的程序:
#include
sbitdula=P2^6
sbitwela=P2^7
voidmain()
{
unsignedinti;
unsignedcharduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07};
unsignedcharwei[]={0xfe,0xfd,0xfb,0xf7,0x7f,0xbf,0xdf,0xef};
wela=1;
P1=0x00;
wela=0;//以上三句是先把位选清零,使得开始屏幕不显示。
delay(100);//此为了稍微延迟避免闪烁。
while
(1)//虽然单片机程序会一遍一遍的执行,但是没有这方面的说明,
所以还是带上这个无限循环
{
wela=1;
P1=wei[i];
wela=0;
dula=1;
P1=duan[i];
dula=0;//这里是让八个数码管依次显示0到7这八个数字
delay(100);//这是扫描间隔
i++;
if(i==8)
i=0;//这里是为了使循环不出错,可以继续执行下去
}
}
voiddelay(inta)//这是延迟函数
{
while(a--);
}
上述就是一个数码管静态显示的最典型的例子,是八个数码管依次显示01234567八个数,当然也可以显示ABCDEF这几个数(姑且算是数吧,十六进制嘛)。
下一个给个流水灯的程序,显示是从第一个向下一个一个的亮,当然是一直只有一个灯亮,当到达最后一个时,再从下向上反向亮,之后一直这样循环。
这个就不注释了,好好看剧能看懂,很简单:
#include
voidmain()
{
unsignedchara[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsignedinti=0;
while
(1)
{
P1=a[i];
delay(1000);
i++;
if(i==8)
for(i=8;i>0;)
{
i--;
P1=a[i];
delay(1000);
}
}
}
voiddelay(ints)
{
while(s--);
}
当这些知识都掌握的时候,下一个就应该是中断系统的知识了,中断系统中,最先学的是定时器,定时器实际是这种东西:
纸老虎!
开始的时候总是看不明白这是什么,当真正掌握的时候会发现,它实际比其他的东西还简单,在这我就给大家说说十六位定时器的例子。
中断必须条件:
三要素:
中断请求;
总中断允许;
相应中断允许响应。
开总中断:
EA=1
上图就是相应中断在编程中的名字,可以直接使用。
允许外部/定时器中断
ET0/ET1/EX0/EX1=1
void函数名()interrupt中断序号
{
跟主函数一样,写处理内容。
}
定时器主要内容:
还是一样,先开总中断开关
EA=1
选择中断方式,打开相应中断:
ET0/ET1=1
TH0=(65536-50000【这里是要定时的时间,单位/微秒】)/256这是高八位的数值
TL0=(65535-50000【同上】)%256这个是低八位数值
(TH0,TL0)是溢出的容器,刚才的值就是容器里的初始量,空闲的值就是所求时间。
溢出后中断发生,容器清零。
这就是每次都给TH0/TL0赋值的原因.其中TH0是高八位,TL0是低八位。
TMOD=0xM0M1;(M0M1是01,10,11等地这样的数)
方式中用的是M0M1,是低八位的最后两位
定时器中断0/1打开:
ET0/1=1
TRO/1=1;这是启动定时器,必不可少
中断函数:
void函数名()interrupt工作方式的序号
{
容器值清零就是THO/TL0等地重新赋值的原因。
然后就是中断函数处理内容,跟主函数一样。
这里主要是处理一个或一些数,然后这个数在主函数中处理,也就是说这里的函数相对说简单的,主要的处理还是在主函数中。
}
工作方式优先表:
定时器工作原理:
工作方式:
(这里说的是TMOD后两位的,既是M1M0,高四位是T1,低四位是T0)
GATE:
门控位。
当为零时,只要用软件使TCON中的TR0或TR1为1,就可以启动定时器/计数器;当GATE=1时用软件使TR0或TR1为1,同时外部中断引脚也为高电平时,才能启动定时器/计数器工作,也就是说定时器的启动多了一个条件。
在此,给出自己编写的每隔一秒变一个数的程序。
显示是这样的:
从第一位开始,先显示0,一秒钟后零灭,第二个数码管显示1,以此类推。
当显示到7的时候,再从新从第一个数码管开始亮,这次是89ABCDEF这几个数一个一个的显示。
然后就是一直循环下去。
也是最简单的定时显示,前辈莫笑。
#include
sbitwela=P2^6
sbitdula=P2^7
voidmain()
{
unsignedcharwei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsignedcharduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsignedinti=0,t=0;
EA=1;
ET0=1;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TOMD=0x01;
TR0=1;
while
(1)
{
while(20-t);
t=0;
wela=1;
if(i>7)
P1=wei[i-8];
else
P1=wei[i];
wela=0;
P1=duan[i];
i++;
if(i==16)
i=0;
}
}
voidtime0()interrupt1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
t++;
}