1. 程式人生 > >51微控制器利用IIC匯流排對LM75A溫度進行讀取

51微控制器利用IIC匯流排對LM75A溫度進行讀取

#include <INTRINS.H>
#include "..\config\c8051f350.h"
#include "..\config\const.h"
#include "..\driver\system.h"
#include "..\driver\other.h"

#define IIC_WRITE 0
#define IIC_READ  1
#define VREF 24380

static unsigned long sysclk=24500000;

sbit SDA=P0^0;
sbit SCL=P0^1;
sbit led=P1^2; 

void Delay_us(unsigned int times){
	unsigned int i;
	for(i=0;i<times;i++){
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		}
}			           //延時us函式

void Delay_ms(unsigned int times)
{
	unsigned int i;
	for (i=0;i<times;i++)
		Delay_us(1000);
}					   //延時ms函式

void iic_start(void){
	  SDA = 1;
	  Delay_us(2);
      SCL = 1;
	  Delay_us(2);
      SDA = 0;
	  Delay_us(2);  
}					  //iic通訊起始訊號


void iic_stop(void){
	  SDA = 0;
	  Delay_us(2);
      SCL = 1;
	  Delay_us(2);
      SDA =1;
}				      //iic通訊終止訊號

void iic_ack(void)                      
{ 
	  SCL = 0;
      SDA = 0;
	  Delay_us(2);
      SCL = 1;
	  Delay_us(2);  
      SCL = 0;
	  Delay_us(1); 
      SDA = 1;
}						//傳送應答訊號函式

bool read_ack(void)                      
{ 
	  bool flag;
	 
      SCL = 0;
	  Delay_us(2);    
      SDA = 1;
      SCL = 1;
	  Delay_us(2);
      flag = SDA; 
      SCL = 0;  
      
	  return flag;
}						//iic應答函式

void iic_nack()                     
{   
      SDA = 1;
	  Delay_us(2);      
      SCL = 1;
	  Delay_us(2);      
	  SCL = 0;
}                        //iic非應答函式

unsigned char get_byte(void)                                 
{
    unsigned char dd;
    int i;
    
    dd=0;
   	SDA = 1;
	for (i=0;i<8;i++)
    {
		 Delay_us(1);
         SCL = 0;
		 Delay_us(5);
         SCL = 1;
		 Delay_us(2); 
         dd<<=1;
		 if (SDA)
      	      dd|=0x01;
		 Delay_us(1);
    }         
    SCL = 0;
	Delay_us(1);
	return dd;
}					     //輸入一個位元組

void out_byte(unsigned char dd)                      
{
    unsigned char i;

    for(i=0;i<8;i++)
    {  
          SCL = 0;
		  Delay_us(0);			
          SDA = (dd & 0x80)>>7;
		  Delay_us(2);         
          SCL = 1;
		  Delay_us(3);
          dd <<= 1;
    } 
	SCL = 0;    
}					     //輸出一個位元組

bool iic_write_addr(unsigned char addr,unsigned char data_addr)
{
	  iic_start();
      out_byte(addr); 
      read_ack();   
      out_byte(data_addr);
      read_ack();     
      return TRUE;          
}                        //寫入器件地址和所需讀取暫存器的地址

void IICA_Read(unsigned char id, unsigned char addr, unsigned char *p, unsigned int len)
{                                                    
         int i;
         bit EA_SAVE = EA;

	     EA = 0;
     	 iic_write_addr(id|IIC_WRITE,addr);  
     	 iic_start();
     	 out_byte(id|IIC_READ);
     	 read_ack();     
     	 for (i=0;i<len;i++)
      	 {
      		   *p++ = get_byte();
      	 	   if (i!=(len-1))
      	   			iic_ack();      	   
      	 }       
    	 iic_nack();        
      	 iic_stop();
     	 EA = EA_SAVE;
}						//iic匯流排讀取多個數據

float readTemperature(){
	unsigned char id=0x90;
	unsigned char addr=0x00;
	unsigned int len=2;
	unsigned char temp[2]={0};
	float temp_value=0.0;
	unsigned int temp_high=0;
	unsigned int temp_low=0;
	unsigned int low=0;
	unsigned int tempforh=0;
	unsigned int judge_posneg=0;

	IICA_Read(id,addr,temp,2);

	temp_high=temp[0];
	temp_low=temp[1];
	low=temp_low>>5;
	tempforh=temp_high*8+low;

	judge_posneg=(temp_high & 0x80)>>7;
	if(judge_posneg==0){
		temp_value=tempforh*0.125;
		return temp_value;
		}else {
			tempforh=(tempforh^0x7FF)+1;
			temp_value=tempforh*(-0.125);   
			return temp_value;
			}
}					    //讀取並計算當前溫度

float main(){
	float tempvalue=0.0;
	PCA0MD&=~0x40;    // 禁止看門狗定時器

	Sysclk_Init();    // 配置系統時鐘
	SysPort_Init();   // 埠配置
	tempvalue=readTemperature();
	while(1){
	led=1;
	Delay_ms(1000);
	led=0;
	Delay_ms(1000);
	}
	SDA=1;
	return tempvalue;
	}