最近在调iic接口的陀螺仪等九轴模块,卖家给的stm32程序死活调试不通过,卖家还不承认程序有问题。用原子哥的程序也不行。没办法,自己写一个吧,增加各种的出错信息判断,方便调试。
出于要写就写一个好的的想法,给程序提出了如下要求:1、能够选择100k的速率或400k;2、能够处理多主机下的时钟信号同步与仲裁的情况;3、能够识别设备拉低SCL的情况,适当减低主机时钟频率适应;4、能够发现并打印各种出错信息,方便iic设备的调试。
其中第4点是最主要的,因为我写这个程序就是为了调试我的九轴模块。根据IIC协议中文版及参考原子等人的程序,我在alientek 的miniSTM32开发板上成功读写了板上的eeprom,也成功读取了
adxl345加速传感器的数据。目测数据能够随着重力方向变化,故初步判断应该是成功的。
/////////////////////////////////////////
介绍程序中2个重要的函数:
1、int iic_dev_read (u8 dev, u8 addr, u8* data); 该函数读取iic总线上dev地址的iic设备,将设备addr地址上寄存器数据读到data,返回错误代码。
2、int iic_dev_write(u8 dev, u8 addr, u8 data); 该函数将数据data写入iic总线上的dev地址的iic设备,数据写入地址为设备上的addr地址,返回错误代码。
上述2个函数能够识别的错误有:
1、err_bus_busy:总线被外部设备拉低,暂时不可用。包括SDA和SCL被拉低2种情况。
2、err_arb_fail:多主机竞争的情况,竞争失败,放弃控制权。(未测试)
3、err_dev_fail:设备没有响应。可能是总线上没有该设备,或是设备处于忙碌状态。
4、err_tar_fail:理论上可能发生的设备拒绝对相应的寄存器的读写操作。
5、总线被外部主机或设备拉低超时。按照iic规范,scl总线可以不限时间被拉低。考虑到我们是模拟iic,为了避免死循环而加入此项功能。
/////////////////////////////////////////
// 与移植有关的配置
// 使用原子的程序即可
extern void delay_us(u32 nus);
#define iic_delay(t_us) delay_us(t_us)
// 将相应端口设置为开漏输出。这个跟原子的程序不太一样,不用频繁的改变输入输出状态,而且端口电平可以被外部改变,适应总线同步与裁决等情况
extern void hw_iic_init(void);
// 这些端口的使用跟板上的情况一致
#define SDA Cin(11)
#define SCL PCin(12)
#define SCL_L() Cout(12)=0
#define SCL_H() Cout(12)=1
#define SDA_L() Cout(11)=0
#define SDA_H() Cout(11)=1
// 调试与优化相关配置,如果没有后面的printf(A);则程序不会打印出错信息,但依然会返回错误代码。
#define IIC_DEBUG(A) printf(A)
// SCL时钟频率 fscl: 100kHz or 400kHz
#define F_SCL (100)
// 释放SCL并查询的次数,如果SCL保持被外部拉低,则退出,并设置_IIC_ERROR_COUDE为:IIC_TIME_OUT
#define IIC_TIME_OUT_COUNT (255)
// 释放SCL并查询的次数,如果SCL保持被外部拉低,则DEBUG提示。
/*delay for voltage raising time*/
#define IIC_RAISING_COUNT (10)
|