[STC单片机]

执行代码超级短的 STC系列专用 初始化IO口函数 宏定义!!!

[复制链接]
722|15
手机看帖
扫描二维码
随时随地手机跟帖
laoxu|  楼主 | 2023-2-17 05:33 | 显示全部楼层 |阅读模式
本帖最后由 laoxu 于 2023-2-19 21:00 编辑

//========================================================================
// 函数: u8        GPIO_Inilize(u8 GPIO, GPIO_InitTypeDef *GPIOx)
// 描述: 初始化IO口.
// 参数: GPIOx: 结构参数,请参考timer.h里的定义.
// 返回: 成功返回 SUCCESS, 错误返回 FAIL.
// 版本: V1.0, 2012-10-22
//========================================================================
u8  GPIO_Inilize(u8 GPIO, GPIO_InitTypeDef *GPIOx);

typedef struct
{
        u8        Mode;                //IO模式,                  GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        u8        Pin;                //要设置的端口        
} GPIO_InitTypeDef;


#################################################################
#################################################################
#################################################################


STC 的 初始化IO口函数, 使用了结构体, 将简单的 对寄存器 PxM1,PxM0 赋值, 搞成一大堆指令。

又是指针,又是判断,程序执行效率极低,我特用宏定义 编写了一个,执行效率极高,功能完全兼容。

程序执行时,仅对寄存器 PxM1,PxM0 赋值, 相当于用 汇编语言直接编写。

当时编写了一个通用型的,能自动识别 STC51、STC16、STC32系列,并给出相对应单片机型的最优化的执行代码。

但后来感觉 H头文件有点复杂有点长,现将其拆分,分别对应于 STC51系列 和 STC251(STC16、STC32)系列 。

现分享给大家 。


网友测试时,可单步运行查看运行结果,也可直接查看检查反汇编程序。

STC_GPIO.rar (29.71 KB)

使用特权

评论回复

相关帖子

laoxu|  楼主 | 2023-2-17 05:42 | 显示全部楼层

#ifndef        __STC_GPIO_H
#define        __STC_GPIO_H

/***************************************************************************************
        Model                : STC_GPIO.H
        Description        : Head file of defining global variable.
        Author                : CLR
        Create Time        : 2023-04-17
        Version ID  : 2.0

        用  途      :通用型, 能对宏晶 STC51/STC16/STC32系列MCU,
                      自动识别, 给出最优化的执行代码!
        作  者      :许意义
        21ic  ID    :LAOXU
        中颖论坛    : bbs.21ic.com   
****************************************************************************************/

//========================================================================
//                              定义声明
//========================================================================

// 请注意, 为了便于下面的宏定义, GPIO输入输出模式, 与官方定义不同!!!
#define        GPIO_PullUp                0L        //上拉准双向口
#define        GPIO_OUT_PP                1L        //推挽输出
#define        GPIO_HighZ                2L        //浮空输入
#define        GPIO_OUT_OD                3L        //开漏输出

/*------------------------------------------------------------------------------------

                            ===========编 程 实 例===========

                               ------Cortex-M051风格1------

1.void GPIO_SET_MODE(Pn, b7,b6,b5,b4,b3,b2,b1,b0);          // 设置IO口输入输出模式(n=0-7)   

  使用方式:
  GPIO_SET_MODE(P3, PullUp,HighZ,PullUp,HighZ,OUT_PP,OUT_OD,OUT_PP,OUT_OD);
                 // 设置P3口的bit.7-bit.0位,依次为PullUp,HighZ,PullUp,HighZ,OUT_PP,OUT_OD,OUT_PP,OUT_OD模式


2.void GPIO_SET_PIN_MODE(Port, Pin_Mode);                 // 设置IO口其中1位或数位输入输出模式(N=0-7,i=0-7)  

  例如:
  GPIO_SET_PIN_MODE(P3, OUT_OD_Pin6);        // 设置P3口的第bit.6位为OUT_OD模式

  GPIO_SET_PIN_MODE(P2, PullUp_Pin5 | OUT_PP_Pin2 | HighZ_Pin0);        // 设置P2口的第bit.5位为PullUp模式,第bit.2位为OUT_PP模式,第bit.0位为HighZ模式
--------------------------------------------------------------------------------------*/

#define        GPIO_SET_MODE(Port, b7,b6,b5,b4,b3,b2,b1,b0)            Port##_SET_MODE(b7,b6,b5,b4,b3,b2,b1,b0)   

#define        GPIO_SET_PIN_MODE(Port, Pin_Mode)                       Port##_SET_PIN_MODE(Pin_Mode)        

/*------------------------------------------------------------------------------------

                              ------Cortex-M051风格2------

3.void Pn_SET_MODE(b7,b6,b5,b4,b3,b2,b1,b0);          // 设置Pn IO口输入输出模式(n=0-4)   

  使用方式:
  P3_SET_MODE(PullUp,HighZ,PullUp,HighZ,OUT_PP,OUT_OD,OUT_PP,OUT_OD);
                 // 设置P3口的bit.7-bit.0位,依次为PullUp,HighZ,PullUp,HighZ,OUT_PP,OUT_OD,OUT_PP,OUT_OD模式


4.void Pn_SET_PIN_MODE(Pin_Mode);                 // 设置Pn IO口其中1位或数位输入输出模式(N=0-7,i=0-7)  

  例如:
  P3_SET_PIN_MODE(OUT_OD_Pin6);        // 设置P3口的第bit.6位为OUT_OD模式

  P2_SET_PIN_MODE(PullUp_Pin5 | OUT_PP_Pin2 | HighZ_Pin0);        // 设置P2口的第bit.5位为PullUp模式,第bit.2位为OUT_PP模式,第bit.0位为HighZ模式
--------------------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------------

                               -------51系列风格-------

5.u8 GPIO_Mode(b7,b6,b5,b4,b3,b2,b1,b0);  设置IO口输入输出模式  

  使用方式:
  PnMode = GPIO_Mode(b7,b6,b5,b4,b3,b2,b1,b0);  设置IO口输入输出模式

  P3Mode = GPIO_Mode(PullUp,HighZ,PullUp,HighZ,OUT_PP,OUT_OD,OUT_PP,OUT_OD);
                 // 设置P3口的bit.7-bit.0位,依次为PullUp,HighZ,PullUp,HighZ,OUT_PP,OUT_OD,OUT_PP,OUT_OD模式

--------------------------------------------------------------------------------------*/



使用特权

评论回复
ayb_ice| | 2023-2-17 09:50 | 显示全部楼层
本帖最后由 ayb_ice 于 2023-2-23 11:50 编辑

一个简单的宏被你搞成这么复杂还说别人的复杂,看我的定义





//GPIOI_XXX
//准双向口,标准的51
#define __GPIO_STD(Px, BITy)\
{\
    Px##M1 &= ~(BITy);\
    Px##M0 &= ~(BITy);\
}

//推挽输出
#define __GPIO_PP(Px, BITy)\
{\
    Px##M1 &= ~(BITy);\
    Px##M0 |=  (BITy);\
}

//高阻输入
#define __GPIO_HZ_INPUT(Px, BITy)\
{\
    Px##M1 |= (BITy);\
    Px##M0 &= ~(BITy);\
}

//开漏输出
#define __GPIO_OD(Px, BITy)\
{\
    Px##M1 |= (BITy);\
    Px##M0 |= (BITy);\
}

//输出1
#define __GPIO_SET(Px, BITy)\
{\
    Px |=  (BITy);\
}

//输出0
#define __GPIO_CLR(Px, BITy)\
{\
    Px &=  ~(BITy);\
}

//反转
#define __GPIO_TGL(Px, BITy)\
{\
    Px ^=  (BITy);\
}

//BIT
#define BIT(x)  (1<<(x))
#define BIT0    BIT(0)
#define BIT1    BIT(1)
#define BIT2    BIT(2)
#define BIT3    BIT(3)
#define BIT4    BIT(4)
#define BIT5    BIT(5)
#define BIT6    BIT(6)
#define BIT7    BIT(7)

#define GPIO_STD(Px_BITx)       __GPIO_STD(Px_BITx)     
#define GPIO_PP(Px_BITx)        __GPIO_PP(Px_BITx)      
#define GPIO_HZ_INPUT(Px_BITx)  __GPIO_HZ_INPUT(Px_BITx)
#define GPIO_OD(Px_BITx)        __GPIO_OD(Px_BITx)      
#define GPIO_SET(Px_BITx)       __GPIO_SET(Px_BITx)
#define GPIO_CLR(Px_BITx)       __GPIO_CLR(Px_BITx)
#define GPIO_TGL(Px_BITx)       __GPIO_TGL(Px_BITx)

#define LED1    P2,BIT0
#define LED1_2    P2,(BIT0+BIT1)
#define LED1_ON()   GPIO_CLR(LED1)
#define LED1_OFF()  GPIO_SET(LED1)
#define LED1_TGL()  GPIO_TGL(LED1)

#define LED1_2_ON()   GPIO_CLR(LED1_2)
#define LED1_2_OFF()  GPIO_SET(LED1_2)
#define LED1_2_TGL()  GPIO_TGL(LED1_2)

这是我一直使用的方法,适用不同的MCU,只需要简单的移植,直观,高效,好维护,好移植

使用如下void Test(void)
{
    GPIO_PP(LED1);

    while (1)
    {
        LED1_TGL();
        Delay(500ms);
        LED1_2_TGL();
        Delay(500ms);
    }
}













使用特权

评论回复
coody| | 2023-2-17 16:38 | 显示全部楼层
ayb_ice 发表于 2023-2-17 09:50
一个简单的宏被你搞成这么复杂还说别人的复杂,看我的定义

我的跟这个基本一样。30年前开始用51,十几年前才用ARM,然后就用这样的宏编程51一样设置、操作ARM的IO,呵呵!我都简化成比如: SET(PA3),CLR(PB2),CPL(PC5)。

使用特权

评论回复
ayb_ice| | 2023-2-17 16:50 | 显示全部楼层
coody 发表于 2023-2-17 16:38
我的跟这个基本一样。30年前开始用51,十几年前才用ARM,然后就用这样的宏编程51一样设置、操作ARM的IO, ...

异曲同工

使用特权

评论回复
laoxu|  楼主 | 2023-2-18 11:59 | 显示全部楼层
楼上的, 只能对 I/O口, 整体赋值 上拉准双向口//推挽输出/浮空输入/开漏输出 其中一项.
而我这宏定义, 可以对 I/O口的每一位 , 分别 赋值  上拉准双向口//推挽输出/浮空输入/开漏输出, 宏定义当然会复杂一些.

这个风格, 完全是 模仿 STC原库, 只是将其 费时费力的结构体指针, 改为 宏定义, 使得编译后的执行代码, 等同于对


寄存器 PxM1,PxM0 直接赋值, 相当于用 汇编语言编写。


原喜欢这种风格的, 可下载参考一下, 不喜欢也没事, 众口难调~~~

使用特权

评论回复
autopccopy| | 2023-2-19 11:08 | 显示全部楼层
不错。
STC也提供IO设置工具及原厂的库函数。

358
STC原厂库函数-230217.png
STC-IO设置工具.png

使用特权

评论回复
laoxu|  楼主 | 2023-2-19 21:03 | 显示全部楼层
本帖最后由 laoxu 于 2023-2-19 21:05 编辑

楼上库文件已更新 !!!

STC_GPIO.rar (29.71 KB)

使用特权

评论回复
coody| | 2023-2-20 19:04 | 显示全部楼层
laoxu 发表于 2023-2-18 11:59
楼上的, 只能对 I/O口, 整体赋值 上拉准双向口//推挽输出/浮空输入/开漏输出 其中一项.
而我这宏定义, 可以 ...

不是哦,宏可以单个IO设置,也可以整体赋值。带参数的宏哦。

使用特权

评论回复
oufuqiang| | 2023-2-23 11:09 | 显示全部楼层
你们各路大神尽管打架,我在旁边记笔记就行

使用特权

评论回复
laoxu|  楼主 | 2023-2-24 19:05 | 显示全部楼层
coody 发表于 2023-2-20 19:04
不是哦,宏可以单个IO设置,也可以整体赋值。带参数的宏哦。

我那可以只对几个需要更改的 I/O口作修改, 你那不行.  

例如:

GPIO_SET_PIN_MODE(P2, PullUp_Pin5 | OUT_PP_Pin2 | HighZ_Pin0);        // 设置P2口的第bit.5位为PullUp模式,第bit.2位为OUT_PP模式,第bit.0位为HighZ模式

使用特权

评论回复
coody| | 2023-2-25 21:40 | 显示全部楼层
本帖最后由 coody 于 2023-2-25 21:46 编辑
laoxu 发表于 2023-2-24 19:05
我那可以只对几个需要更改的 I/O口作修改, 你那不行.  

例如:

我的宏只能设置一种模式,可以单个IO设置,也可以整组IO设置。
只设置一个IO:GPIO_PP(P1, BIT0);   //设置P1.0为推挽输出
   设置多个IO:GPIO_PP(P1, BIT2+BIT1+BIT0);   //设置P1.0 P1.1 P1.2为推挽输出
   设置多个IO:GPIO_PP(P2, 0xf0);   //设置P2.7 P2.6 P2.5 P2.4为推挽输出
#define LED1    P2,BIT0
只设置一个IO:GPIO_PP(LED1);   //设置LED1(P2.0)为推挽输出

只是多一种方法,并不否认你的方法,看各自需要。我喜欢简单的,比较直观,混合设置我担心会混乱。

使用特权

评论回复
laoxu|  楼主 | 2023-3-5 20:03 | 显示全部楼层
coody 发表于 2023-2-25 21:40
我的宏只能设置一种模式,可以单个IO设置,也可以整组IO设置。
只设置一个IO:GPIO_PP(P1, BIT0);   //设 ...

你的理解不正确.

我这宏定义, 可以对 I/O口的每一位 , 分别 赋值  上拉准双向口//推挽输出/浮空输入/开漏输出, 宏定义当然会复杂一些.

是指需要 PxM0,  PxM1 同时设置的 情况, 而不是像你现在这样, 对 单一寄存器 赋值.

例如:
GPIO_SET_PIN_MODE(P2, PullUp_Pin5 | OUT_PP_Pin2 | HighZ_Pin0);        // 设置P2口的第bit.5位为PullUp模式,第bit.2位为OUT_PP模式,第bit.0位为HighZ模式

使用特权

评论回复
laoxu|  楼主 | 2023-3-5 20:05 | 显示全部楼层
而没有设置的位, 维持不变.

使用特权

评论回复
coody| | 2023-3-6 11:00 | 显示全部楼层
本帖最后由 coody 于 2023-3-6 11:01 编辑
laoxu 发表于 2023-3-5 20:03
你的理解不正确.

我这宏定义, 可以对 I/O口的每一位 , 分别 赋值  上拉准双向口//推挽输出/浮空输入/开 ...

你可能没细看,我的宏也是一样同时设置 PxM0,  PxM1的。
不要怀疑我们的宏做不到,毕竟用来做产品都20多年了,后来移植到ARM,宏操作都一样,移植性非常好。带参数的宏,像函数一样是可以同时操作多个寄存器、变量的。

使用特权

评论回复
zhxzhxzzhhxx| | 2023-3-9 21:23 | 显示全部楼层
ayb_ice 发表于 2023-2-17 09:50
一个简单的宏被你搞成这么复杂还说别人的复杂,看我的定义

我是这样写的:
#define        Pin0                0x01        //IO引脚 Px.0
#define        Pin1                0x02        //IO引脚 Px.1
#define        Pin2                0x04        //IO引脚 Px.2
#define        Pin3                0x08        //IO引脚 Px.3
#define        Pin4                0x10        //IO引脚 Px.4
#define        Pin5                0x20        //IO引脚 Px.5
#define        Pin6                0x40        //IO引脚 Px.6
#define        Pin7                0x80        //IO引脚 Px.7
#define        PinAll        0xFF        //IO所有引脚

#define P0n_standard(bitn)                        P0M1 &= ~(bitn),        P0M0 &= ~(bitn)        //00 标准
#define P0n_push_pull(bitn)                        P0M1 &= ~(bitn),        P0M0 |=  (bitn)        //01 推挽
#define P0n_pure_input(bitn)                P0M1 |=  (bitn),        P0M0 &= ~(bitn)        //10 输入
#define P0n_open_drain(bitn)                P0M1 |=  (bitn),        P0M0 |=  (bitn)        //11 开漏

#define P1n_standard(bitn)                        P1M1 &= ~(bitn),        P1M0 &= ~(bitn)
#define P1n_push_pull(bitn)                        P1M1 &= ~(bitn),        P1M0 |=  (bitn)
#define P1n_pure_input(bitn)                P1M1 |=  (bitn),        P1M0 &= ~(bitn)
#define P1n_open_drain(bitn)                P1M1 |=  (bitn),        P1M0 |=  (bitn)

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:猜猜俺是谁的马夹?

146

主题

2274

帖子

221

粉丝