stm32 IIC软件移植过程 Delay_us IO端口方向配置 逻辑分析仪测IIC时序

在移植软件IIC的过程中,遇到了一些问题,这是我的解决方法
1.IIC有delay要求,hal库只能提供ms级,使用systick配置us级配置相关原文链接:https://blog.csdn.net/qq_47713364/article/details/119917176
2.IIC协议在读取数据时或者产生应答时对管脚IO读取,因此不能单一的设置为输出,有时要配置成输入,使用寄存器配置SDA的输入和输出
原文链接:https://www.cnblogs.com/Montauk/p/5850344.html
/* 寄存器配置 */
#define IIC_SDA_IN     {GPIOB->CRL&=0XFFF0FFFF;GPIOB->CRL|=(u32)8<<16;}//0所在的地方表示第几个寄存器(0-7)此时是PB4,8表示0x8就是1000,把CNF配置为10,MODE配置为00,左移16是PB4
#define IIC_SDA_OUT    {GPIOB->CRL&=0XFFF0FFFF;GPIOB->CRL|=(u32)7<<16;}//0所在的地方表示第几个寄存器(0-7)此时是PB4,3表示0x3就是0010,把CNF配置为00,MODE配置为10,左移16是PB4
3.在使用逻辑分析仪分析IIC时序时,由于IIC是开漏模式,单独测试IIC的管脚PB3,4,无法读取到电平,在接入屏幕后在测试方可     参考文章:https://blog.csdn.net/as480133937/article/details/105366932

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于STM32实现模拟I2C软件配置的代码: ```c #include "stm32f10x.h" #define SDA_OUT() GPIOB->CRL &= 0X0FFFFFFF;GPIOB->CRL |= 0x30000000//PB6输出模式 #define SDA_IN() GPIOB->CRL &= 0X0FFFFFFF;GPIOB->CRL |= 0x80000000//PB6输入模式 #define IIC_SCL PBout(7) //SCL #define IIC_SDA PBout(6) //SDA #define READ_SDA PBin(6) //SDA IN void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); IIC_SCL = 1; IIC_SDA = 1; } void IIC_Start(void) { SDA_OUT(); IIC_SDA = 1; IIC_SCL = 1; delay_us(4); IIC_SDA = 0; delay_us(4); IIC_SCL = 0; } void IIC_Stop(void) { SDA_OUT(); IIC_SCL = 0; IIC_SDA = 0; delay_us(4); IIC_SCL = 1; IIC_SDA = 1; delay_us(4); } u8 IIC_Wait_Ack(void) { u8 ucErrTime = 0; SDA_IN(); IIC_SDA = 1; delay_us(1); IIC_SCL = 1; delay_us(1); while (READ_SDA) { ucErrTime++; if (ucErrTime > 250) { IIC_Stop(); return 1; } } IIC_SCL = 0; return 0; } void IIC_Ack(void) { IIC_SCL = 0; SDA_OUT(); IIC_SDA = 0; delay_us(2); IIC_SCL = 1; delay_us(2); IIC_SCL = 0; } void IIC_NAck(void) { IIC_SCL = 0; SDA_OUT(); IIC_SDA = 1; delay_us(2); IIC_SCL = 1; delay_us(2); IIC_SCL = 0; } void IIC_Send_Byte(u8 txd) { u8 t; SDA_OUT(); IIC_SCL = 0; for (t = 0; t < 8; t++) { if ((txd & 0x80) >> 7) IIC_SDA = 1; else IIC_SDA = 0; txd <<= 1; delay_us(2); IIC_SCL = 1; delay_us(2); IIC_SCL = 0; delay_us(2); } } u8 IIC_Read_Byte(unsigned char ack) { unsigned char i, receive = 0; SDA_IN(); for (i = 0; i < 8; i++) { IIC_SCL = 0; delay_us(2); IIC_SCL = 1; receive <<= 1; if (READ_SDA) receive++; delay_us(1); } if (!ack) IIC_NAck(); else IIC_Ack(); return receive; } u8 single_write(u8 addr, u8 reg, u8 data) { u8 res; IIC_Start(); IIC_Send_Byte(addr << 1 | 0); res = IIC_Wait_Ack(); IIC_Send_Byte(reg); res |= IIC_Wait_Ack(); IIC_Send_Byte(data); res |= IIC_Wait_Ack(); IIC_Stop(); return res; } u8 single_read(u8 addr, u8 reg, u8* data) { u8 res; IIC_Start(); IIC_Send_Byte(addr << 1 | 0); res = IIC_Wait_Ack(); IIC_Send_Byte(reg); res |= IIC_Wait_Ack(); IIC_Start(); IIC_Send_Byte(addr << 1 | 1); res |= IIC_Wait_Ack(); *data = IIC_Read_Byte(0); IIC_Stop(); return res; } ``` 注:以上代码仅供参考,具体实现要根据自己的硬件和需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值