Kód: Egész kijelölése
#define F_CPU 16000000UL
#define SCL_CLOCK 100000L
#define DS1307_ADDR (0xD0) //device address
#include <avr/io.h>
#include <util/delay.h>
#include <lcd.c>
#include <stdlib.h>
#include <temp_sensor_util.h>
#include <avr/eeprom.h>
#include <compat/twi.h>
#include <i2cmaster.h>
#include <avr/pgmspace.h>
char buffer[20];
uint8_t negativ=0,egesz=0,tort=0,min_egesz=200,min_tort=0,max_egesz=0,max_tort=0;
uint8_t scratchpad[9];
uint8_t year, month, day, hour, minute, second;
/*************************************************************************
Initialization of the I2C bus interface. Need to be called only once
*************************************************************************/
void i2c_init(void)
{
/* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
TWSR = 0; /* no prescaler */
TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */
}/* i2c_init */
/*************************************************************************
Issues a start condition and sends address and transfer direction.
return 0 = device accessible, 1= failed to access device
*************************************************************************/
unsigned char i2c_start(unsigned char address)
{
uint8_t twst;
// send START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// wait until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
// send device address
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
// wail until transmission completed and ACK/NACK has been received
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
return 0;
}/* i2c_start */
/*************************************************************************
Issues a start condition and sends address and transfer direction.
If device is busy, use ack polling to wait until device is ready
Input: address and transfer direction of I2C device
*************************************************************************/
void i2c_start_wait(unsigned char address)
{
uint8_t twst;
while ( 1 )
{
// send START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// wait until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
// send device address
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
// wail until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
{
/* device busy, send stop condition to terminate write operation */
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
// wait until stop condition is executed and bus released
while(TWCR & (1<<TWSTO));
continue;
}
//if( twst != TW_MT_SLA_ACK) return 1;
break;
}
}/* i2c_start_wait */
/*************************************************************************
Issues a repeated start condition and sends address and transfer direction
Input: address and transfer direction of I2C device
Return: 0 device accessible
1 failed to access device
*************************************************************************/
unsigned char i2c_rep_start(unsigned char address)
{
return i2c_start( address );
}/* i2c_rep_start */
/*************************************************************************
Terminates the data transfer and releases the I2C bus
*************************************************************************/
void i2c_stop(void)
{
/* send stop condition */
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
// wait until stop condition is executed and bus released
while(TWCR & (1<<TWSTO));
}/* i2c_stop */
/*************************************************************************
Send one byte to I2C device
Input: byte to be transfered
Return: 0 write successful
1 write failed
*************************************************************************/
unsigned char i2c_write( unsigned char data )
{
uint8_t twst;
// send data to the previously addressed device
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
// wait until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits
twst = TW_STATUS & 0xF8;
if( twst != TW_MT_DATA_ACK) return 1;
return 0;
}/* i2c_write */
/*************************************************************************
Read one byte from the I2C device, request more data from device
Return: byte read from I2C device
*************************************************************************/
unsigned char i2c_readAck(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}/* i2c_readAck */
/*************************************************************************
Read one byte from the I2C device, read is followed by a stop condition
Return: byte read from I2C device
*************************************************************************/
unsigned char i2c_readNak(void)
{
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}/* i2c_readNak */
/*
* days per month
*/
const uint8_t ds1307_daysinmonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 };
/*
* initialize the accellerometer
*/
void ds1307_init() {
i2c_init();
_delay_us(10);
}
/*
* transform decimal value to bcd
*/
uint8_t ds1307_dec2bcd(uint8_t val) {
return val + 6 * (val / 10);
}
/*
* transform bcd value to deciaml
*/
static uint8_t ds1307_bcd2dec(uint8_t val) {
return val - 6 * (val >> 4);
}
/*
* get number of days since 2000/01/01 (valid for 2001..2099)
*/
static uint16_t ds1307_date2days(uint8_t y, uint8_t m, uint8_t d) {
uint16_t days = d;
for (uint8_t i = 1; i < m; ++i)
days += pgm_read_byte(ds1307_daysinmonth + i - 1);
if (m > 2 && y % 4 == 0)
++days;
return days + 365 * y + (y + 3) / 4 - 1;
}
/*
* get day of a week
*/
uint8_t ds1307_getdayofweek(uint8_t y, uint8_t m, uint8_t d) {
uint16_t day = ds1307_date2days(y, m, d);
return (day + 6) % 7;
}
/*
* set date
*/
uint8_t ds1307_setdate(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
//sanitize data
if (second < 0 || second > 59 ||
minute < 0 || minute > 59 ||
hour < 0 || hour > 23 ||
day < 1 || day > 31 ||
month < 1 || month > 12 ||
year < 0 || year > 99)
return 8;
//sanitize day based on month
if(day > pgm_read_byte(ds1307_daysinmonth + month - 1))
return 0;
//get day of week
uint8_t dayofweek = ds1307_getdayofweek(year, month, day);
//write date
i2c_start_wait(DS1307_ADDR | I2C_WRITE);
i2c_write(0x00);//stop oscillator
i2c_write(ds1307_dec2bcd(second));
i2c_write(ds1307_dec2bcd(minute));
i2c_write(ds1307_dec2bcd(hour));
i2c_write(ds1307_dec2bcd(dayofweek));
i2c_write(ds1307_dec2bcd(day));
i2c_write(ds1307_dec2bcd(month));
i2c_write(ds1307_dec2bcd(year));
i2c_write(0x00); //start oscillator
i2c_stop();
return 1;
}
/*
* get date
*/
void ds1307_getdate() {
i2c_start_wait(DS1307_ADDR | I2C_WRITE);
i2c_write(0x00);//stop oscillator
i2c_stop();
i2c_rep_start(DS1307_ADDR | I2C_READ);
second = ds1307_bcd2dec(i2c_readAck() & 0x7F);
minute = ds1307_bcd2dec(i2c_readAck());
hour = ds1307_bcd2dec(i2c_readAck());
i2c_readAck();
day = ds1307_bcd2dec(i2c_readAck());
month = ds1307_bcd2dec(i2c_readAck());
year = ds1307_bcd2dec(i2c_readNak());
i2c_stop();
}
void writeTemp(){
lcd_gotoxy(0,0);
if (negativ) // If its negative
{
lcd_putc('-');
}
lcd_puts(itoa(egesz,buffer,10));
lcd_putc('.');
lcd_puts(itoa(tort,buffer,10)); //tortresz
lcd_puts(" ");
}
void writeDate(){
lcd_gotoxy(0,1);
lcd_puts(itoa(year,buffer,10));
lcd_putc('/');
lcd_puts(itoa(month,buffer,10));
lcd_putc('/');
lcd_puts(itoa(day,buffer,10));
}
void writeTime(){
lcd_gotoxy(0,2);
lcd_puts(itoa(hour,buffer,10));
lcd_putc(':');
lcd_puts(itoa(minute,buffer,10));
lcd_putc(':');
lcd_puts(itoa(second,buffer,10));
}
static void master_reset(void)
{
//Master Tx reset pulse
//Pull bus low 480us minimum
MASTER_TX();
BUS_LOW();
_delay_us(480);
//Master Rx 480us minimum
//Waiting for DS18B20 presence pulse
MASTER_RX();
_delay_us(480);
}
static void master_write_bit(uint8_t bit_value)
{
//Initiate write time slot
MASTER_TX();
BUS_LOW();
_delay_us(1);
//Pull bus high to write "1" to DS18B20
//or leave bus low to write "0" to DS18B20
if(bit_value != 0)
{
BUS_HIGH();
}
_delay_us(59); //delay to meet write time slot req.
//1us recovery time
MASTER_RX();
_delay_us(1);
}
static uint8_t master_read_bit(void)
{
uint8_t bit_value;
//Initiate write time slot
MASTER_TX();
BUS_LOW();
_delay_us(1);
//Master releasing bus
MASTER_RX();
_delay_us(10); //wait for DS18B20 output to stablize
//Read in bit value
if(BUS_LINE == 0)
{
bit_value = 0;
}
else
{
bit_value = 1;
}
//wait to meet minimum read time slot of 60us plus 1us recovery time
_delay_us(50);
return bit_value;
}
static void master_send_command(uint8_t command, commandType cmd_type)
{
uint8_t bit_pos;
//Need to reset for new round of access of DS18B20
if(cmd_type == ROM_COMMAND_TYPE)
{
master_reset();
}
//Write each bit to DS18B20, LSB first
for(bit_pos = 0; bit_pos != 8; ++bit_pos)
{
master_write_bit(command & (1<<bit_pos));
}
}
static int16_t master_read_temp(void)
{
uint8_t bit_pos;
uint8_t i;
//initialize, send rom command "skip rom" and function command "read scratchpad"
master_send_command(ROM_COMMAND_SKIP_ROM, ROM_COMMAND_TYPE);
master_send_command(FUNCTION_COMMAND_READ_SCRATCHPAD, FUNC_COMMAND_TYPE);
//read scratchpad
for(i=0;i<9;i++){
scratchpad[i]=0;
for(bit_pos=0;bit_pos<8;++bit_pos)
scratchpad[i]|=master_read_bit()<<bit_pos;
}
return (scratchpad[1]<<8)|(scratchpad[0]);
}
void get_temp(void)
{
int16_t TReading, Tc_100;
TReading = master_read_temp();
if (TReading & 0x8000) // negative
{
TReading = (TReading ^ 0xffff) + 1; // 2's comp
negativ=1;
}
else negativ=0;
Tc_100 = (int16_t)(6.25 * TReading); // multiply by (100 * 0.0625) or 6.25
egesz = (uint8_t)(Tc_100 / 100); // egeszresz
tort=(uint8_t)((Tc_100 % 100)/10); //tortresz
}
void start_conversion(void)
{
//initialize, send rom command "skip rom" and function command "convert t"
master_send_command(ROM_COMMAND_SKIP_ROM, ROM_COMMAND_TYPE);
master_send_command(FUNCTION_COMMAND_CONVERT_T, FUNC_COMMAND_TYPE);
}
uint8_t crc8(const uint8_t *addr)
{
uint8_t crc = 0;
uint8_t len=8;
while (len--) {
uint8_t inbyte = *addr++;
for (uint8_t i = 8; i; i--) {
uint8_t mix = (crc ^ inbyte) & 0x01;
crc >>= 1;
if (mix) crc ^= 0x8C;
inbyte >>= 1;
}
}
return crc;
}
int main()
{
lcd_init(LCD_DISP_ON);
lcd_clrscr();
start_conversion();
ds1307_init();
while(1)
{
if (master_read_bit() == 1){ //konverzio kesz
get_temp();
start_conversion();
if (crc8(scratchpad)==scratchpad[8]) writeTemp();
}
ds1307_getdate();
writeDate();
writeTime();
}
return 0;
}