引言
单片机的应用越来越广泛,种类也越来越多。由于嵌入式C语言可读性强、移植性好,与汇编语言相比大大减轻了软件工程师的劳动强度,因而越来越多的单片机工程师开始使用C语言编程。但C语言的可移植性仅限于与硬件无关的子程序,而与具体硬件有关的子程序则无法移植。在单片机应用中,位操作(特别是对引脚的位操作)非常普遍,如EEPROM数据和IC卡数据的读写、字段式LCD显示等,很多带串口的集成电路都需要单片机用软件来做I/O口读写程序。如何让这些子程序既有很好的通用性,生成代码的效率又高,是很多软件工程师都在考虑的问题。这里介绍两种C语言位操作的移植方法。
1 用逻辑运算实现位操作
请看下面这个子程序:
INT8U Card102RdByte(void) {
INT8U Temp8U, n = 8;
do{ Temp8U <<= 1;
if( PIN_CARD_SDA_RD() ) Temp8U |= 0x01;
PIN_CARD_CLK_H();PIN_CARD_CLK_L();
}while(--n);
return Temp8U;
}
这是通过单片机引脚从88SC102卡中读一个字节的子程序。程序采用μC/OSII中的书写风格,即变量和函数采用“驼峰”写法,由define定义的常量和内联函数采用全部大写加下划线的写法。
此程序驱动一个引脚输出CARD_CLK高低信号,从另一个引脚一位一位读取CARD_SDA数据。
1.1 用于MSP430系列单片机
此程序应用到MSP430单片机上(本文用的是MSP430F413单片机),头文件中要有如下定义:
typedefunsigned charINT8U;
#include
#definePIN_CARD_SDA_RD()(P6IN & 0x01)
#definePIN_CARD_CLK_H()P6OUT |=0x04
#definePIN_CARD_CLK_L()P6OUT &= ~0x04
汇编结果如下:
In segment CODE, align 2, keepwithnext
__code unsigned char Card102RdByte(void)
Card102RdByte:
0000007E42MOV.B#0x8, R14
??Card102RdByte_0:
0000024C5CRLA.BR12
000004D2B33400BIT.B#0x1, &0x34
0000080128JNC??Card102RdByte_1
00000A5CD3BIS.B#0x1, R12
??Card102RdByte_1:
00000CE2D23500BIS.B#0x4, &0x35
000010E2C23500BIC.B#0x4, &0x35
0000147E53ADD.B#0xff, R14
0000164E93CMP.B#0x0, R14
000018F423 JNE??Card102RdByte_0
00001A3041RET
这与手工汇编编程的结果几乎一样,代码效率很高。
1.2 用于51系列单片机
在51系列单片机中应用此程序,头文件要加入以下定义:
#include"Reg932.h"//Philips LPC932单片机
sbitCradClk=P0^1;
sbitCardSDA=P0^0;
#definePIN_CARD_SDA_RD()CardSDA
#definePIN_CARD_CLK_H()CradClk=1
#definePIN_CARD_CLK_L()CradClk=0
原来的程序不作任何改动,汇编结果如下:
; FUNCTION Card102RdByte (BEGIN)
;-- Variable 'Temp8U' assigned to Register 'R7' --
;-- Variable 'n' assigned to Register 'R6' --
00007E08MOVR6,#08H
0002?C0007:
0002EFMOVA,R7
000325E0ADDA,ACC
0005FFMOVR7,A
0006308003JNBCardSDA,?C0008
0009430701ORLAR7,#01H
000C?C0008:
000CD281SETBCradClk
000EC281CLRCradClk
0010DEF0DJNZR6,?C0007
0012?C0009:
001222RET
; FUNCTION Card102RdByte (END)
由汇编结果可知,对位的直接清零和置位已达到最简,只是读位值不够理想。
顶一下 0
踩一下
相关文章
用户评论
已有0位网友发表了看法



发表评论