本文以Nucleo板做主控电路,通过模拟I2C接收BH1750的数据,然后用Cube配置的硬件I2C发送到OLED上显示出来。
首先用CubeMX搭建工程
1、
硬件I2C选择使用I2C2,
模拟I2C用PB5做SDA、PB6做SCL。
2、
硬件I2C配置,将速度模式选为Fast Mode,频率选为最高400KHz,其它都可以保持默认。
模拟I2C是配置GPIO,PB5、6配置是一样的,IO需要配置为开漏输出。除了PB5、6其它的IO不用理会。
然后编写代码
3、oled.c文件
这里硬件I2C,是用HAL_I2C_Mem_Write函数写入I2C。
hi2c2:是你自己使用的具体哪个I2C,一般会自动生成,在i2c.c中的初始定义中可以找到;
OLED_SLAVE_ADDRESS:设备的地址 即oled屏幕的地址,具体看厂家的说明,在给的驱动代码中应该是可以找到的;
OLED_dat_ADDRESS:设备内部地址,可以参考原驱动代码。这个函数这里是写入寄存器;
I2C_MEMADD_SIZE_8BIT:设备内部地址编址方式,根据设备决定是8位编址或者16位编址方式; 这个参数的填写有两种 I2C_MEMADD_SIZE_8BIT I2C_MEMADD_SIZE_16BIT,可以在库代码中找到具体定义;
dat:写入的数据;
1:写入的字节大小;
I2C2_TIMEOUT_MAX:超时时间。
- /*
- * 函数功能: 通过硬件I2C向OLED写入命令或数据
- * 输入参数: dat 数据,cmd 命令
- * 返 回 值: 无
- * 说 明:无
- */
- void OLED_WR_Byte(unsigned char dat,unsigned char cmd)
- {
- if(cmd) {HAL_I2C_Mem_Write(&hi2c2,OLED_SLAVE_ADDRESS,OLED_dat_ADDRESS,I2C_MEMADD_SIZE_8BIT,&dat,1,I2C2_TIMEOUT_MAX);}
- else {HAL_I2C_Mem_Write(&hi2c2,OLED_SLAVE_ADDRESS,OLED_cmd_ADDRESS,I2C_MEMADD_SIZE_8BIT,&dat,1,I2C2_TIMEOUT_MAX);}
- }
复制代码 4、i2c.c文件
模拟I2C的代码我是写在i2c.c文件的最后面,具体代码我这里就不贴出来了。
- #define I2C_SCL_HIGH() HAL_GPIO_WritePin(I2Cx_SCL_GPIO_Port,I2Cx_SCL_Pin,GPIO_PIN_SET) // 输出高电平
- #define I2C_SCL_LOW() HAL_GPIO_WritePin(I2Cx_SCL_GPIO_Port,I2Cx_SCL_Pin,GPIO_PIN_RESET)// 输出低电平
- #define I2C_SDA_HIGH() HAL_GPIO_WritePin(I2Cx_SDA_GPIO_Port,I2Cx_SDA_Pin,GPIO_PIN_SET) // 输出高电平
- #define I2C_SDA_LOW() HAL_GPIO_WritePin(I2Cx_SDA_GPIO_Port,I2Cx_SDA_Pin,GPIO_PIN_RESET)// 输出低电平
- #define I2C_SDA_READ() HAL_GPIO_ReadPin(I2Cx_SDA_GPIO_Port,I2Cx_SDA_Pin)
复制代码
最后放张实物图
|
能再说一点吗,求教STM32的GPIO是变量,是怎么让I2C模拟更好的呢?
你想想如果需要多通道I2C,而且任意脚位。。。那么你是不是每次都要搞一套I2C的命名,然后各自宏定义,但是,GPIO是变量,变量是啥意思,就是可以赋值,就可以把GPIO的脚位赋值给变量,那么只需要实现一套I2C,然后切换,或者多通道的时候,只需要赋值不同的GPIO不就可以啦!!!当然了,这还涉及到GPIO控制寄存器,是一样的。。。
评分
查看全部评分