ME32x系列MCU IO使用技巧之输出寄存器

文章详细介绍了ME32x系列微控制器的GPIO模块,包括OUT、SET、CLR和NOT寄存器的功能和使用。指出在ARMCPU中,由于不支持BIT操作,直接对单个IO操作可能引发中断安全问题。建议在初始化时使用OUT寄存器,而对单个IO操作应优先考虑SET/CLR以确保执行的确定性。
摘要由CSDN通过智能技术生成
  1. 概述

ME32x系列是内嵌ARM Cortex™ M0/M3核的32位微控制器。该系列控制器由敏矽微电子有限公司自主开发,并具有自主知识产权。敏矽微电子的微控制器包括有通用MCU和专用SOC系列,具有非常高的性价比,是MCU产品升级换代和国外产品替代的最佳选择。通用功能有高精度ADC,CAN接口,I2S音频接口,UART串口,SPI接口,I2C总线接口,看门狗定时器(WDT),通用计数器/定时器。特殊接口包括人机界面控制器(LCD驱动,电容触摸按键)和马达控制功能模块。

GPIO模块

ME32x系列所有MCU都含有多个GPIO模块,每个GPIO模块可以对16个IO通道的输入输出进行控制。GPIO模块主要实现以下功能:

  • 数字管脚可以用软件定义为输入或输出
  • 管脚读写可以被屏蔽
  • 多个管脚的置位、清零位用一条指令实现
  • 管脚的输出取反
  • 每一个管脚可作为外部中断信号
  • 可编程的中断触发条件

其中,实现IO端口输出的寄存器一般有OUT、SET、CLR和NOT。下面我们将对这几个寄存器如何使用做一些讨论。

GPIO输出寄存器

OUT寄存器可以实现IO的0/1输出;

SET寄存器只能实现IO的1输出,并且寄存器写1有效,读为0;

CLR寄存器只能实现IO的0输出,并且寄存器写1有效,读为0;

NOT寄存器只能实现IO的取反输出,并且寄存器写1有效,读为0;

从上面的描述,可以看出:

  • 当我们要IO输出为1时,可以使用OUT或者SET寄存器
  • 当我们要IO输出为0时,可以使用OUT或者CLR寄存器
  • 当我们要IO当前输出取反时,可以简单的使用NOT,当然也可通过软件对当前的状态进行判断后使用OUT/SET/CLR寄存器输出对应的值。

然而由于ARM CPU不支持BIT(位)操作,我们对单个IO的输出不直接操作,只能通过软件结构的变量模式进行操作。这种结构模式可以让软件看起来简单易懂,有的时候甚至给我们带来错觉,认为ARM CPU可以实现单指令的BIT(位)操作,以至于程序员在编程过程中忽略结构的变量BIT(位)操作的真正含义,从而给以中断驱动的嵌入式软件带来不可预知的执行结果。

结构变量定义:

typedef struct {

  union {

    __IO uint32_t  OUT;                             /*!< Pin output value register                                             */

    struct {

      __IO uint32_t  OUT0       :  1;               /*!< GPIO pin PIOn pin PIOn_0 output value                                 */

      __IO uint32_t  OUT1       :  1;               /*!< GPIO pin PIOn pin PIOn_1 output value                                 */

      __IO uint32_t  OUT2       :  1;               /*!< GPIO pin PIOn pin PIOn_2 output value                                 */

      __IO uint32_t  OUT3       :  1;               /*!< GPIO pin PIOn pin PIOn_3 output value                                 */

      __IO uint32_t  OUT4       :  1;               /*!< GPIO pin PIOn pin PIOn_4 output value                                 */

      __IO uint32_t  OUT5       :  1;               /*!< GPIO pin PIOn pin PIOn_5 output value                                 */

      __IO uint32_t  OUT6       :  1;               /*!< GPIO pin PIOn pin PIOn_6 output value                                 */

      __IO uint32_t  OUT7       :  1;               /*!< GPIO pin PIOn pin PIOn_7 output value                                 */

      __IO uint32_t  OUT8       :  1;               /*!< GPIO pin PIOn pin PIOn_8 output value                                 */

      __IO uint32_t  OUT9       :  1;               /*!< GPIO pin PIOn pin PIOn_9 output value                                 */

      __IO uint32_t  OUT10      :  1;               /*!< GPIO pin PIOn pin PIOn_10 output value                                */

      __IO uint32_t  OUT11      :  1;               /*!< GPIO pin PIOn pin PIOn_11 output value                                */

      __IO uint32_t  OUT12      :  1;               /*!< GPIO pin PIOn pin PIOn_12 output value                                */

      __IO uint32_t  OUT13      :  1;               /*!< GPIO pin PIOn pin PIOn_13 output value                                */

      __IO uint32_t  OUT14      :  1;               /*!< GPIO pin PIOn pin PIOn_14 output value                                */

      __IO uint32_t  OUT15      :  1;               /*!< GPIO pin PIOn pin PIOn_15 output value                                */

    } OUT_b;                                        /*!< BitSize                                                               */

  };

   union {

    __O  uint32_t  SET;                             /*!< Pin output value set register                                         */

    struct {

      __O  uint32_t  SET0       :  1;               /*!< Set GPIO pin PIOn_0 output value                                      */

      __O  uint32_t  SET1       :  1;               /*!< Set GPIO pin PIOn_1 output value                                      */

      __O  uint32_t  SET2       :  1;               /*!< Set GPIO pin PIOn_2 output value                                      */

      __O  uint32_t  SET3       :  1;               /*!< Set GPIO pin PIOn_3 output value                                      */

      __O  uint32_t  SET4       :  1;               /*!< Set GPIO pin PIOn_4 output value                                      */

      __O  uint32_t  SET5       :  1;               /*!< Set GPIO pin PIOn_5 output value                                      */

      __O  uint32_t  SET6       :  1;               /*!< Set GPIO pin PIOn_6 output value                                      */

      __O  uint32_t  SET7       :  1;               /*!< Set GPIO pin PIOn_7 output value                                      */

      __O  uint32_t  SET8       :  1;               /*!< Set GPIO pin PIOn_8 output value                                      */

      __O  uint32_t  SET9       :  1;               /*!< Set GPIO pin PIOn_9 output value                                      */

      __O  uint32_t  SET10      :  1;               /*!< Set GPIO pin PIOn_10 output value                                     */

      __O  uint32_t  SET11      :  1;               /*!< Set GPIO pin PIOn_11 output value                                     */

      __O  uint32_t  SET12      :  1;               /*!< Set GPIO pin PIOn_12 output value                                     */

      __O  uint32_t  SET13      :  1;               /*!< Set GPIO pin PIOn_13 output value                                     */

      __O  uint32_t  SET14      :  1;               /*!< Set GPIO pin PIOn_14 output value                                     */

      __O  uint32_t  SET15      :  1;               /*!< Set GPIO pin PIOn_15 output value                                     */

    } SET_b;                                        /*!< BitSize                                                               */

  };

  union {

    __O  uint32_t  CLR;                             /*!< Pin output value clear register                                       */

    struct {

      __O  uint32_t  CLR0       :  1;               /*!< Clear GPIO pin PIOn_0 output value                                    */

      __O  uint32_t  CLR1       :  1;               /*!< Clear GPIO pin PIOn_1 output value                                    */

      __O  uint32_t  CLR2       :  1;               /*!< Clear GPIO pin PIOn_2 output value                                    */

      __O  uint32_t  CLR3       :  1;               /*!< Clear GPIO pin PIOn_3 output value                                    */

      __O  uint32_t  CLR4       :  1;               /*!< Clear GPIO pin PIOn_4 output value                                    */

      __O  uint32_t  CLR5       :  1;               /*!< Clear GPIO pin PIOn_5 output value                                    */

      __O  uint32_t  CLR6       :  1;               /*!< Clear GPIO pin PIOn_6 output value                                    */

      __O  uint32_t  CLR7       :  1;               /*!< Clear GPIO pin PIOn_7 output value                                    */

      __O  uint32_t  CLR8       :  1;               /*!< Clear GPIO pin PIOn_8 output value                                    */

      __O  uint32_t  CLR9       :  1;               /*!< Clear GPIO pin PIOn_9 output value                                    */

      __O  uint32_t  CLR10      :  1;               /*!< Clear GPIO pin PIOn_10 output value                                   */

      __O  uint32_t  CLR11      :  1;               /*!< Clear GPIO pin PIOn_11 output value                                   */

      __O  uint32_t  CLR12      :  1;               /*!< Clear GPIO pin PIOn_12 output value                                   */

      __O  uint32_t  CLR13      :  1;               /*!< Clear GPIO pin PIOn_13 output value                                   */

      __O  uint32_t  CLR14      :  1;               /*!< Clear GPIO pin PIOn_14 output value                                   */

      __O  uint32_t  CLR15      :  1;               /*!< Clear GPIO pin PIOn_13 output value                                   */

    } CLR_b;                                        /*!< BitSize                                                               */

  };

  union {

    __O  uint32_t  NOT;                             /*!< Pin output value invert register                                      */

    struct {

      __O  uint32_t  NOT0       :  1;               /*!< Invert GPIO pin PIOn_0 output value                                   */

      __O  uint32_t  NOT1       :  1;               /*!< Invert GPIO pin PIOn_1 output value                                   */

      __O  uint32_t  NOT2       :  1;               /*!< Invert GPIO pin PIOn_2 output value                                   */

      __O  uint32_t  NOT3       :  1;               /*!< Invert GPIO pin PIOn_3 output value                                   */

      __O  uint32_t  NOT4       :  1;               /*!< Invert GPIO pin PIOn_4 output value                                   */

      __O  uint32_t  NOT5       :  1;               /*!< Invert GPIO pin PIOn_5 output value                                   */

      __O  uint32_t  NOT6       :  1;               /*!< Invert GPIO pin PIOn_6 output value                                   */

      __O  uint32_t  NOT7       :  1;               /*!< Invert GPIO pin PIOn_7 output value                                   */

      __O  uint32_t  NOT8       :  1;               /*!< Invert GPIO pin PIOn_8 output value                                   */

      __O  uint32_t  NOT9       :  1;               /*!< Invert GPIO pin PIOn_9 output value                                   */

      __O  uint32_t  NOT10      :  1;               /*!< Invert GPIO pin PIOn_10 output value                                  */

      __O  uint32_t  NOT11      :  1;               /*!< Invert GPIO pin PIOn_11 output value                                  */

      __O  uint32_t  NOT12      :  1;               /*!< Invert GPIO pin PIOn_12 output value                                  */

      __O  uint32_t  NOT13      :  1;               /*!< Invert GPIO pin PIOn_13 output value                                  */

      __O  uint32_t  NOT14      :  1;               /*!< Invert GPIO pin PIOn_14 output value                                  */

      __O  uint32_t  NOT15      :  1;               /*!< Invert GPIO pin PIOn_15 output value                                  */

    } NOT_b;                                        /*!< BitSize                                                               */

  };

}PA_Type;

#define PA_BASE                         0x50060000UL

#define PA                              ((PA_Type                 *) PA_BASE)

调用:

PA->OUT_b.OUT0=0/1;

这个调用将对PA0 IO口实现输出0或者1。如果我们看这条程序的汇编,就会发现,实现这次对PA0的端口操作,实际上经过3个步骤:

  1. 读回PA OUT寄存器值到一个变量
  2. 对变量的BIT0进行逻辑运算实现BIT0的0/1操作
  3. 把变量的值重新写回到PA的OUT寄存器

在如果步骤1/2/3连续执行没有被中断打断,没有问题;如果1/2/3被中断打断,并且在这个中断里也对PA的OUT寄存器进行了操作,那么这个中断对PA OUT寄存器操作将在2/3执行后被覆盖掉,也就意味着在中断里的输出操作结果失效。如果同时有多个中断在执行类似的操作,整个系统会变得无法预知。这就是有人经常讲的输出不工作。。。

如果我们把OUT寄存器换成SET、CLR去执行输出1/0会怎么样呢?

PA->SET_b.SET0=1; //输出1

PA->CLR_b.CLR0=1; //输出0

虽然它也经历了寄存器读回、修改,然后写回操作,由于它只有写1有效,读为0,它无法对除PA0 IO口外其它IO造成任何影响,即使在执行读回、修改、写回操作时被其它中断打断。

总结

在对GPIO整个端口16个IO输出初始化时,可以采用OUT寄存器直接赋值

在对单个IO进行操作时,不论什么情况,都不要使用OUT寄存器,取而代之的是采用SET/CLR输出1/0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值