硬件IIC的重映射使用问题
沁恒的蓝牙系列芯片,有映射硬件模块去其他引脚的功能,可以配置各芯片的功能引脚重映射寄存器(R16_PIN_ALTERNATE),或者使用函数GPIOPinRemap函数进行配置。
比如说想要配置串口2重映射到PB22、23,可以调用如下代码↓
GPIOPinRemap(ENABLE, RB_PIN_UART2); //重映射串口2到PB22、23 GPIOB_SetBits(GPIO_Pin_23); //串口2GPIO初始化,TXD2_在配置推挽输出前先置位 GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeIN_PU); GPIOB_ModeCfg(GPIO_Pin_23, GPIO_ModeOut_PP_5mA); UART2_DefInit(); //串口2初始化
以下是常用重映射的一些注意点。
①实际使用哪个引脚就初始化哪个引脚。重映射之后只初始化默认引脚,再从重映射引脚接杜邦线那就调不通。
②重映射过去,使用的引脚可能有原本有特殊功能,比如说串口2的默认引脚在PA6、7,将它重映射到PB22、23时,注意PB23多用作手动复位脚,需要在ISP工具中取消“使能RST作为手工复位输入引脚”的框选,否则串口2发送数据拉低电平,就会复位芯片。PB22作为下载配置脚可以不用改,因为它只在上电的时候会用作boot脚,进了程序之后就参考普通串口配置GPIO即可。
硬件IIC的重映射,如果使用与默认引脚PB12、13一样的代码,会出问题↓
测试现象:重映射过后,用杜邦线将PB12、13接GND,上电复位/软件后,会卡在busy判忙。如果给原先的PB12、13上电初始化加上内部上拉,不会有卡在判忙的情况,即使是运行中拉低PB12、13也不会有影响。
其实手册中有作说明↓
大概意思是说,复位后会立即进行默认引脚PB12、13上的busy检测,即使没有使能硬件IIC,也会进行检测。由于复位时PB12、13引脚的电平状态是不确定的,若判断为busy,会导致接下来的IIC读写卡在判忙。
解决方法有两个。方法①在I2C_Init()函数中增加软件复位相关代码来清busy标志。注意PB20、21要配置为上拉(GPIO_ModeIN_PU)。最新EVT中已经在I2C_Init()函数中增加了复位相关代码。代码如下↓
GPIOB_ModeCfg(GPIO_Pin_20 | GPIO_Pin_21, GPIO_ModeIN_PU); //配置重映射之后的引脚 对应使用软件复位的方式 GPIOPinRemap(ENABLE, RB_PIN_I2C); //重映射到PB20、21 I2C_Init(I2C_Mode_I2C, 400000, I2C_DutyCycle_16_9, I2C_Ack_Enable, I2C_AckAddr_7bit, HOST_NO_ADDR);
方法②在重映射之后,用四行代码拉GPIO模拟一个停止标志,清除一下busy的硬件标志位(这里用I2C_GenerateSTOP(ENABLE)由硬件产生一个停止信号测试不通,模拟一个停止位能调通)。原引脚对于busy的影响只在重映射函数之前。注意PB20、21要配置为推挽(GPIO_ModeOut_PP_5mA)。代码如下↓
GPIOB_ModeCfg(GPIO_Pin_20 | GPIO_Pin_21,GPIO_ModeOut_PP_5mA); GPIOPinRemap(ENABLE,RB_PIN_I2C); //重映射PB20、21 GPIOB_SetBits(GPIO_Pin_21); //给予一个停止标志,清BUSY GPIOB_ResetBits(GPIO_Pin_20); DelayMs(10); GPIOB_SetBits(GPIO_Pin_20); I2C_Init(I2C_Mode_I2C, 400000, I2C_DutyCycle_16_9, I2C_Ack_Enable, I2C_AckAddr_7bit, HOST_NO_ADDR);