⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c_ds1631.c

📁 AVR - using ds1631 throug i2c.
💻 C
字号:
// from scratch i2c to control the ds1631 temperature sensor
//
//	Author: Dingo_aus
//
//	Date: 14/12/2004
//
//	This work is subject to Copryright. No reproduction is allowed without prior express consent of the author
//
//  Contact: see http://www.users.on.net/~symes/Email.htm or pm Dingo_aus at www.avrfreaks.net


#include <avr/io.h>
#include "../avrlib/uart.h"	//to allow easy uart communications (chews up about 1k of code space (1k left available))

#define DEV_DS1631	0x90	//I2C slave address of the ds1631 with a1-3 to GND
#define BIT_SCL	5	//SCL on PORT D, pin PD5
#define BIT_SDA 6	//SDA on PORT D, pin PD6

void delay(void);
void start(void);
void tx_byte(int);
int acknow(void);
void write_config(int);
void start_read_temp(void);
void read_temp(void);
char rx_byte(void);

u08 senddatum;
int temperature[2];	//global variable to store the actual temperature value

int main(void)
{
	delay();
	asm volatile ("cli");	//turn off interrupts
	
	temperature[0] = 0;
	temperature[1] = 0;
	
	uartInit();
	uartSetBaudRate(9600);
	
	DDRD |= (1<<BIT_SDA);	//set SDA pin as output
	DDRD |= (1<<BIT_SCL);  //set SCL pin as output
	PORTD |=(1<<BIT_SDA);	//SDA high
	PORTD |=(1<<BIT_SCL);	//SCL high
	
	write_config(0x0f);
	start_read_temp();
	read_temp();
	
		
	
}


void delay()
{
	//the original delay code filled two registers with 0XFF then decremented both loops,
	//one inside the other. Total delay .0244 seconds
	
	//This "for" loop gives approximately the same delay 
	
	
	for(int temp = 63000; temp<1 ;temp--)
	{
		asm volatile("nop");
	}	
		
	return;
}

//sends start condition on the I2C bus
void start(void)
{	
	//different to 24LC256 code.
	//DS1631 datasheet says SCL high then SDA goes low to indicate START
	//PORTD |= (1<< BIT_SCL);
	//PORTD |= (1<<BIT_SCL);
	
	PORTD |= (1 << BIT_SCL);
	PORTD &= ~(1 << BIT_SDA);
	
}


void tx_byte(int value)	
{	
	for(int n=0;n<=7;n++)
	{
		//take it high
		PORTD |= (1<<BIT_SDA);
		//look at the left (MSB) most byte of temp
		if(!(value & 0x80))	//if left most byte is 0 then....
		{	
			//SDA low
			PORTD &= ~(1<<BIT_SDA);
		}
		//left shift so next loop iteration deals with next value
		value = value<<1;
		
		//pulse clock line
		PORTD |=(1<<BIT_SCL);		//high
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		PORTD &= ~(1<<BIT_SCL);	//low		
		
	}
	
	
	return;
}

//checks if the ack bit came back (maybe add a delay? --A: called in a loop - no need for delay)
int acknow(void)
{
	//change DDRD:take SDA low on DDRD (make input)
	DDRD &= ~(1 << BIT_SDA);
	//take SDA high
	PORTD |= (1<<BIT_SDA);
	
	//set carry flag
	int tempret = 1;
	//take SCL high
	PORTD |=(1<<BIT_SCL);
	asm volatile ("nop");
	asm volatile ("nop");
	//if SDA low then clear the carry flag
	if(!((PIND & 0x40)==0x40))	//check if SDA is low (hard coded to PD6)
	{
		senddatum = '-';
		uartSendByte(senddatum);
	
		tempret = 0;	//success
		
	}
	
	//take SCL low
	PORTD &= ~(1 << BIT_SCL);
	
	//make SDA oupput again by changign DDRD
	DDRD |= (1<<BIT_SDA);
	
	//return
	return tempret;	

}

void write_config(int config)
{
	int done = 0;
	while(!done)
	{
		
		PORTD &= ~(1 << BIT_SDA);//send start condition (take lines low)
		PORTD &= ~(1 << BIT_SCL);
		
	
		tx_byte(0x90);	//send the slave address so correct slave picks up
		if(acknow())
		{
			senddatum = '1';
			uartSendByte(senddatum);	
			continue;
		}
		
		tx_byte(0xAC);	//send the access configuration command
		if(acknow())
		{
			senddatum = '2';
			uartSendByte(senddatum);
			continue;
		}
		
		tx_byte(config);	//POL is active high, and 1SHOT mode, 12-bit precision
		if(acknow())
		{
			continue;
		}		
		
		//Now create a stop condition
		
		
		PORTD &= ~(1<<BIT_SDA);
		
		PORTD |= (1<<BIT_SCL);	//stop condition
		PORTD |= (1<<BIT_SDA);
		
		senddatum = 'O';
		uartSendByte(senddatum);
		senddatum = 'K';
		uartSendByte(senddatum);
	
		done = 1;
	
	}
	return;

}

void start_read_temp()
{	
	int done = 0;
	while(!done)
	{
		//This start assumes last routine left lines high (ie proper STOP condition, then idle)
		PORTD &= ~(1 << BIT_SDA);//send start condition (take lines low)
		PORTD &= ~(1 << BIT_SCL);
		
		tx_byte(0x90);	//send the slave address so correct slave picks up
		if(acknow())
		{
			senddatum = '4';
			uartSendByte(senddatum);	
			continue;
		}
		
		tx_byte(0x51);	//send the Start temperature conversion command - for 1SHOT mode it automatically stops after this
		if(acknow())
		{
			senddatum = '5';
			uartSendByte(senddatum);	
			continue;
		}
	
		PORTD &= ~(1<<BIT_SDA);
		
		PORTD |= (1<<BIT_SCL);	//stop condition
		PORTD |= (1<<BIT_SDA);
	
		senddatum = 's';
		uartSendByte(senddatum);	
		senddatum = 't';
		uartSendByte(senddatum);	
		senddatum = 'a';
		uartSendByte(senddatum);	
		senddatum = 'r';
		uartSendByte(senddatum);	
		senddatum = 't';
		uartSendByte(senddatum);	
		senddatum = 'e';
		uartSendByte(senddatum);	
		senddatum = 'm';
		uartSendByte(senddatum);	
		senddatum = 'p';
		uartSendByte(senddatum);	
	
		done = 1	;
	}
		
	
	return;
}

//Function to read the temp stored during start_read_temp()
//Value is two bytes and stored in a global variable (no array passed to this function at this stage)
void read_temp(void)
{
		int done = 0;
	while(!done)
	{
		//This start assumes last routine left lines high (ie proper STOP condition, then idle)
		PORTD &= ~(1 << BIT_SDA);//send start condition (take lines low)
		PORTD &= ~(1 << BIT_SCL);
		
		tx_byte(0x90);	//send the slave address so correct slave picks up
		if(acknow())
		{
			senddatum = '6';
			uartSendByte(senddatum);	
			continue;
		}
		
		tx_byte(0xAA);	//send the command to read the temp
		if(acknow())
		{
			senddatum = '7';
			uartSendByte(senddatum);	
			continue;
		}
	
		//Need to repeat the start condition to change to read mode
		PORTD |= (1<<BIT_SDA);
		PORTD |= (1<<BIT_SCL);
		//delay??
		PORTD &= ~(1<<BIT_SDA);
		//had problem before without this (as long as SDA goes down first)
		PORTD &= ~(1<<BIT_SCL);
		
		tx_byte(0x91);	//send the slave address but with R/W bit set to 1 for read
		if(acknow())
		{
			senddatum = '8';
			uartSendByte(senddatum);	
			continue;
		}
		
		//read in MSB
		temperature[0] = rx_byte();
		
		//send ack signal
		PORTD |= (1<<BIT_SDA);
		PORTD |= (1<<BIT_SCL);
		
		PORTD &= ~(1<<BIT_SCL);
		PORTD &= ~(1<<BIT_SDA);
		
		//pulse SCL
		PORTD |= (1<<BIT_SCL);
		//leaving SDA low
		asm volatile ("nop");
		PORTD &= ~(1<<BIT_SCL);
		PORTD |= (1<<BIT_SDA);
		PORTD |= (1<<BIT_SCL);
		
		temperature[1] = rx_byte();
		
		
		PORTD &= ~(1<<BIT_SDA);
		
		PORTD |= (1<<BIT_SCL);	//stop condition
		PORTD |= (1<<BIT_SDA);
	
		senddatum = 13;
		uartSendByte(senddatum);	
		senddatum = 't';
		uartSendByte(senddatum);	
		senddatum = 'e';
		uartSendByte(senddatum);	
		senddatum = 'm';
		uartSendByte(senddatum);	
		senddatum = 'p';
		uartSendByte(senddatum);	
		senddatum = 'r';
		uartSendByte(senddatum);	
		senddatum = 'e';
		uartSendByte(senddatum);	
		senddatum = 'a';
		uartSendByte(senddatum);	
		senddatum = 'd';
		uartSendByte(senddatum);	
		senddatum = ':';
		uartSendByte(senddatum);	
		senddatum = temperature[0];
		uartSendByte(senddatum);
		senddatum = temperature[1];
		uartSendByte(senddatum);			
	
		done = 1	;
	}
		
	return;
}

char rx_byte(void)
{
	
	//char retval = 0x00;//TEMP  = 0x0000
	int flag=0;
	DDRD &= ~(1<<BIT_SDA);	//SDA made input
	PORTD |=(1<<BIT_SDA);	//set SDA high
	
	int temprxval = 0;
		
	for(int t=0; t<=7; t++)	//need to step through each bit received from the bus
	{
		PORTD |= (1<<BIT_SCL);
		flag = 1;
		if(!((PIND & 0x40)==0x40))	//if SDA low
		{
			flag = 0;
			senddatum = '0';
			uartSendByte(senddatum);
		}
		else
		{
		senddatum = '1';
		uartSendByte(senddatum);
		}
		temprxval = (temprxval << 1);
		temprxval = temprxval | flag;
		
			
		//retval = retval | flag;
		//retval = retval<<1;
		//retval++;
		
		
		
		PORTD &= ~(1<<BIT_SCL);
		
	}
	senddatum = 13;
	uartSendByte(senddatum);
	//senddatum = temprxval;
	//uartSendByte(senddatum);
	
	DDRD |=(1<<BIT_SDA);	//SDA made output again

	return temprxval;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -