基于51系列单片机的简单c语言编程
基于大家都学过了c语言和单片机,但我们学单片机的时候没有学到如何用c来编程序,来替代难懂而又冗长的汇编指令。难道这么好的c就忍心搁置在记忆的深处浪费掉了?其实用c来对单片机编程不是很难的一件事情,这只是一个接口问题,而这个接口则相当简单。一般人花一两个小时可以基本掌握了,编几个简单的程序没有问题了。然后当你回头看看上学期那些用汇编做的实验,真是easy!
用c来对单片机编程主要是引入了几个单片机特有的函数以及函数标识符、修饰符等,所有指令遵循c语言的语法。本文主要说明了编程中经常用到的几个函数说明、中断等情况,对于复杂的很少用到的函数及修饰符忽略不计,有兴趣我们一起研究下 ^_^
在c51函数定义中要考虑的东西比较多,不像我们在c语言中总是int、int、int看上去不爽再float,还是不爽就double。c51中不能随便就int了。要知道我们的程序最后是要烧到单片机里面去的,那是8位机,可不是你32位的cup ~-~
c51中一个完整的函数定义从先到后包括存储类型说明、类型说明、标识符、修饰符部分、存储模式共5部分。完整的表格如下:
[存储类型说明符] [类型说明] [标识符] 修饰符部分 [存储模式]
static unsigned char 函数名 (reentrant)(interrupt m)(using n)
extern char small
unsigned int compact
int large
unsigned long
long
float
struct
union
void
bit
很重要的一张表,已经包括了c51中所有函数的定义,建议做成txt放在桌面上或者做成jpg成桌面并在CDEFG盘、移动硬盘、u盘、邮箱备份(有条件的还可刻录成光盘)^_^
详细说明如下:
【存储类型说明符】有static和extern两种。这两种c语言中已经学过,不详细说明了。static指静态变量,本函数内部有效。extern是外部变量,全局有效。另外如果不加说明,则默认是extern。
【类型说明】一共11种,比较重要。
1、unsigned char:无符号字符型,长度8位,大小范围0-255。因为和单片机位数一致,可以看成跟汇编里的A和R是一样的,是c51中用的最多的类型了。如果变量范围不超过256,那你就毫不犹豫的在标识符前面写上它吧。
2、char:唯一和上面有区别的是它是有符号的8位,大小范围 -128-127。
3、unsigned int:无符号整型,长度16位,大小范围0-65535。如果你实在没有办法把变量控制在256之内,那么就用它吧。65535应该够用了吧?如果还不够,对你的编程能力要怀疑一下了。
4、int:就像char和unsigned char的区别一样,int唯一和上面不同的只是符号问题。 大小范围-32768-32767。
5、void:无值型,也经常用到的一种类型,长度为0。表示函数不返回值实际编程时用到以上5种类型已经足够了,以下几种仅做友情介绍。
6、 unsigned long: 无符号长整型,长度32位 大小范围 0-4294967295(好大啊)。很少用到,基本上不用到。要知道你定一个unsigned long我们的单片机可要让出4个寄存器给你了,对于资源有限的51系列单片机,这是相当奢侈的做法。
7、long:不再多讲了,跟5的区别只是符号,也是基本上不用到的。
8、float:符点型32位。也是相当奢侈的做法,建议不用
9、double:符点型64位。最奢侈的做法!
10、struct:结构型。
11、union:联合型。
【标识符】:
标识符是最灵活的地方了,可以是你喜欢的任何字母的组合,当然不能是c语言中已经定义的符号。建议用拼音或英语单词,助于记忆。同种类型变量多了可以加下划线再数字的形式,如example_1、example_2、example_3等。
【修饰符部分】也比较重要
完整的修饰符的形式是(reentrant)(interrupt m)(using n),括号中的修饰符可以同时出现也可以出现其中一个。
reetrant是可重复调用修饰符。所谓可重复调用,指一个函数正在被其他函数(如A函数)调用但还没有返回时,又有一个第三方函数(如函数B)可以来调用此函数而不会被函数A改变的变量而改变其运行结果,在B看来就像A不存在一样。加上reetrant后,说明此函数是可重复调用的。显然 reetrant修饰符会使单片机额外开发寄存器来保存第一次调用时变量的值,会增加资源的开销。
interrupt m:应该说这是最重要的修饰符了,加了interrupt后说明此函数是中断函数,即函数返回指令是reti。根据m值的不同而代表不同的中断。说明如下:
interrupt 0 指明此函数是外部中断0
interrupt 1 指明此函数是计时器/计数器T0中断
interrupt 2 指明此函数是外部中断1
interrupt 3 指明此函数是计时器/计数器T1中断
interrupt 4 指明此函数是串行口中断
另外对于52单片机还有interrupt 5,指明此函数是计时器/计数器T2中断
using n:这是指明函数变量放置在那组寄存器,51系列共有4组寄存器(好像没有记错吧^_^)。那么可以分别用using 0、using 1、using 2、using 3来修饰。加上此修饰后是人工配置寄存器组(适合牛人),如果不加此修饰则编译程序会自动分配寄存器组来放置变量(嘿嘿,适合我这种菜鸟)。
【存储模式】:
共3种,分别是small、compact、large。
1. Small模式
指所有缺省变量参数均装入内部RAM,优点是访问速度快,缺点是空间有限,只适用于小程序。
2. Compact模式
所有缺省变量均位于外部RAM区的一页(256Bytes),具体哪一页可由P2口指定,在STARTUP.A51文件中说明,优点是空间较Small为宽裕速度
较Small慢,较large要快,是一种中间状态。
3. large模式
所有缺省变量可放在多达64KB的外部RAM区,优点是空间大,可存变量多,缺点是速度较慢。
可以按照自己程序的大小来定哪种模式。
函数部分简单的就这样了,举个例子如:
static unsigned char example 定义无符号字符型静态变量example
void timer_0(void) interrupt 1 using 1 samll 定义T0中断函数,使用第二组寄存器,所有缺省变量参数均装入内部RAM
编译程序:推荐大家用keil,只能用一句话来形容了,很好很强大!
关于头文件:c51使用的头文件一般是reg51.h或reg52.h,引用此头文件后在编程时可以使用51系列中已经定义的特殊寄存器名而不用事先声明,如P1(注意,是大写哦)代表P1口,ET0代表计时器/计数器T0的中断允许位,T0代表计时器/计数器T0等等。
关于位运算:在keil中定义位用sbit声明,第几位用符号“^”表示,如sbit ck="P1"^0 定义ck为P1.0口。bit跟sbit的区别是一种是定义,一种是声明。bit是定义一个变量,然后将寄存器的某一位赋值给变量(如P1.1的值给变量 a)。而sbit是声明一个变量,声明后这个变量和寄存器的某一位等价,地址空间相同(如P1.1声明变量a,以后a可以代表P1.1使用)。还有一个跟一般c语言不同点是在keil中为求反可以使用符号
“~”,当然也可以使用原来的“!”,其他与啊或啊都跟原来c语言相同,不再赘述。
本人也刚刚处于起步阶段,写的不是很全面,有些地方写得不是很好,可能也存在一定错误,望大家批评指正。
下面附上一段简单程序,此程序在P2.3和P2.6脚输出T=3ms的方波,在P2.0管脚输出T=1s的方波,在keil下编译无误并在s52上稳定运行,所用晶振12M^_^
#include
sbit ckl = P2^3; /*定义管脚,脉冲*/
sbit ckr = P2^6; /*定义管脚,脉冲*/
sbit p20 = P2^0;
unsigned int j;
void clock_initial() reentrant /*计时1.5ms*/
{
TR2=0;
TH2=0xFA;
TL2=0x24;
TR2=1;
}
void main()
{
T2CON=0x00; //计时器T2工作方式选择
TF2=0;
ckl=0;
ckr=0;
clock_initial();
ET2=1;
EA=1;
for( ; ; );
}
void clk_int(void) interrupt 5 // 中断函数
{
j=j+1;
TF2=0;
ckl=~ckl;
ckr=~ckr;
if(j==333)
{p20=~p20;
j=0;}
clock_initial();
文章评论(0条评论)
登录后参与讨论