在沁恆家32位機(CH56x,CH57X,CH58X)中,我們發現GPIO似乎並沒有一個單獨的輸出模式叫開漏(OD,open-drian)
在CH57x,CH58x只有下面幾種模式:
/**
* @brief Configuration GPIO Mode
*/
typedef enum{
GPIO_ModeIN_Floating, //浮空輸入
GPIO_ModeIN_PU, //上拉輸入
GPIO_ModeIN_PD, //下拉輸入
GPIO_ModeOut_PP_5mA, //推挽輸出最大5mA
GPIO_ModeOut_PP_20mA, //推挽輸出最大20mA
}GPIOModeTypeDef;
那么怎么實現開漏呢?
開漏的特性:
- 輸出高的時候: 懸空/ 弱上拉
- 輸出低的時候: 強吸入電流
沁恆的的GPIO模式配置函數:
這里我們只拿GPIOA來做說明
/*******************************************************************************
* Function Name : GPIOA_ModeCfg
* Description : GPIOA端口引腳模式配置
* Input : pin:
PA0-PA15
GPIO_Pin_0 - GPIO_Pin_15
mode:
GPIO_ModeIN_Floating - 浮空輸入
GPIO_ModeIN_PU - 上拉輸入
GPIO_ModeIN_PD - 下拉輸入
GPIO_ModeOut_PP_5mA - 推挽輸出最大5mA
GPIO_ModeOut_PP_20mA - 推挽輸出最大20mA
* Return : None
*******************************************************************************/
void GPIOA_ModeCfg( uint32_t pin, GPIOModeTypeDef mode ) {
switch(mode){
case GPIO_ModeIN_Floating:
R32_PA_PD_DRV &= ~pin;
R32_PA_PU &= ~pin;
R32_PA_DIR &= ~pin;
break;
case GPIO_ModeIN_PU:
R32_PA_PD_DRV &= ~pin;
R32_PA_PU |= pin;
R32_PA_DIR &= ~pin;
break;
case GPIO_ModeIN_PD:
R32_PA_PD_DRV |= pin;
R32_PA_PU &= ~pin;
R32_PA_DIR &= ~pin;
break;
case GPIO_ModeOut_PP_5mA:
R32_PA_PD_DRV &= ~pin;
R32_PA_DIR |= pin;
break;
case GPIO_ModeOut_PP_20mA:
R32_PA_PD_DRV |= pin;
R32_PA_DIR |= pin;
break;
default:
break;
}
}
所以,我們只需要按照下面的方式即可實現,開漏
下面使用PB5/PB4 模擬iic 的初始化代碼
初始化:
把要設置為開漏輸出的IO, 初始化為輸入模式,然后輸出設置為低電平就行了,
#define IIC_CKL_PIN GPIO_Pin_5
#define IIC_SDA_PIN GPIO_Pin_4
#define ch57x_i2c_clk_init() { GPIOB_ModeCfg(IIC_CKL_PIN,GPIO_ModeIN_PU );\
GPIOB_ResetBits(IIC_CKL_PIN);}
#define ch57x_i2c_sda_init() { GPIOB_ModeCfg(IIC_SDA_PIN,GPIO_ModeIN_PU );\
GPIOB_ResetBits(IIC_SDA_PIN);}
使用:
通過設置IO的方向寄存器,來實現開漏的高低電平控制
#define GPIOB_PinOutput(pin) (R32_PB_DIR |= pin)
#define GPIOB_PinInput(pin) (R32_PB_DIR &= ~pin)
#define ch57x_i2c_clk_set() { GPIOB_PinInput(IIC_CKL_PIN); }
#define ch57x_i2c_clk_clr() { GPIOB_PinOutput(IIC_CKL_PIN); }
#define ch57x_i2c_clk_get() ( GPIOB_ReadPortPin(IIC_CKL_PIN) )
#define ch57x_i2c_sda_set() { GPIOB_PinInput(IIC_SDA_PIN); }
#define ch57x_i2c_sda_clr() { GPIOB_PinOutput(IIC_SDA_PIN); }
#define ch57x_i2c_sda_get() ( GPIOB_ReadPortPin(IIC_SDA_PIN))
注意事項:
- 除了耐受5v輸入的IO外,其他IO處於輸入模式時,不能高於芯片的供電電壓,所以如果對接5v系統的iic,盡量用耐受5v輸入的IO.
- CH57x,CH58x 系列芯片的內部上拉是50K,如果速度比較快,通常是需要掛外部上拉的.