LM75A,数字温度传感器,IIC接口,读取简单,只需要读取2个寄存机的值就可计算出来温度
手里里有个贴片的LM75A,在一块废弃的pcb板上利用0805电阻脚把lm75a的sda和scl脚焊好,其它的引脚用插针焊好
现在lm75a对外有4个引脚,分别是VCC,GND,SDA,SCL
把5,6,7,8,脚焊在了一起,这样根据pdf介绍
它的iic地址为1001111,即0x4F。
把VCC,GND,SDA,SCL与cc2530网关开发板的终端开发板连接起来
LM75A | CC2530终端开发板 |
---|---|
VCC | +3.3V |
GND | GND |
SDA | P0_6 |
SCL | P0_7 |
先写软件模拟iic,cc2530根普通的51单片机单片机,普通的51单片机读取io状态的时候把io置高直接读就可以了,而cc2530需要专门专门设定寄存器来制定当前的io是输入还是输出,因此多写了写了2个宏用于寄存器赋值
#define SDA P0_6//数据线
#define SCL P0_7//时钟线
#define _nop_() asm("nop");
#define set_sda_in() P0DIR &= ~(1<<6)
#define set_sda_out() P0DIR |= 1<<6
软件模拟iic的驱动如下:
#include "iic.h"
/*
I2C通信使用delay()函数
一个_nop_()延时1us,总线要求延时大于4.7us
单片机频率执行周期不同时按实际需要修改
sck时钟频率400k
*/
void delay()
{
int i = 0;
for(i = 0; i < 32*4.7; i++)
_nop_();
}
//总线初始化
//将总线都拉高以释放总线
void iic_init()
{
set_sda_out();
SCL = 1;
delay();
SDA = 1;
delay();
}
//启动信号
//SCL在高电平期间,SDA由高电平向低电平的变化定义为启动信号
void iic_start()
{
set_sda_out();
SDA = 1;
delay();
SCL = 1;
delay();
SDA = 0;
delay();
}
//停止信号
//SCL在高电平期间,SDA由低电平向高电平的变化定义为停止信号
void iic_stop()
{
set_sda_out();
SDA = 0;
delay();
SCL = 1;
delay();
SDA = 1;
delay();
}
//应答信号
//SCL在高电平期间,SDA被从设备拉为低电平表示应答
//其中(SDA == 1)&&(i<255)表示若在一段时间内没有收到从器件的应答则主器件默认从器件已经收到数据而不再等待应答信号
//若没有这部分代码,程序会停在这里,实际运用中不允许这种情里发生,或者return ture或false,方便调试
//等待从设备产生应答
void iic_srespons()
{
set_sda_in();
unsigned char i = 0;
SCL = 1;
delay();
while((SDA == 1)&&(i<254))
i++;
SCL = 0;
delay();
}
//由主设备发出应答
//从设备在发送完一字节后将SDA拉高(SDA被释放),主设备将SDA拉低产生应答
void iic_mrespons()
{
set_sda_out();
SDA = 0;//直接将SDA拉低,再操纵SCL
delay();
SCL = 1;
delay();
SCL = 0;
delay();
}
//主设备不应答
void iic_nrespons()
{
set_sda_out();
SDA = 1;//SDA高电平为不应答
delay();
SCL = 1;
delay();
SCL = 0;
delay();
}
//写入
//串行发送一个字节时,需要把这个字节中的8位一位一位地发出去,“temp=temp<<1;”
//表示将temp左移一位,最高位将移入PSW寄存器的CY位中,然后将CY赋给SDA进而在SCL的控制下发送出去
//最后将SDA拉高,以等待从设备产生应答
void iic_write(unsigned char data)
{
set_sda_out();
unsigned char i, temp;
temp = data;
for(i=0; i<8; i++)
{
SCL = 0;
delay();
SDA = temp/128;
delay();
SCL = 1;
delay();
temp = temp << 1;
}
SCL = 0;
delay();
SDA = 1;
delay();
}
//读出
//串行接受一个字节时需了、将8位一位一位地接受,然后再组合成一个字节,
//代码定义了k,将k左移一位后与SDA进行“或”运算,一次把8个独立的位放入一个字节中来完成接收
unsigned char iic_read()
{
set_sda_in();
unsigned char i, k;
SCL = 0;
delay();
SDA = 1;
delay();
for(i=0; i<8; i++)
{
SCL = 1;
delay();
k = (k<<1)|SDA;
SCL = 0;
delay();
}
delay();
return k;
}
在main函数中开启的串口用于显示温度,因为不读只往外写
串口初始化函数
void uart_init(void) { PERCFG = 1<<1; //uart1:P1 alt2 P0SEL = (1<<2)|(1<<3); //P0_2,P0_3用作串口,第二功能 P0DIR &= ~(1<<2); //P0_2 rxd input P0DIR |= (1<<3); //P0_3 txd output P2DIR &= ~0XC0; //P0优先作为UART0 U0CSR |= 0x80; //UART方式 U0GCR |= 11; U0BAUD |= 216; //波特率设为115200 其中关于修改波特率值的问题 UTX0IF = 1; //具体参看用户手册的串口部分 //U0CSR |= 0x40; //允许接收 // UTX0IF = 0; //UART0 TX中断标志初始置位0 //IEN0 |= 1<<2; // 开总中断,接收中断 }
串口发送函数
void uart_send(char *p_data,unsigned char length)
{
int i=0;
for(i=0;i
float ReadTemp(void)
{
int temphigh, templow;
iic_start();
iic_write(IIC_ADDR);//硬件地址1001111,读模式,LM75不需要指定地址,直接连续读2字节温度
iic_srespons();
temphigh = iic_read();
iic_mrespons();
templow = iic_read();
iic_nrespons();
iic_stop();
if(temphigh > 127)//负温度的处理,理论可行,尚未测试
{
temphigh = (~temphigh) + 1;//~优先级低于+
templow = (~templow) + 1;
temphigh = temphigh << 3;
templow = templow >> 5;
return -(temphigh+templow)*0.125;
}
temphigh = temphigh << 3;
templow = templow >> 5;
return (temphigh+templow)*0.125;
}
void main()
{
int i = 0;
char buffer[20];
system_init();
iic_init();//I2C总线初始化
uart_init();
uart_send("system initial success...\r\n",27);
while(1)
{
uart_send(buffer,sprintf(buffer,"Temperature is: %2.1f\r\n", ReadTemp()));
for(i=0;i<10000;i++) delay();//延迟1s
}
}
成功!温度上升是因为我那电烙铁烤了它。
源码下载链接: 点击打开链接