코딩중 .. 2



// Made by DAEWOO RYU
// NEW TECHNOLOGY COMPANY(N.T.C)
// Email : davdiryu@newtc.co.kr
// http://www.NTC.co.kr
// You can use this source code freely, but we don't support for upgrading or
// we do have no responsiblilty for using this source code for commercial purpose.
// When you spread this source code out, then please leave my name and company name.

// ****************************** //
// *** I2C Hardware Interface *** //
// ****************************** //

#define F_CPU (16000000L)
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <util/delay.h>
#include <compat/twi.h>



#define MAX_TRIES 50
#define DS1307_ID    0xD0        // I2C DS1307 Device Identifier
#define DS1307_ADDR  0x00        // I2C DS1307 Device Address
#define I2C_START 0
#define I2C_DATA 1
#define I2C_DATA_ACK 2
#define I2C_STOP 3
#define ACK 1
#define NACK 0

// DS1307 Register Address
// Second: ds1307_addr[0]
// Minute: ds1307_addr[1]
// Hour  : ds1307_addr[2]
// Day   : ds1307_addr[3]
// Date  : ds1307_addr[4]
// Month : ds1307_addr[5]
// Year  : ds1307_addr[6]

#define HOUR_24 0
#define HOUR_12 1
char ds1307_addr[7];
char sdigit[3]={'0','0','\0'};
char *weekday[]={"Null","Sun","Mon","Tue","Wed","Thr","Fri","Sat"};
char *month[]={"Null","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
char hour_mode, ampm_mode;




/* START I2C Routine */
unsigned char i2c_transmit(unsigned char type) 
{
  switch(type) {
     case I2C_START:    // Send Start Condition
       TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
       break;
     case I2C_DATA:     // Send Data with No-Acknowledge
       TWCR = (1 << TWINT) | (1 << TWEN);
  break;
     case I2C_DATA_ACK: // Send Data with Acknowledge
       TWCR = (1 << TWEA) | (1 << TWINT) | (1 << TWEN);
  break;
     case I2C_STOP:     // Send Stop Condition
  TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
  return 0;
  }
  // Wait for TWINT flag set on Register TWCR
  while (!(TWCR & (1 << TWINT)));
  // Return TWI Status Register, mask the prescaller bits (TWPS1,TWPS0)
  return (TWSR & 0xF8);
}
char i2c_start(unsigned int dev_id, unsigned int dev_addr, unsigned char rw_type)
{
  unsigned char n = 0;
  unsigned char twi_status;
  char r_val = -1;
i2c_retry:
  if (n++ >= MAX_TRIES) return r_val;
  // Transmit Start Condition
  twi_status=i2c_transmit(I2C_START);

  // Check the TWI Status
  if (twi_status == TW_MT_ARB_LOST) goto i2c_retry;
  if ((twi_status != TW_START) && (twi_status != TW_REP_START)) goto i2c_quit;
  // Send slave address (SLA_W)
  TWDR = (dev_id & 0xF0) | (dev_addr & 0x07) | rw_type;
  // Transmit I2C Data
  twi_status=i2c_transmit(I2C_DATA);
  // Check the TWSR status
  if ((twi_status == TW_MT_SLA_NACK) || (twi_status == TW_MT_ARB_LOST)) goto i2c_retry;
  if (twi_status != TW_MT_SLA_ACK) goto i2c_quit;
  r_val=0;
i2c_quit:
  return r_val;
}

void i2c_stop(void)
{
  unsigned char twi_status;
  // Transmit I2C Data
  twi_status=i2c_transmit(I2C_STOP);
}

char i2c_write(char data)
{
  unsigned char twi_status;
  char r_val = -1;
  // Send the Data to I2C Bus
  TWDR = data;
  // Transmit I2C Data
  twi_status=i2c_transmit(I2C_DATA);
  // Check the TWSR status
  if (twi_status != TW_MT_DATA_ACK) goto i2c_quit;
  r_val=0;
i2c_quit:
  return r_val;
}

char i2c_read(char *data,char ack_type)
{
  unsigned char twi_status;
  char r_val = -1;               

  if (ack_type) {
    // Read I2C Data and Send Acknowledge
    twi_status=i2c_transmit(I2C_DATA_ACK);
    if (twi_status != TW_MR_DATA_ACK) goto i2c_quit;
  } else {
    // Read I2C Data and Send No Acknowledge
    twi_status=i2c_transmit(I2C_DATA);
    if (twi_status != TW_MR_DATA_NACK) goto i2c_quit;
  }
  // Get the Data
  *data=TWDR;
  r_val=0;
i2c_quit:
  return r_val;
}

// Convert Decimal to Binary Coded Decimal (BCD)
char dec2bcd(char num)
{
  return ((num/10 * 16) + (num % 10));
}

// Convert Binary Coded Decimal (BCD) to Decimal
char bcd2dec(char num)
{
  return ((num/16 * 10) + (num % 16));
}



void Read_DS1307(void)
{
   char data;
   // First we initial the pointer register to address 0x00
   // Start the I2C Write Transmission
   i2c_start(DS1307_ID,DS1307_ADDR,TW_WRITE);
    // Start from Address 0x00
   i2c_write(0x00);
   // Stop I2C Transmission
   i2c_stop();

   // Start the I2C Read Transmission
   i2c_start(DS1307_ID,DS1307_ADDR,TW_READ);
   // Read the Second Register, Send Master Acknowledge
   i2c_read(&data,ACK);
   ds1307_addr[0]=bcd2dec(data & 0x7F);
   // Read the Minute Register, Send Master Acknowledge
   i2c_read(&data,ACK);
   ds1307_addr[1]=bcd2dec(data);
   // Read the Hour Register, Send Master Acknowledge
   i2c_read(&data,ACK);
   if ((data & 0x40) == 0x40) {
     hour_mode = HOUR_12;
ampm_mode=(data & 0x20) >> 5;   // ampm_mode: 0-AM, 1-PM
ds1307_addr[2]=bcd2dec(data & 0x1F);
   } else {
     hour_mode = HOUR_24;
ampm_mode=0;
     ds1307_addr[2]=bcd2dec(data & 0x3F);
   }
   // Read the Day of Week Register, Send Master Acknowledge
   i2c_read(&data,ACK);
   ds1307_addr[3]=bcd2dec(data);
   // Read the Day of Month Register, Send Master Acknowledge
   i2c_read(&data,ACK);
   ds1307_addr[4]=bcd2dec(data);
   // Read the Month Register, Send Master Acknowledge
   i2c_read(&data,ACK);
   ds1307_addr[5]=bcd2dec(data);
   // Read the Year Register, Send Master No Acknowledge
   i2c_read(&data,NACK);
   ds1307_addr[6]=bcd2dec(data);
   // Stop I2C Transmission
   i2c_stop();
}



void Write_DS1307(void)
{
   unsigned char i, hour_format;
   // Make sure we enable the Oscillator control bit CH=0 on Register 0x00
   ds1307_addr[0]=ds1307_addr[0] & 0x7F;
   // Start the I2C Write Transmission
   i2c_start(DS1307_ID,DS1307_ADDR,TW_WRITE);
   // Start from Address 0x00
   i2c_write(0x00);
   // Write the data to the DS1307 address start at 0x00
   // DS1307 automatically will increase the Address.
   for (i=0; i<7; i++) {
     if (i == 2) {
  hour_format=dec2bcd(ds1307_addr[i]);
  if (hour_mode) {
    hour_format |= (1 << 6);
        if (ampm_mode)
      hour_format |= (1 << 5);
         else
      hour_format &= ~(1 << 5);
  } else {
    hour_format &= ~(1 << 6);
       }
  i2c_write(hour_format);
} else {
       i2c_write(dec2bcd(ds1307_addr[i]));
     }
   }
   // Stop I2C Transmission
   i2c_stop();
}


void port_init(void)
{
  PORTB = 0x00;
  DDRB  = 0x00;

  PORTC = 0x00; //m103 output only
  DDRC  = 0x0f;

  PORTD = 0x00;
  DDRD  = 0x00;
}


unsigned char digit_num=0;
const char segment_data[10] = {63, 6,91,79,102,109,125,39,127,103};
unsigned char display_num[4]={0,0,0,0};         // Seven segment 4자리 숫자 출력 버퍼
unsigned int FourDigit=1234;

volatile int display_now = 0;


void Display(void){        
display_num[0] = (FourDigit%10000)/1000;
    display_num[1] = (FourDigit%1000)/100;
    display_num[2] = (FourDigit%100)/10;
    display_num[3] = (FourDigit%10);
}



typedef unsigned char BYTE;

volatile BYTE RS_Char=0x00;


int SendByte(BYTE data)
{
// while (!((UCSRA) & (1<<UDRE)));
loop_until_bit_is_set(UCSRA,UDRE);
UDR = data;
return 0;
}


SIGNAL(SIG_UART_RECV) // UART0 수신 인터럽트
{
RS_Char = UDR;
SendByte(RS_Char);
}


SIGNAL(SIG_OVERFLOW0)
{
static unsigned char count = 0;
  TCNT0= 0xFF - 157;          // overflow at 10 mSec

if(count > 10) { // every 100ms
display_now = 1;
count = 0;
return;
}
count++;
}


void UART_Init(unsigned long BaudRate)
{
// Not Double mode, Not multi_communication
UCSRA = 0X00;
// 0b 1001 1000 RXCIE,TXCIE,UDRIE,RxEN,TxEN,xxx
UCSRB = 0X98;
UCSRC = 0X06;
// Setting BaudRate
UBRRH = 0X00;
UBRRL = (F_CPU/BaudRate/16 - 1);

}


int main()
{

asm volatile ("cli"); //disable all interrupts
  port_init();



  TCCR0=(1<<CS02)|(1<<CS00);  // Use maximum prescaller: Clk/1024
// 64us per 1 clk
  TCNT0= 0xFF - 157;          // overflow at 10 mSec
  TIMSK=(1<<TOIE0);            // Enable Counter Overflow Interrupt


UART_Init(9600);


 // Initial ATMega168 TWI/I2C Peripheral
  TWSR = 0x00;   // Select Prescaler of 1
  // SCL frequency = 11059200 / (16 + 2 * 48 * 1) = 98.743 khz
  TWBR = 0x30;   // 48 Decimal


  asm volatile ("sei"); //re-enable interrupts

fdevopen(SendByte, 0);
 
while(1) {
    // Read DS1307
if(display_now) {
display_now = 0;
   Read_DS1307();   
printf("%s,%s(%d:%d:%d)\r\n",weekday[ds1307_addr[3]],month[ds1307_addr[5]],ds1307_addr[2],ds1307_addr[1],ds1307_addr[0]);
}
}
return 1;
}