STC利用宏设置IO新方法,精简编译代码(原创)

本文介绍了一种使用宏来快速配置STC单片机IO口的方法,包括设置弱上拉、推挽、高阻态和输入状态等。通过具体的宏定义和示例代码展示了如何简化IO配置过程。

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

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;//B‭10111111‬
P1M1 |= 0x40;//B‭01000000‬

这个宏没增加编译代码,而且方便记忆,修改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文件,直接可以调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值