ERP与MES系统源代码:WPF开发AGV上位机执行系统,集成SQL数据库技术、多线程技术及应...
2026/3/20 1:15:47
最近在调一个IIC陀螺仪,发什么命令都没反应。折腾半天才发现——GPIO引脚根本没动!
原来是移植了正点原子的库,里面的IO操作是F103的位带操作,和F401不兼容。
这个函数用来验证SCL和SDA能不能正常拉高/拉低。
voidGPIO_Test(void){printf("Starting GPIO test...\r\n");// 测试SCL引脚(PA8)printf("Testing SCL (PA8)...\r\n");IIC_SCL(1);delay_ms(100);printf("SCL = 1, PA8_IDR = %d\r\n",HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8));IIC_SCL(0);delay_ms(100);printf("SCL = 0, PA8_IDR = %d\r\n",HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8));// 测试SDA引脚(PC9)printf("Testing SDA (PC9)...\r\n");SDA_OUT();IIC_SDA(1);delay_ms(100);printf("SDA = 1 (output), PC9_IDR = %d\r\n",HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_9));IIC_SDA(0);delay_ms(100);printf("SDA = 0 (output), PC9_IDR = %d\r\n",HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_9));printf("GPIO test completed.\r\n");}正常应该这样:
Starting GPIO test... Testing SCL (PA8)... SCL = 1, PA8_IDR = 1 SCL = 0, PA8_IDR = 0 ← 写0能读到0,说明拉低了 Testing SDA (PC9)... SDA = 1 (output), PC9_IDR = 1 SDA = 0 (output), PC9_IDR = 0我当时的情况:
SCL = 0, PA8_IDR = 1 ← 写0还是读到1,根本没拉低! SDA = 0 (output), PC9_IDR = 1GPIO没问题后,用这个扫描总线上的设备。
voidI2C_Scan(void){u8 i,ack;printf("Starting I2C scan...\r\n");for(i=0;i<128;i++){IIC_Start();IIC_Send_Byte((i<<1)&0xFE);// 写地址ack=IIC_Wait_Ack();IIC_Stop();if(ack==0){printf("Found device at 0x%02X (7-bit: 0x%02X)\r\n",(i<<1),i);}delay_ms(1);}printf("I2C scan completed.\r\n");}输出示例:
Starting I2C scan... Found device at 0xD0 (7-bit: 0x68) ← 找到陀螺仪了,地址0x68 I2C scan completed.正点原子的库里有这么一段:
#defineBITBAND(addr,bitnum)((addr&0xF0000000)+0x2000000+((addr&0xFFFFF)<<5)+(bitnum<<2))#defineGPIOA_ODR_Addr(GPIOA_BASE+12)// 0x4001080C#defineGPIOA_IDR_Addr(GPIOA_BASE+8)// 0x40010808...这些地址是F103的!F401的寄存器布局不一样,直接用会导致IO操作失效。
F103的ODR偏移是+12
F103的IDR偏移是+8
F401的ODR偏移是+20
F401的IDR偏移是+16
Cortex-M4编程手册 PM0214 第3.7节 Bit-Banding
#defineBITBAND(addr,bitnum)((addr&0xF0000000)+0x2000000+((addr&0xFFFFF)<<5)+(bitnum<<2))// F401的GPIO寄存器偏移(参考RM0368手册)#defineGPIOA_ODR_Addr(GPIOA_BASE+20)// 0x40020014 ← F401的ODR偏移是+20#defineGPIOA_IDR_Addr(GPIOA_BASE+16)// 0x40020010 ← F401的IDR偏移是+16...// 别用位带了,直接HAL#defineIIC_SCL(n)HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,n)#defineIIC_SDA(n)HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,n)// 读取SDA切换方向#defineSDA_IN(){GPIOC->MODER&=~(3<<(9*2));GPIOC->MODER|=0<<(9*2);}#defineSDA_OUT(){GPIOC->MODER&=~(3<<(9*2));GPIOC->MODER|=1<<(9*2);}#defineREAD_SDAHAL_GPIO_ReadPin(GPIOC,GPIO_PIN_9)设备没反应? ↓ 跑 GPIO_Test() ↓ 写1读1,写0读0? ──否──→ 检查IO配置/上拉电阻/代码兼容性 ↓ 是 跑 I2C_Scan() ↓ 找到设备地址? ────否──→ 检查接线/供电/设备是否损坏 ↓ 是 开始正常读写调试