i.MX25 系列的 GPIO 口大多是复用口,如果我们想将某 IO 口设置为输入或输出,首先需通过复用配置寄存器将该 IO 口配置为 GPIO ,然后再配置 GPIO 的相关寄存器。
通过配置 SW_MUX_CTL 寄存器选择 IO 口的工作模式,每一个管脚都对应一个 SW_MUX_CTL 寄存器,具体通过如下描述:
IOMUXC_SW_MUX_CTL_PAD_<Pin_Name>
这里 <Pin_Name> 为管脚名。寄存器对应描述见表 1 :
表 1 : SW_MUX_CTL 寄存器描述
通过配置 SW_PAD_CTL 设置 IO 口的驱动电压,回转率,驱动强度,开漏,上拉, DDR 类型等。有些管脚需要通过 SW_PAD_CTL_GRP 设置一组 IO 口。 SW_PAD_CTL 寄存器通过如下描述:
IOMUXC_SW_PAD_CTL_PAD_<Pin_Name>
这里 <Pin_Name> 为管脚名。寄存器对应描述见表 2 及表 3 :
表 2 : SW_PAD_CTL 寄存器描述 ( 一 )
表 3 : SW_PAD_CTL 寄存器描述 ( 二 )
这里 DDR 相关管脚比较特殊,其寄存器描述有所不同,见表 4 所示:
表 4 : DDR 对应 SW_PAD_CTL 寄存器描述
有些 IO 口需要成组设置,具体各自寄存器设置可查看 i.MX25 手册。
关于各 IO 口具体复用的功能,以及如何设置 SW_MUX_CTL 来决定 IO 口模式,可查看 i.MX25 手册的表 4-18[IMX25RM.pdf] 。
例如我们需要设置某 IO 口为输入或输出,首先通过上面的方法设置完复用功能相关寄存器,接着要设置 GPIO 的相关寄存器。每个 GPIO 都对应有 8 个寄存器设置,在程序中通过结构体封装如下:
typedef struct
{
UINT32 DR; // lqm:Data register
UINT32 GDIR; // lqm:GPIO Direction register. 0:input 1:output
UINT32 PSR; // lqm:Pad sample register. read only
UINT32 ICR1; // lqm:interrupt control register1
UINT32 ICR2; // lqm:interrupt control register2
UINT32 IMR; // lqm:interrupt mask register
UINT32 ISR; // lqm:interrupt state register
UINT32 EDGE_SEL; // lqm:edge select register
} CSP_GPIO_REGS, *PCSP_GPIO_REGS;
其中 DR 表示数据寄存器,也就是 IO 口的高低电平。 GDIR 表示方向寄存器, 0 表示输入, 1 表示输出。 PSR 为只读寄存器,用户通过读取该寄存器值获取 IO 口的状态。 ICR1 , ICR2 为中断控制寄存器,表明了中断触发方式; IMR 为中断屏蔽寄存器, ISR 为中断状态寄存器, EDGE_SEL 为边沿选择寄存器。
当 GPIO 口设置为 GPIO 模式时,若设置为输出,则 DR[n] 返回该寄存器本身设置的值,若设置为输入,则 DR[n] 返回该脚外部输入的信号值。
当 GPIO 设置为非 GPIO 模式时,若设置为输出,则 DR[n] 返回该寄存器本身设置的值,若设置为输入,则 DR[n] 固定返回 0 。
ICR1 描述了 GPIO[0:15] 的中断触发方式,具体见表 5 :
表 5 :中断触发方式
ICR2 描述了 GPIO[16:31] 的中断触发方式,具体见表 6 :
表 6 :中断触发方式
IMR 对应位为 0 时,表示屏蔽对应 GPIO 的中断功能,为 1 时表示使能对应中断功能。 ISR 对应位为 1 时,表示对应 GPIO 中断产生,需要通过软件清零相应位。为 0 时表示中断未产生。
EDGE_SEL 用于设置 GPIO 是否使用边沿触发,若对应 GPIO 口设置为 1 ,表示相应 GPIO 采用上下沿触发,前面的 ICR1 , ICR2 的设置将变得无效。当 EDGE_SEL 的对应位恢复为 0 时, ICR1 , ICR2 的相应位才会变得有效。
不论 GPIO 设置为输入还是输出,在读取 GPIO 对应的电平值时,都读取 PSR 的值,尽量不要读取 DR 的值。而设置 IO 口的电平时通过设置 DR 的值来实现