IIC好像也不是很难|AD5175初次体验
目录
经过了近两个礼拜的折磨,终于用STM32驯服AD5175了,从一开始调整硬件,修改软件,反复阅读数据手册,最后再到硬件修改。回过头看会觉得简单,但是每一个被忽略的小细节就决定了最后的成败。分享一下这段经历,给自己一个总结,也给大家提个醒。(中间出现的原理图有错误,将在最后放能用的电路图)
IIC简介
IIC(Inter-Integrated Circuit),集成电路总线,常见的称呼还有I2C,是飞利浦公司推出的一种半双工同步通信方式。IIC串行总线的信号线有数据线SDA和时钟线SCL,一般两根线都接有上拉电阻,以确保在空闲时刻都为高电平。IIC设备分为主机和从机,而每个设备都有其唯一的地址,这些设备连接在同一IIC总线上,由主机发出广播,控制相应地址的从机。
IIC常见的几种信号
起始信号
IIC从机并不是一直在等着数据,只有当起始信号出现后,从机才会知道,主机要开始叫人干活了。IIC协议中对起始信号的定义是这样的:当时钟线(SCL)为高电平时,数据线(SDA)从高电平向低电平跳变。代码示例
:
// 产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT();
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;
delay_us(4);
IIC_SCL=0;
}
结束信号
就像我们聊天结束的时候说拜拜,而从机知道主机结束本次数据传输就是通过结束信号表达的:当时钟线(SCL)为高电平时,数据线(SDA)从低电平向高电平跳变。代码示例
:
// 产生IIC结束信号
void IIC_Stop(void)
{
SDA_OUT();
IIC_SDA=0;
delay_us(4);
IIC_SCL=1;
delay_us(4);
IIC_SDA=1;
delay_us(4);
}
应答信号
主机每发送一个字节(8bit),从机就会反馈一个应答信号。一般的,把数据线(SDA)拉高,主机放开对数据线的控制,如果是有效应答位(ACK),从机会把数据线(SDA)电平拉低。若数据线(SDA)为高电平,称为非应答位(NACK)。代码示例
:
//对于从机而言
//产生ACK信号
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//产生NACK信号
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//对于主机而言
//等待应答信号
u8 IIC_Wait_Ack(void)
{
u8 ErTime=0;
SDA_IN();
IIC_SCL=1;
delay_us(1);
while(READ_SDA)
{
ErTime++;
if(ErTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;
return 0;
}
发送一个字节
代码示例
:
//发送一个字节
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;
for(t=0;t<8;t++)
{
IIC_SDA=(txd&0x80)>>7;
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;
}
电路原理图
AD5175的数据手册中没有给出具体的参考设计电路,但是有各个引脚的说明
PIN1:单电源模式下为2.7-5.5V;双电源模式下为正负2.5V到正负2.75V。
PIN2和PIN3是电阻的接头,没有正负极之分,但要注意每个引脚电压需要在VSS和VDD之间。
PIN4:电源负极,单电源时候接地。
PIN5:外部电容,对地接1uF电容
PIN6:地
PIN7:软件复位,低电平有效
PIN8:数据线
PIN9:时钟线
PIN10:地址位(详见数据手册)
根据数据手册可以很容易设计出电路原理图,如下图:
很容易看出,数据线和时钟线的地方没有接上拉电阻,后期补上了两个10k的上拉电阻(挖坑了)
莽改AD5175电阻值
从数据手册的写操作可以看出,只需要发送3字节数据就能写入一次数据(具体数据格式见数据手册)
一开始写的时候就很莽,看到时序图,就去找对应的操作怎么修改RDAC的值(也不是说不行,就是少了一步)。代码示例
:
//修改RDAC
unsigned char AD5175_WriteRDAC(void)
{
IIC_Start();
IIC_Send_Byte(0x58);
if(IIC_Wait_Ack())
return 1;
IIC_Send_Byte(0x05);
if(IIC_Wait_Ack())
return 2;
IIC_Send_Byte(0x00);
if(IIC_Wait_Ack())
return 3;
IIC_Stop();
}
写完这个,RDAC的值怎么都不会发生改变,电阻值也不会跟着变,当时就是开始查硬件的问题,也是在这个时候发现了少了上拉电阻;但是接了上拉电阻之后也不会发生任何改变。然后就开始用示波器去观察时钟信号和数据信号:
按照时钟周期一个一个的去对数据信号,改变数据信号,看到的波形也能发生变化;就开始纳闷数据发送正确,会不会还是硬件问题,甚至还怀疑是不是A和W引脚有正负极之分,在PCB上割线、飞线,调试过程还弄断了三块AD5175的芯片引脚
IIC调试器
师兄看不下去了,掏出了他压箱底的IIC调试器给我用。
通过上位机软件发送IIC指令,后面还是用杜邦线和飞线接到AD5175上。这个上位机可以扫描从机地址,奇怪的是,怎么都扫不到,但是发送的数据波形还是正确的,就没有理会这个小bug。虽然波形正确,可怎么都不会改变AD5175的阻值;开始怀疑是不是这个模块坏了,用一个之前调成功的PCF8563模块和这个调试器接起来,发现可以读取到从机地址,但仍无法接收到正常反馈数据,遂止。
STM32的HAL库函数
既然调试器不会用,还害怕自己写的模拟IIC程序有问题,那就用HAL库,也是在这个阶段,在一次逛论坛的时候,看到有大佬说,有些是有写保护的。果然,数据手册中一查,WRITE PROTECTION几个大字赫然眼前,看到这里都想抽自己了,但也庆幸终于找到解脱之道了。
所以,在写RDAC之前,需要先把RDAC的写保护关闭(默认开启),在控制寄存器(control register)中把C1置为高电平即可关闭RDAC的写保护。再写入正常数据前,先写入0x1c和0x02。代码示例
:
//主函数
while (1)
{
unsigned char temp[4]= {0x1c,0x02,0x05,0x00};
/* USER CODE END WHILE */
HAL_I2C_Master_Transmit(&hi2c2, 88 ,temp , I2C_MEMADD_SIZE_8BIT, 0xfff);
HAL_I2C_Master_Transmit(&hi2c2, 88 ,temp+1 , I2C_MEMADD_SIZE_8BIT, 0xfff);
HAL_Delay(20);
HAL_I2C_Master_Transmit(&hi2c2, 88 ,temp+2 , I2C_MEMADD_SIZE_8BIT, 0xfff);
HAL_I2C_Master_Transmit(&hi2c2, 88 ,temp+3 , I2C_MEMADD_SIZE_8BIT, 0xfff);
HAL_Delay(20);
/* USER CODE BEGIN 3 */
}
但即使是到这个份上,AD5175的阻值还纹丝不动,那就只能怀疑主机是不是有问题,即使单片机最小系统之前一直用的好好的,但也有可能SMT的时候BOM配错了什么的;然后又花了半天检查了PCBA的BOM,看也看不出个名堂,那还不如用开发板呢。这时候前几天单独做的AD5175的转接板到了,那就把他接到开发板上,再用上述代码操作。
当然,结果还是不尽人意,既然确保了上位机硬件、软件没问题。从机的通讯也基本可以确定没问题,那问题还是可能出现在从机的硬件上。
一次偶然的相遇
虽然觉得问题出现在从机硬件上,可就几个电容电阻的怎么也看不出问题。在一次偶然的搜索中,刷到一篇卓大大写的关于AD5272的调试[^1]
链接: AD5272数字变阻器
看到他用的上拉电阻是2k,抱着无路可走的态度,也把上拉改小了(原来10k),这一改不要紧,AD5175的阻值开始可以控制!原来门道都在这啊!
上拉电阻的选择
作者在一开始在上拉电阻的选择时,就在网上随便搜了个电路,想着上拉电阻只要有就行的想法,照着安装了个10k的上拉电阻。下面是在网上搜集的上拉电阻选择的一些注意事项,如有错误,敬请指出。
上拉电阻不能太大
当上拉电阻大了之后,在电路中消耗的攻略就多了,所能流过的电流也小了。这个电流过小会影响芯片的正常工作;上拉电阻大了之后还会导致电压变化速度慢,可能会产生误码。
上拉电阻也不能太小
电阻小了,一个最直观的影响就是,能流过该电阻的电流变大,电流过大容易超出电阻的额定工作电压,同时输入到芯片的电流大了(超过引脚最大允许电流),也会对芯片造成损伤。
上拉电阻实际应用时候的选择
上拉电阻的值,可以通过计算得到最大值和最小值,只需要在这个里面选择就行,NXP有一份文档描述了IIC总线和上拉电阻的选择,链接: link
网上也有一些比较粗暴的方法:在1-10k中间选一个合适的。
具体怎么操作还是根据自己的喜好来(出了问题可能就是怎么也不会想到是上拉电阻的问题)
总结
遇到的问题有两个:
1、写RDAC的时候没有关闭RDAC的写保护
2、上拉电阻过大,驱动能力不足
最终的电路图就如下所示。
尝试了模拟IIC;电脑做主机,用调试器控制从机;用开发板调试;用HAL库调试;每种方法都是可以达到最终的效果的,所以在写程序前,一定一定要检查硬件电路的问题,硬件有问题,软件写出花来了也带不动。