STC利用宏设置IO新方法,精简编译代码
/*
STC的IO有几种配置方式,分别是弱上拉、推挽、高组态、输入,四种状态。
通过对PXM0和PXM1(X为0~5)特殊寄存器设置,网上看到有类似宏的方式设置IO,但是不够简洁,设置的格式类似。
不同系列的STC单片机,可能PXM0和PXM1的顺序可能不一样,根据实际型号调整
下面是宏代码:
*/
#include "STC15F2K60S2.h"
#define BIT0 0x00
#define BIT1 0x01
#define BIT2 0x02
#define BIT3 0x03
#define BIT4 0x04
#define BIT5 0x05
#define BIT6 0x06
#define BIT7 0x07
#define _P0 0
#define _P1 1
#define _P2 2
#define _P3 3
#define _P4 4
#define _P5 5
#define NOR_IO 0 //一般模式
#define STR_O 1 //推挽输出
#define LOS_I 2 //输入状态
#define OC_O 3 //OC门输出
#define _A(x) P##x##M0
#define _B(x) P##x##M1
#define A(x) _A(x)
#define B(x) _B(x)
#define C(x,y,z) ((z%2) == 0 ? (A(x) &= ~(1<<y)) : (A(x) |= (1<<y)))
#define D(x,y,z) ((z/2) == 0 ? (B(x) &= ~(1<<y)) : (B(x) |= (1<<y)))
#define E(x,y) ((y%2) == 0 ? (A(x) = 0) : (A(x) = 0xff))
#define F(x,y) ((y/2) == 0 ? (B(x) = 0) : (B(x) = 0xff))
#define SET_IO(x,y,z) C(x,y,z);D(x,y,z)
#define SET_PORT(x,y) E(x,y);F(x,y)
/
/*
此方法写出的宏能在keil C中编译通过
设置IO方法:SET_IO(_P1,BIT6,LOS_I);
设置PORT方法:SET_PORT(_P2,STR_O);
*/
//譬如要设置P1.6为高组态输入,P1.7为推挽输出,P2为推挽输出端口
void PORT_IO_inti(void)
{
SET_IO(_P1,BIT6,LOS_I); //P1.6为高组态输入
SET_IO(_P1,BIT7,STR_O); //P1.7为推挽出
SET_PORT(_P2,STR_O); //P2为推挽输出
}
void main(void)
{
PORT_IO_inti();
while (1);
}
查看反汇编代码
C:0x0000 020016 LJMP C:0016
139: void PORT_IO_inti(void)
140: {
141: SET_IO(_P1,BIT6,LOS_I); //P1.6为高组态输入
C:0x0003 5392BF ANL P1M0(0x92),#0xBF
C:0x0006 439140 ORL P1M1(0x91),#0x40
142: SET_IO(_P1,BIT7,STR_O); //P1.7为推挽出
C:0x0009 439280 ORL P1M0(0x92),#0x80
C:0x000C 53917F ANL P1M1(0x91),#0x7F
143: SET_PORT(_P2,STR_O); //P2为推挽输出
C:0x000F 7596FF MOV P2M0(0x96),#0xFF
C:0x0012 E4 CLR A
C:0x0013 F595 MOV P2M1(0x95),A
144: }
C:0x0015 22 RET
C:0x0016 787F MOV R0,#0x7F
C:0x0018 E4 CLR A
C:0x0019 F6 MOV @R0,A
C:0x001A D8FD DJNZ R0,C:0019
C:0x001C 758107 MOV 0x81,#0x07
C:0x001F 020022 LJMP main(C:0022)
146: void main(void)
147: {
148: PORT_IO_inti();
C:0x0022 120003 LCALL PORT_IO_inti(C:0003)
150: while (1);
C:0x0025 80FE SJMP C:0025
重点是这几行代码
141: SET_IO(_P1,BIT6,LOS_I); //P1.6为高组态输入
C:0x0003 5392BF ANL P1M0(0x92),#0xBF
C:0x0006 439140 ORL P1M1(0x91),#0x40
142: SET_IO(_P1,BIT7,STR_O); //P1.7为推挽出
C:0x0009 439280 ORL P1M0(0x92),#0x80
C:0x000C 53917F ANL P1M1(0x91),#0x7F
143: SET_PORT(_P2,STR_O); //P2为推挽输出
C:0x000F 7596FF MOV P2M0(0x96),#0xFF
C:0x0012 E4 CLR A
C:0x0013 F595 MOV P2M1(0x95),A
C:0x0003 5392BF ANL P1M0(0x92),#0xBF
C:0x0006 439140 ORL P1M1(0x91),#0x40
写成C语言方式:
P1M0 &= 0xbf;//B10111111
P1M1 |= 0x40;//B01000000
这个宏没增加编译代码,而且方便记忆,修改IO简单.
可以将
#define BIT0 0x00
#define BIT1 0x01
#define BIT2 0x02
#define BIT3 0x03
#define BIT4 0x04
#define BIT5 0x05
#define BIT6 0x06
#define BIT7 0x07
#define _P0 0
#define _P1 1
#define _P2 2
#define _P3 3
#define _P4 4
#define _P5 5
#define NOR_IO 0 //一般模式
#define STR_O 1 //推挽输出
#define LOS_I 2 //输入状态
#define OC_O 3 //OC门输出
#define _A(x) P##x##M0
#define _B(x) P##x##M1
#define A(x) _A(x)
#define B(x) _B(x)
#define C(x,y,z) ((z%2) == 0 ? (A(x) &= ~(1<<y)) : (A(x) |= (1<<y)))
#define D(x,y,z) ((z/2) == 0 ? (B(x) &= ~(1<<y)) : (B(x) |= (1<<y)))
#define E(x,y) ((y%2) == 0 ? (A(x) = 0) : (A(x) = 0xff))
#define F(x,y) ((y/2) == 0 ? (B(x) = 0) : (B(x) = 0xff))
#define SET_IO(x,y,z) C(x,y,z);D(x,y,z)
#define SET_PORT(x,y) E(x,y);F(x,y)
这段代码放在H文件,直接可以调用