iot-fan文章目录
在沁恒家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,如果速度比较快,通常是需要挂外部上拉的.
 
扩展
- 使用原子指令操作GPIO:https://www.cnblogs.com/iot-fan/p/17254827.html
 

                
            
        
浙公网安备 33010602011771号