1,功能介绍
按下Button,LED亮,松开不亮
1.1 相关电路原理图
TC275 lite Kit这块板子有两个可以演示的LED,分别对应P00.5和P00.6这两个芯片管脚,根据电路原理图可以看出当GPIO输出低电平时,电路导通,LED被点亮;除了两个可以操作的LED,还提供了一个Button按钮,对应管脚P00.7,根据电路原理图,当按钮按下时,由于R20电阻的存在,P00.7会得到低电平,GPIO为0,当Button松开时,GPIO为1。
1.2 Port口初始化配置及相关寄存器介绍
芯片的端口引脚可以被配置成通用输出输出(GPIO)引脚,TC275有3个核,通过在core 0的主函数中调用init_GPIOs函数来配置端口引脚。
int core0_main(void)
{
IfxCpu_enableInterrupts();
/* !!WATCHDOG0 AND SAFETY WATCHDOG ARE DISABLED HERE!!
* Enable the watchdogs and service them periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
IfxScuWdt_disableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
/* Wait for CPU sync event */
IfxCpu_emitEvent(&g_cpuSyncEvent);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
init_GPIOs(); /* Initialize port pin for push button and LED */
while(1)
{
control_LED(); /* Check the push button and set the LED accordingly */
}
return (1);
}
在init_GPIOs函数中,把LED1和LED2对应的Port口设置为GPIO的输出,将Button对应的Port口配置成输出
#define LED1 &MODULE_P00,5 /* Port pin for the LED */
#define LED2 &MODULE_P00,6 /* Port pin for the LED */
#define BUTTON &MODULE_P00,7 /* Port pin for the button */
void init_GPIOs(void)
{
/* Setup the port pin connected to the LED to general output mode push-pull. This function can be used
* to initialize any port pin by specifying the port number, pin number and port pin mode.
*/
IfxPort_setPinMode(LED1, IfxPort_Mode_outputPushPullGeneral);
IfxPort_setPinMode(LED2, IfxPort_Mode_outputPushPullGeneral);
/* Setup the port pin connected to the push button to input mode. This function can be used to initialize any
* port to input mode by just specifying the port number as illustrated.
*/
IfxPort_setPinMode(BUTTON, IfxPort_Mode_inputPullUp);
}
芯片的P0端口对应的首地址是0xF003A000u ,地址大小是256byte,TC275共有16组Port口,寄存器地址空间是非完全连续的。
从芯片手册可以看出,P00.5可以配置成GTM、ADC、GPIO等多种功能
关于Port相关的寄存器如下:
typedef volatile struct _Ifx_P
{
Ifx_P_OUT OUT; /**< \brief 0, Port Output Register */
Ifx_P_OMR OMR; /**< \brief 4, Port Output Modification Register */
Ifx_P_ID ID; /**< \brief 8, Identification Register */
unsigned char reserved_C[4]; /**< \brief C, \internal Reserved */
Ifx_P_IOCR0 IOCR0; /**< \brief 10, Port Input/Output Control Register 0 */
Ifx_P_IOCR4 IOCR4; /**< \brief 14, Port Input/Output Control Register 4 */
Ifx_P_IOCR8 IOCR8; /**< \brief 18, Port Input/Output Control Register 8 */
Ifx_P_IOCR12 IOCR12; /**< \brief 1C, Port Input/Output Control Register 12 */
unsigned char reserved_20[4]; /**< \brief 20, \internal Reserved */
Ifx_P_IN IN; /**< \brief 24, Port Input Register */
unsigned char reserved_28[24]; /**< \brief 28, \internal Reserved */
Ifx_P_PDR0 PDR0; /**< \brief 40, Port Pad Driver Mode 0 Register */
Ifx_P_PDR1 PDR1; /**< \brief 44, Port Pad Driver Mode 1 Register */
unsigned char reserved_48[8]; /**< \brief 48, \internal Reserved */
Ifx_P_ESR ESR; /**< \brief 50, Port Emergency Stop Register */
unsigned char reserved_54[12]; /**< \brief 54, \internal Reserved */
Ifx_P_PDISC PDISC; /**< \brief 60, Port Pin Function Decision Control Register */
Ifx_P_PCSR PCSR; /**< \brief 64, Port Pin Controller Select Register */
unsigned char reserved_68[8]; /**< \brief 68, \internal Reserved */
Ifx_P_OMSR0 OMSR0; /**< \brief 70, Port Output Modification Set Register 0 */
Ifx_P_OMSR4 OMSR4; /**< \brief 74, Port Output Modification Set Register 4 */
Ifx_P_OMSR8 OMSR8; /**< \brief 78, Port Output Modification Set Register 8 */
Ifx_P_OMSR12 OMSR12; /**< \brief 7C, Port Output Modification Set Register 12 */
Ifx_P_OMCR0 OMCR0; /**< \brief 80, Port Output Modification Clear Register 0 */
Ifx_P_OMCR4 OMCR4; /**< \brief 84, Port Output Modification Clear Register 4 */
Ifx_P_OMCR8 OMCR8; /**< \brief 88, Port Output Modification Clear Register 8 */
Ifx_P_OMCR12 OMCR12; /**< \brief 8C, Port Output Modification Clear Register 12 */
Ifx_P_OMSR OMSR; /**< \brief 90, Port Output Modification Set Register */
Ifx_P_OMCR OMCR; /**< \brief 94, Port Output Modification Clear Register */
unsigned char reserved_98[8]; /**< \brief 98, \internal Reserved */
Ifx_P_LPCR0 LPCR0; /**< \brief A0, Port LVDS Pad Control Register 0 */
Ifx_P_LPCR1 LPCR1; /**< \brief A4, Port LVDS Pad Control Register 1 */
Ifx_P_LPCR2 LPCR2; /**< \brief A8, Port LVDS Pad Control Register 2 */
unsigned char reserved_A4[76]; /**< \brief AC, \internal Reserved */
Ifx_P_ACCEN1 ACCEN1; /**< \brief F8, Port Access Enable Register 1 */
Ifx_P_ACCEN0 ACCEN0; /**< \brief FC, Port Access Enable Register 0 */
} Ifx_P;
/** \} */
1.3 IfxPort_setPinMode
在初始化过程中,主要是通过IfxPort_setPinMode去配置Port口的相关寄存器实现对应功能
参数说明
-
Ifx_P *port
:指向端口控制模块的指针,详见1.2章节 -
uint8 pinIndex
:引脚索引 (0-15) -
IfxPort_Mode mode
:引脚模式配置
-
IOCR(输入输出控制寄存器(Port Input/Output Control Registers,IOCR))
每个Port口最多有16个引脚,以P0为例,分别是P0.0~P0.15;每个Port口有四个IOCR寄存器,其中
-
IOCR0
:控制引脚 0-3 -
IOCR4
:控制引脚 4-7 -
IOCR8
:控制引脚 8-11 -
IOCR12
:控制引脚 12-15
通过iocrIndex = (pinIndex / 4);来确定使用哪个寄存器,选定IOCR寄存器后,每个Port端口具有4个IOCR寄存器,对应Pin脚关系如下:
-
Pn_IOCR0: Pn.[3:0]
-
Pn_IOCR4: Pn.[7:4]
-
Pn_IOCR8: Pn.[11:8]
-
Pn_IOCR12: Pn.[15:12]
我们以Pn_IOCR0为示例,每个IOCR有4个位域,分别对应4个pin脚,
每个位域有5个bit位,这5个bit位的不同含义如下:
/** \brief Ifx_P input / output mode definition.
*
* \see Ifx_P.IOCR, IfxPort_setPinMode()
*/
typedef enum
{
IfxPort_Mode_inputNoPullDevice = 0, /**< \brief Input, No pull device connected. */
IfxPort_Mode_inputPullDown = 8U, /**< \brief Input, pull-down device connected. */
IfxPort_Mode_inputPullUp = 0x10U, /**< \brief Input, pull-up device connected. */
IfxPort_Mode_outputPushPullGeneral = 0x80U, /**< \brief Push-pull, General-purpose output */
IfxPort_Mode_outputPushPullAlt1 = 0x88U, /**< \brief Push-pull, Alternate output function 1. */
IfxPort_Mode_outputPushPullAlt2 = 0x90U, /**< \brief Push-pull, Alternate output function 2. */
IfxPort_Mode_outputPushPullAlt3 = 0x98U, /**< \brief Push-pull, Alternate output function 3. */
IfxPort_Mode_outputPushPullAlt4 = 0xA0U, /**< \brief Push-pull, Alternate output function 4. */
IfxPort_Mode_outputPushPullAlt5 = 0xA8U, /**< \brief Push-pull, Alternate output function 5. */
IfxPort_Mode_outputPushPullAlt6 = 0xB0U, /**< \brief Push-pull, Alternate output function 6. */
IfxPort_Mode_outputPushPullAlt7 = 0xB8U, /**< \brief Push-pull, Alternate output function 7. */
IfxPort_Mode_outputOpenDrainGeneral = 0xC0U, /**< \brief Open-drain, General-purpose output. */
IfxPort_Mode_outputOpenDrainAlt1 = 0xC8U, /**< \brief Open-drain, Alternate output function 1. */
IfxPort_Mode_outputOpenDrainAlt2 = 0xD0U, /**< \brief Open-drain, Alternate output function 2. */
IfxPort_Mode_outputOpenDrainAlt3 = 0xD8U, /**< \brief Open-drain, Alternate output function 3. */
IfxPort_Mode_outputOpenDrainAlt4 = 0xE0U, /**< \brief Open-drain, Alternate output function 4. */
IfxPort_Mode_outputOpenDrainAlt5 = 0xE8U, /**< \brief Open-drain, Alternate output function 5. */
IfxPort_Mode_outputOpenDrainAlt6 = 0xF0U, /**< \brief Open-drain, Alternate output function 6. */
IfxPort_Mode_outputOpenDrainAlt7 = 0xF8U /**< \brief Open-drain, Alternate output function 7. */
} IfxPort_Mode;
-
PDISC(Pin脚AD功能选择寄存器(Pin Function Decision Control Register,PDISC))
英飞凌芯片的部分Pin脚是支持复用为AD采样的引脚,如果复用为AD采样引脚,就无法再读取引脚的输入,每个Port端口有一个PDISC寄存器,16个位域各控制一个引脚,Pinx的输入控制,0表示数字输入,为普通Pin脚,1表示模拟输入,ADC Pin脚;、。通过port->PDISC.U &= ~(1 << pinIndex);将指定的pinindex的引脚对应的位域写为0,表示为普通的Pin脚
void IfxPort_setPinMode(Ifx_P *port, uint8 pinIndex, IfxPort_Mode mode)
{
volatile Ifx_P_IOCR0 *iocr = &(port->IOCR0);
uint8 iocrIndex = (pinIndex / 4);
uint8 shift = (pinIndex & 0x3U) * 8;
if (port == &MODULE_P40)
{
uint16 passwd = IfxScuWdt_getCpuWatchdogPassword();
IfxScuWdt_clearCpuEndinit(passwd);
port->PDISC.U &= ~(1 << pinIndex);
IfxScuWdt_setCpuEndinit(passwd);
}
__ldmst(&iocr[iocrIndex].U, (0xFFUL << shift), (mode << shift));
}
1.4 IfxPort_setPinState&IfxPort_getPinState
这两个函数一个是用来获取GPIO的状态,一个是用来设置GPIO的状态
void control_LED(void)
{
/* With the routine getPinState() the value of a particular pin can be retrieved. This
* function can be used to retrieve any port state by just specifying the port number
* as illustrated.
*/
if(IfxPort_getPinState(BUTTON) == 0)
{
/* With the routine setPinState() the state of the port can be set to drive either
* LOW or HIGH. This function can be used to retrieve any port state by just
* specifying the port number as illustrated.
*/
IfxPort_setPinState(LED1, IfxPort_State_low);
IfxPort_setPinState(LED2, IfxPort_State_high);
}
else
{
IfxPort_setPinState(LED1, IfxPort_State_high);
IfxPort_setPinState(LED2, IfxPort_State_low);
}
}
-
IfxPort_setPinState
设置Pin脚状态的API主要是通过修改Port输出修改寄存器(Port Output Modification Register,OMR)的值来实现。每个Port有一个OMR寄存器,每个OMR寄存器有32个bit,对应PSx
(x = 0-15,set位)和PCLx(x = 0-15,clear位)两组寄存器,如果要拉高某个Pin脚,就将PSx置1,拉低则将PCLx置1,如果要翻转两个都置1,而其他没有设置位的Pin脚则不会受影响。
#define LED1 &MODULE_P00,5 /* Port pin for the LED */
#define LED2 &MODULE_P00,6 /* Port pin for the LED */
/** \brief Ifx_P output modification modes definition.
*
* \see Ifx_P.OMR, IfxPort_setPinState()
*/
typedef enum
{
IfxPort_State_notChanged = (0 << 16) | (0 << 0), /**< \brief Ifx_P pin is left unchanged. */
IfxPort_State_high = (0 << 16) | (1U << 0), /**< \brief Ifx_P pin is set to high. */
IfxPort_State_low = (1U << 16) | (0 << 0), /**< \brief Ifx_P pin is set to low. */
IfxPort_State_toggled = (1U << 16) | (1U << 0) /**< \brief Ifx_P pin is toggled. */
} IfxPort_State;
IFX_INLINE void IfxPort_setPinState(Ifx_P *port, uint8 pinIndex, IfxPort_State action)
{
port->OMR.U = action << pinIndex;
}
-
IfxPort_getPinState
获取Pin脚状态的API主要是通过Port输入寄存器(Port Input Register,IN)来实现,每个Port口有一个IN寄存器来读取Pin脚的当前状态,无论Pin脚是输入还是输出模式都可以通过该寄存器读取Pin脚的电平状态。如果读取到的是0,则代表当前Pin脚是低电平,如果是1,则代表当前电平是高电平。
#define BUTTON &MODULE_P00,7 /* Port pin for the button */
IFX_INLINE boolean IfxPort_getPinState(Ifx_P *port, uint8 pinIndex)
{
return (__getbit(&port->IN.U, pinIndex) != 0) ? TRUE : FALSE;
}
2,实验分享
通过在Core0的main函数里面一直调用control_LED来监控Button的状态,进而控制LED。
如果当前Button没有按下,则LED2亮起来,如果Button按下了,则当前LED2灭掉,另外一个LED1亮起来。
LED_GPIO