前面两篇文章,把L051基本功能都测试过了,确实感觉到ST的CubeMX工具真是好用,对应换芯片的应用来说,着实方便,底层库封装好,上层应用程序基本都一样~~ 今天我们就来吧I2C设备添加一下,今天正好借这个机会,把I2C的代码优化一下。 1、CubeMX IO口的设置 模拟I2C的IO口都设置为开漏输出,因为电路图上有外部上拉。 初始化的时候,2个SDA和SCL都得拉高。所以设置如下:
2、做一个us延时函数 在HAL库中,只有ms的延时函数HAL_Delay,没有us的延时函数,今天用了网上一个延时函数,发现有问题,搞得整个时钟出了问题,郁闷,折腾了一下午。 时间浪费了,通讯模块那边因为这个时钟设置也出了点问题,一直返回复位信息,用了怎么多年的芯片还第一次遇到,Enocean 的TCM310模块,主要这个技术支持也不太好找。 = =! 还是快速找一个us函数,不是那么精确也可以,直接用空语句测试,后面已经经过测试,下面这个函数做的us延时可以正常移植以前的I2C程序。
void delay_us(uint32_t Delay)
{
uint32_t cnt = Delay * 8;
uint32_t i = 0;
for(i = 0; i < cnt; i++)__NOP();
}
3、移植I2C代码 3.1 SHT21温湿度传感器 代码移植没什么问题, i2c.c:
#include "i2c.h"
void i2c_init(void) {
}
void i2c_start(void) {
sda_high();
delay_us(10);
scl_high();
delay_us(10);
sda_low();
delay_us(10);
scl_low();
delay_us(10);
}
void i2c_stop(void) {
sda_low();
delay_us(10);
scl_low();
delay_us(10);
scl_high();
delay_us(10);
sda_high();
delay_us(10);
}
uint8 i2c_write(uint8 u8Data)
{
uint8 u8Bit;
uint8 u8AckBit;
u8Bit = 0x80;
while(u8Bit) {
if(u8Data&u8Bit) {
sda_high();
delay_us(20);
}
else{
sda_low();
delay_us(20);
}
scl_high();
delay_us(30);
u8Bit >>= 1;
scl_low();
delay_us(30);
}
sda_high();
delay_us(10);
scl_high();
delay_us(10);
u8AckBit= sda_read();
delay_us(10);
scl_low();
delay_us(10);
return u8AckBit;
}
uint8 i2c_read(uint8 u8Ack)
{
uint8 u8Bit;
uint8 u8Data;
u8Bit = 0x80;
u8Data = 0;
while(u8Bit){
scl_high();
delay_us(20);
u8Bit >>= 1;
u8Data <<= 1;
u8Data |= sda_read();
delay_us(20);
scl_low();
delay_us(50);
}
if(u8Ack==I2C_ACK) {
sda_low();
delay_us(20);
}
else {
sda_high();
delay_us(20);
}
scl_high();
delay_us(20);
scl_low();
delay_us(20);
sda_high();
delay_us(20);
return u8Data;
}
i2c.h:
#ifndef _I2C_H_INCLUDED
#define _I2C_H_INCLUDED
#include "main.h"
#include "Datadef.h"
#define sda_high() HAL_GPIO_WritePin(sht_sda_GPIO_Port,sht_sda_Pin,GPIO_PIN_SET);
#define sda_low() HAL_GPIO_WritePin(sht_sda_GPIO_Port,sht_sda_Pin,GPIO_PIN_RESET);
#define sda_read() (HAL_GPIO_ReadPin(sht_sda_GPIO_Port,sht_sda_Pin) == GPIO_PIN_SET);
#define scl_high() HAL_GPIO_WritePin(sht_scl_GPIO_Port,sht_scl_Pin,GPIO_PIN_SET);
#define scl_low() HAL_GPIO_WritePin(sht_scl_GPIO_Port,sht_scl_Pin,GPIO_PIN_RESET);
#define DONOTHING() {;}
#define I2C_WRITE 0
#define I2C_READ 1
#define I2C_ACK 0
#define I2C_NACK 1
void i2c_init(void);
void i2c_start(void);
void i2c_stop(void);
uint8 i2c_write(uint8 u8Data);
uint8 i2c_read(uint8 u8Ack);
#endif
SHT21部分的驱动就不用怎么修改了,基本上直接拿过来,把ms延时函数替换一下,就直接用,这里就不贴出来
测试结果: 板载的HTU21D,实际测试下来,一直会比空气问题高一点,这个问题,我倒是有点头疼,虽然做过分割,不铺铜等一些处理,还是不尽如人意。
3.1 欧姆龙远距离红外测温D6T系列 其实有了上面的成功案例,这个也不是什么问题,还是老样子,定义好IO口,写好驱动逻辑,主要是因为板子上接口还没焊接,明天再试试,再接着补充一下。
完成了这几个工作,下面一篇文章应该会学习L051 的 flash读写操作,因为项目中总得有一些设置需要掉线不丢失的,以前F103都是直接保存在内部flash中,L051的flash读写操作是怎么实现的,明天我们拭目以待!
|