使用SMBus访问温度传感器,并控制smart Fan
首先聊聊SMBus的访问方法
硬件上:两条线SMBus Clock和Data信号
当clock信号为高时data信号才有效,data信号下降,意味着Start。data信号上升,意味着Stop。开始后会发送九位,包括八位数据,一个应答位,如下图,
从示波器上可以看到(蓝为clock,黄为data),可以看到发送的为01011100,第9为应答位为高,即NACK,设备无响应。最后为stop。
这样就可以通过示波器知道SMBus设备是否响应。
软件上:在SMBus基地址后续寄存器有状态、访问方式、命令、从地址、数据等寄存器,这些寄存器都可查看datasheet。访问方式即为:
1、清状态(清完后为0x40)
2、写从地址(从地址最后一位1为读,0为写)
3、写数据(读不用)
4、设置访问方式(字节、字、双字访问)
5、等待应答(ACK状态寄存器变0x42,NACK则为0x44)
6、读数据(写不用)
举个栗子:下面代码为SMBus访问内存SPD信息
#include <stdio.h>
#include <conio.h>
#include <dos.h>/*register add*/
#define SMB_Base_Add 0xf000/*read SPD by byte*/
#define HST_STS 0x00
#define HST_CNT 0x02
#define HST_CMD 0x03
#define XMIT_SLVA 0x04
#define HST_D0 0x05void D_delay();
int SMB_ACK();
int Register_Configuration(int SPD_add);void main()
{int data,k;printf(" ");for(k=0x0;k<=0xf;k++){printf(" %02x",k);}printf("\n");for(k=0x0;k<=0xff;k++){if(k%16==0){printf("\n");printf("%02x",k);}data = Register_Configuration(k);/*read data*/printf(" %02x",data);}getch();
}
int Register_Configuration(int SPD_add)
{int state,data;outportb(SMB_Base_Add|HST_STS,0xFE);/*clear */outportb(SMB_Base_Add|XMIT_SLVA,0xA1);/*slave/SPD base address *///1 is read,0 is write/* last bit is w/r,must be 1 */outportb(SMB_Base_Add|HST_CMD,SPD_add);/*offset*/outportb(SMB_Base_Add|HST_CNT,0x48);/*byte read*/D_delay(); ·state = SMB_ACK();if(state!=0){return 0xff;}data = inportb(SMB_Base_Add|HST_D0);D_delay();return data;}
void D_delay()
{int i;for(i=100;i>0;i--);
}
int SMB_ACK() /*check smbus ready*/
{int state_A,state_B,i,s=0;for(i=0;i<0x80;i++) /*circle until ACK = 0*/{state_A = inportb(SMB_Base_Add|HST_STS);D_delay();outportb(SMB_Base_Add|HST_STS,state_A);D_delay();state_B = state_A;state_B = state_A&0x02;if(state_B!=0) /* INTR = 1 BIT1 */{goto ret;}state_B = state_A;state_B = state_B&0xbf; /* INUSE_STS = 0 BIT6 */if(state_B==0){goto ret;}state_B = state_A;state_B = state_B&0x04; /* DEV_ERR = 1(Invalid Command/Time-out/Unclaimed Cycle) BIT2 */if(state_B){break;}}s = 1;ret:return s;}
下面为温度传感器并能智能控制风扇的芯片EMC2103-1,该芯片slave address为0x5c
DP、DN接thermal,TRIP_SET引脚由硬件接多大电阻决定shutdown的温度,使用smbus访问
有四种方式控制(查看datasheet)
1、PWM直接控制风扇,不根据温度,EN_ALGO、LUT_LOCK写0,无需配置Look Up Table,直接写Fan Driver Setting
2、FSC:Fan Speed Control Mode, EN_ALGO写1、LUT_LOCK写0,
3、PWM Setting w/LUT Mode
首先配置LUT,八个温度设置和八个改温度下对应风扇PWM设置,然后LUT_LOCK写1,RPM/PWM写1。注:LUT_LOCK置1时无法改写LUT
代码如下,注:如果无法连续写,应该是状态没清掉
void Smbus_delay()
{int i,j;for(i=0;i<256;i++)for(j=0;j<256;j++)IoWrite8(0x400+0x00,0xdf);
}
void Smbus_Write(UINT8 address,UINT8 value)
{IoWrite8(0x400+0x00,0xdf);IoWrite8(0x400+0x00,0xdf);IoWrite8(0x400+0x00,0xdf);IoWrite8(0x400+0x00,0xdf);IoWrite8(0x400+0x04,0x5c);IoWrite8(0x400+0x03,address);IoWrite8(0x400+0x05,value);IoWrite8(0x400+0x02,0x48);IoWrite8(0x400+0x00,0xdf);IoWrite8(0x400+0x00,0xdf);IoWrite8(0x400+0x00,0xdf);IoWrite8(0x400+0x00,0xdf);
}
void main()
{Smbus_Write(0x50,0x00);Smbus_delay();Smbus_Write(0x51,0x44);Smbus_delay();Smbus_Write(0x52,0x30);Smbus_delay();Smbus_Write(0x56,0x66);Smbus_delay();Smbus_Write(0x57,0x35);Smbus_delay();Smbus_Write(0x5b,0x88);Smbus_delay();Smbus_Write(0x5c,0x3e);Smbus_delay();Smbus_Write(0x60,0xaa);Smbus_delay();Smbus_Write(0x61,0x42);Smbus_delay();Smbus_Write(0x65,0xbb);Smbus_delay();Smbus_Write(0x66,0x48);Smbus_delay();Smbus_Write(0x6a,0xdd);Smbus_delay();Smbus_Write(0x6b,0x4e);Smbus_delay();Smbus_Write(0x6f,0xee);Smbus_delay();Smbus_Write(0x70,0x50);Smbus_delay();Smbus_Write(0x74,0xff);Smbus_delay();Smbus_Write(0x75,0x55);Smbus_delay();Smbus_Write(0x50,0x30);Smbus_delay();
}