单片机c语言小项目开发,单片机的一些开发技巧(一)

本文介绍了在单片机开发中如何利用C语言嵌入汇编语言实现精确延时,通过软件方法扩展外部中断源,以及如何生成和使用库函数保护知识产权。示例代码详细展示了具体实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很多朋友正在学习单片机开发技术,但开发中免不了要碰到这样、那样的问题,有些问题可能无碍大局,但有一些问题却直接影响到产品的成本、体积、性能。这里介绍笔者的几个技巧,希望对大家的工作有帮助。

一.C语言中嵌入汇编语言

单片机开发中,通常我们使用C语言编写主程序,这样可以充分借助C语言工具提供的运算库函数及强大的数据处理能力。但C语言的可控性不及汇编语言,在有些对时序要求严格的处理上,我们还需用灵活性更强的汇编语言来编写。上海AVR单片机培训这样就产生了C语言和汇编语言混合编程的问题,一般分成三种方式:1.汇编语言调用C语言函数;2. C语言调用汇编语言;3. C语言中嵌入汇编语言。这里我们主要介绍第3种,即C语言中嵌入汇编语言。

下面的一段程序是主程序调用精确的205μS延时子程序并使P1.0交替输出高、低电平的方波。

/*------------程序名test.c------------*/

#include P 晶振频率12.000MHz《》

/****************/

void delay(void)//延时205μS

{

#pragma asm

MOV R0,#100

LOOP:

DJNZ R0,LOOP

#pragma endasm

}

/***************/

void main (void)//主函数,其功能使P1.0交替输出高、低电平的方波

{

while(1)

{P1_0=!P1_0;

delay();}

}

具体实现过程为:

1.先用汇编语言编制一段延时程序,在keil开发环境中编译,然后进行软件仿真,晶振频率的设置应和你的要求相符。仿真时注意观察左边寄存器窗口内的时间显示,调整延时程序的参数可得到我们需要的精确延时。

2.用C51编写主程序及延时子程序的外壳(等待嵌入汇编语言),假定此程序名称为test.c。

3.将第1步所得的汇编延时子程序放入C51编写的延时子程序外壳中。注意在开始及结束时分别加上#pragma asm、#pragma endasm语句,这种方法是通过asm与endasm告诉C51编译器,中间行不用编译为汇编行。

4.按照Keil的使用方法,建立工程文件并添加源程序。

5.点击含有汇编程序的C源程序后再右击,在弹出的下拉菜单中选中Options for File ‘test.c’(图1),这时出现图2所示的界面,勾选Generate Assembler SRC File(生成汇编SRC文件)及Assembler SRC File(封装汇编文件)使其有效。

6. 根据项目的编译模式加载封装库文件,通常在Small模式时为C51S.LIB(该文件在C:\Keil\C51\Lib\C51S.LIB),具体见图3。

7.点击Rebuild target(重建所有目标文件)即可得到编译结果(图4)。

c91e8f4d371160b6e0352bdcac23986f.png

图1

a2bc3cbe7bf260d0614d76f8c37f85d1.png

图2

1cf23f044cdb987b0281605f3fbc4642.png

图3

70374580133d23b49506482bb762a1cc.png

图4

二。用软件扩展外部中断

大家知道,51单片机的外部中断只有2个,书本上曾介绍了一种扩展外部中断源的方法,但是需增加硬件开销(见图5)。经或非门引入外中断源输入端(/INT0或/INT1),同时又连到某I/0口。这样,每个“源”都可能引起中断,在中断服务程序中通过软件查询便可确定哪一个是正在申请的中断源,其查询的次序则由中断源优先级决定,这就可实现多个外部中断源的扩展。

2a64430fc0ec874ee202f7ed848e221a.png

图5

这种方法尽管扩展了外部中断源,但也有不尽人意之处,如设计一个具有8个中断源的电路,则需一个8输入端的或非门(或门),显然,对体积与成本都不利。这里介绍笔者设计的扩展外部中断源的方法,由纯软件实现,不添加一个元件(见图6)。

bc6caf5f48bd7f985052383116aada9b.png

图6

#include 《 P》

static unsigned char data m;//m为全局变量

/*-------延时子程序-------*/

void delay(unsigned int k)

{

unsigned int i,j;

for(i=0;i

for(j=0;j《121;j++)

{;}}

}

/*---外部中断INT0子程序---*/

void init0()interrupt 0

{

delay(10);//延时10mS抗抖动干扰

if(P3_2==0)

{

EX0=0;//关INT0中断

EA=0;//关总中断

P3_2=0;//置P3.2为低电平

P2=0xff;//置P2口为全1

m=P2;//读取P2口状态至m

P2=0x00;//恢复P2口为全0

P3_2=1; //置P3.2为高电平

IT0=1;//置INT0为边沿触发

EX0=1; //开INT0中断

EA=1;} //开总中断

}

/********主程序*********/

void main(void)

{

P2=0x00;// 置P2口为全0

P3_2=1;// 置P3.2为高电平

IT0=1;// 置INT0为边沿触发

EX0=1;// 开INT0中断

EA=1; //开总中断

while(1)//无限循环

{

P0=m;//将全局变量m中的内容输出至P0口

P3_0=!P3_0;//P3.0取反,指示程序状态

delay(500);//延时500mS

}

}

程序解释:无按键按下时,P3.0的发光管闪亮,作程序状态显示。主程序初始化时,置P2口为全0,置P3.2为高电平,同时置INT0为边沿触发,并开放中断。8个按键的任一个按下时都会引起INT0中断,进入中断服务子程序后,首先关闭中断,然后置P3.2为低电平,置P2口为全1,再读取P2口状态至m,通过查询m的状态字即可知道正在申请的中断源。这里我们采用的方法是将m输出至P0口点亮LED作指示。退出中断时,重新开放中断。

三。库函数的生成

当将自己开发的程序提供给他人使用但又不便公开源代码时,把源代码做成库函数是一种可行的办法,这样可以保护自己的知识产权及利益,这里我们介绍生成库函数的方法及使用。

/*------------程序名test1.c------------*/

void delay(unsigned int k)

{

unsigned int i,j;

for(i=0;i

for(j=0;j《121;j++)

{;}}

}

1.按照keil的使用方法,建立工程文件test1.uv2并添加上面的源程序test1.c。

2.点击工程,在弹出的下拉菜单中点Options for Target ‘Target 1’,在Output 页面中,选中“Create Library:”后进行编译,则在指定的路径上生成与项目同名的“Lib”文件(图1)。需注意的是,存储模式(Large或Small)应与所使用的系统设置相同。

ec263106162badb349dac0b5e2ccdbd1.png

图1

3. 建立另一个工程文件test2.uv2。

/*------------程序名test2.c------------*/

#include P 晶振频率12.000MHz《》

/****************/

extern void delay(void);

void main (void)//主函数,其功能使P1.0交替输出高、低电平的方波

{

while(1)

{P1_0=!P1_0;

delay();}

}

4.将包含主程序的test2.c及刚才生成的test1.LIB添加到工程中(图2)。在Output 页面中,勾选建立hex文件。

4b559b9f955c02e5d7185115e6ff7cba.png

图2

5. 点击Rebuild target(重建所有目标文件)即可得到编译结果(图3)。

30b0ed5521f39b0b1725299799b69ba1.png

图3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值