开篇:润墨网以专业的文秘视角,为您筛选了一篇基于PICC编译器中C语言与汇编语言混编的分析范文,如需获取更多写作素材,在线客服老师一对一协助。欢迎您的阅读与分享!
摘要:文章通过9个程序详细介绍PIC单片机在picc编译器环境下,C语言与汇编语言混合编程的方法并对出现的情况进行分析解决,最后对C语言与汇编语言混合编程的优劣提出自已的看法。
关键词:PIC单片机;PICC编译器;C语言;汇编语言
中图分类号:TP312文献标识码:A文章编号:1009-3044(2010)11-2640-05
Analysis Based on C Language and Assembler Language Mix Programming in PICC Compiler
LIU Jin-ping, YE Sai-feng
(Fujian Electric Vocational and Technical College, Quanzhou 362000, China)
Abstract: Articles detailed C language and assembly language mixed programming methodology and anslysis and settlement according to these problems of PIC singlechip in PICC compiler environment through 9 program and lastly presented their own views on the advantages and disadvantages of C language and assembly language mixed programming .
Key words: PICC singlechip; PICC compiler; C language; assembler language
目前,最常用PIC单片机C语言编程环境是MATLAB调试环境和HI-TECH编译器PICC。虽然还有众多支持PIC单片机的C语言编译器,但PICC因为稳定、可靠、编译生成的代码效率高,而受到青睐。用C语言来开发PIC单片机系统软件最大的好处是编写代码效率高,软件高度直观、维护升级方便、代码的重复利用率高、便于跨平台的代码移植等。因此用C语言编程,在进行系统设计和开发的工程师群体中得到广泛认可。既然C语言是一种强有力的程序设计语言,那么是不是就可以抛弃汇编语言?写单片机C程序最关键的一点是单片机内设资源非常有限,同时,要求控制的实时性高,这就要求对单片机体系结构和硬件资源有详尽的了解,而这些恰恰是汇编语言的优势,所以对于PIC爱好者,尤其初学者而言,C语言与汇编语言混编是不可避免的。实际上,C语言和汇编语言混合编程可以使单片机应用程序的开发效率和程序本身的运行效率达到最佳的配合。
1 PICC对RAM的特殊要求
下面,我们通过一个引例的不同编程来看PICC对RAM的特殊要求。
例:将RAM中的BANK0的0X20~0X2F共16个单元置为55H。
1.1 采用汇编语言编程
程序1:
INCLUDE "P16F877.INC"
MOVLW 0X20
MOVWF FSR
MOVLW 55H
ABC MOVWFINDF
INCF FSR ,F
BTFSSFSR ,4
GOTOABC
GOTO$
END
程序1经过调试,运行后能实现引例功能。
1.2 采用C语言编程
程序2:
#include"pic.h"
unsigned char i;
unsigned char *tmp;
void main()
{
tmp=0x20;
for(i=1;i
{
(*tmp)=0x55;
tmp++;
}
}
程序2中运用指针知识,经过调试没有发现错误,但运行后根本无法满足引例的要求。
修改程序2第2行为:“bank2 unsigned char i;”,即变量i改到RAM的BANK2。运行的结果是将0X56~0X64共15个单元置为55H。再次将程序2第6行修改为:“tmp=0x21;”,运行后,RAM的0X21~0X30共16个单元置为55H,离要求还有一点距离。
1.3 采用C语言绝对定位技术
程序3:
#include"pic.h"
bank2 unsigned char i;
static volatile unsigned char *tmp @ 0x30;
void main()
{
tmp=0x20;
for(i=1;i
{
(*tmp)=0x55;
tmp++;
}
}
程序3将定义的指针定位在BANK0的0X30单元开始的区域,与0X20~0X2F区域没有冲突。经过调试运行能实现引例功能。
1.4 采用C语言与汇编语言混编
程序4:
#include"pic.h"
bank2 unsigned char i;
void main()
{ #asm
MOVLW0X20
MOVWF_FSR
MOVLW0X55
MOVWF_INDF
#endasm
for(i=1;i
{ #asm
INCF _FSR,F
MOVLW0X55
MOVWF _INDF
#endasm
}
}
程序4中唯一变量i 定义在RAM的BANK2区域,程序经过调试运行能实现引例功能。要说明的是,C语言与汇编语言混编时,汇编语言部分的特殊功能寄存器名必须采用下划线引导和大写字母。
从以上不同方法的编程出现的结果,可以看出在C语言环境下,PICC对File Registers(RAM数据存储器)中的20H~7FH单元具有绝对使用权,这些单元位于BANK0的最后,即通用寄存器的96个字节。所以,在编程时若要应用这部分单元,那么,则在C语言中定义的所有变量必须放在除BANK0外的RAM中,否则运行结果不可预料。
2 PICC混编时对传递参数的要求
2.1 采用局部变量进行主函数与自定义函数之间的数据传递
PICC规定,应用局部变量传递数据,在汇编语言部分引用参数时,第2 个形参要写成?_函数名,第3个形参要写成?_函数名+1,以此类推。而第1个形参以及函数内部自定义变量必须分别命名为?a_函数名,?a_函数名+1,……,至于?a_函数名先分配给第1个形参或是第1个自定义变量则不确定。
程序5:
#include
void Test(unsigned char inVar1, unsigned char inVar2,unsigned char inVar3,unsigned char inVar4)
{
unsigned char tmp1=0;
inVar1++;
asm("incf ?a_Test+1,f");
asm("decf ?_Test,f");//inVar2--;
#asm //inVar3+=5;
movf ?_Test+1,w
addlw 0x5
movwf ?_Test+1
#endasm
#asm //inVar4-=0x5左移一位,低位补1;
bsf _STATUS,0
rlf ?_Test+2,f
#endasm
#asm //tmp1=inVar1;
movf ?a_Test+1,w
movwf ?a_Test
#endasm
}
void main()
{
unsigned char t1,t2;
t1=t2=10;
Test(t1,t2,t1,t2);
}
程序5中的自定义函数名为Test,共有inVar1~inVar4等4个形参,函数内部还有1个自定义变量tmp1。在汇编语言中inVar1写成?a_Test+1、inVar2~inVar4分别写成?_Test~?_Test+2、而tmp1写成?a_Test。需要说明的是:
1) 程序中C语言部分若不对第1个形参inVar1进行操作,则在汇编语言部分中对inVar1处理是无效的!也就是不分配内在单元给inVar1。
2) 程序中C语言部分若不对函数内部的自定义tmp1进行赋值或运算,则在汇编部分对tmp1处理是无效的,也就是不分配RAM空间。
以上两点,在进行C语言与汇编语言混编时应特别关注。
2.2 采用全局变量进行主函数与自定义函数之间的数据传递
程序6:
#include
volatile unsigned char tmp;
volatile bank1 unsigned char tmp1;
volatile bank2 unsigned char tmp2;
void Test(void)
{
#asm
clrf _STATUS
movlw 0x55
movwf _tmp
#endasm
}
void Test1(void)
{
#asm
clrf _STATUS
movlw 0x10
movwf _tmp
bcf _STATUS,6
BSF _STATUS,5
movlw 0x20
movwf _tmp1^0x80;非BANK0变量,在汇编语言中使用要如此
#endasm
}
void main()
{
while(1)
{
Test1();
if(tmp==0x10)
{
tmp=0xab;
}
if(tmp1==0x20)
{
tmp1=0xcd;
}
Test();
tmp2=tmp+tmp1;
}
}
程序6采用全局变量传递数据,共定义tmp、tmp1、tmp2三个全局变量,分别定义在RAM的BANK0、BANK1、BANK2,其中tmp、tmp1用于函数之间传递函数,在汇编语言部分要使用这两个全局变量时,只要在变量名前加下划线作为引导就可以了。但要注意的是,若这些全局变量定义在非BANK0,如程序中的tmp,则在汇编语言部分使用时,必须写成_tmp1^0x80。若是定义在BANK1,就得写成_tmp1^0x100,若是定义在BANK2,就得写成_tmp1^0x180。
程序7:
#include
volatile unsigned char inVar1,inVar2,inVar3,inVar4;
void Test()
{
unsigned char tmp1=0;
//inVar1-=1;
asm("incf _inVar1,f");
//inVar2--;
asm("decf _inVar2,f");
//inVar3+=5;
#asm
movf _inVar3,w
addlw 0x5
movwf _inVar3
#endasm
//inVar4-=0x5左移一位,低位补1;
#asm
bsf _STATUS,0
rlf _inVar4,f
#endasm
//tmp1=inVar1;
#asm
movf _inVar1,w
movwf ?a_Test
#endasm
}
void main()
{
unsigned char tmp1=2;
inVar1=inVar2=inVar3=inVar4=10;
Test();
inVar1=inVar4;inVar3=tmp1;
}
程序7除定义了全局变量,还在自定义函数中定义了一个自定义变量tmp1,同样在汇编部分要换名为?a_Test,需要说明的是,若对tmp1不赋初值,那么在汇编时会出现“找不到?a_Test”错误信息,而无法通过汇编。
使用全局变量最大的好处是寻址直观,只需在 C 语言定义的变量名前增加一个下划线,即可在汇编语句中寻址,使用全局变量进行参数传递效率比形参传递高。
3 C语言主函数内含汇编语言的情况
程序8:
#include
void main()
{
unsigned char tmp,i;
while(1)
{
tmp=1;
#asm
movf ?a_main+1,w
movwf ?a_main
#endasm
i++;
} }
程序8在主函数内定义两个变量,这两个变量在汇编语言部分使用时,必须换名为 ?a_main和 ?a_main+1,需要说明的是,第1 个自定义变量tmp,在汇编语言部分使用?a_main前,在C语言部分必须先进行赋初值或计算,否则会出现错误。
程序9:
#include
volatileunsigned char tmp,i;
void main()
{
while(1)
{
//tmp=1;
#asm
movf _i,w
movwf _tmp
#endasm
i++;
} }
程序9在主函数外定义了两个全局变量,它们在汇编语言部分使用比较简单,只要在变量前加下划线引导就可以。
4 结束语
可以看出,C语言和汇编语言混合编程在具体实施时,一定要注意许多细节问题,否则运算结果不可预料。
一般来说,在项目开发过程中,程序量较大且PICC 进行后道编译优化,采用C语言编写的代码不会比全部用汇编编写的代码差多少。所以,既然用了C语言编程,就尽量避免使用嵌入汇编指令或整个地编写汇编指令模块文件。对于非得采用C语言和汇编语言混合编程,一定要注意:1)尽量使用嵌入汇编;2)尽量使用全局变量进行参数传递。
参考文献:
[1] 李荣正.PIC单片机原理及应用[M].北京:北京航空航天大学出版社,2006.
[2] 周坚.PIC单片机轻松入门[M].北京:北京航空航天大学出版社,2009.
[3] 张明峰.PIC单片机入门与实战[M].北京:北京航空航天大学出版社,2004.