ATmega328PB i2c master mode example source
ATmega328PB에서 마스터 모드로 동작하는 i2c 예제 소스다.
i2c led 컨트롤용으로 만들었던 코드다.
급하게 만들어서 read 함수가 없다. 컨트롤용이라 write만...
datasheet를 보고 만들었다.
지금은 보드가 없어 read 함수 구현 테스트가 힘들다. 보드 생기면 구현해서
업데이트하자.
iic.h
#ifndef IIC_H_
#define IIC_H_
void iic_init(int ch);
int write_iic(int ch, int address, int *data, int len);
#endif /* IIC_H_ */
iic.c
#define F_CPU 8000000UL //
//#define F_CPU 16000000UL //
#include <math.h>
#include <stdlib.h>
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/twi.h>
#include <util/delay.h>
#include "iic.h"
#ifndef TWI_FREQ
#define TWI_FREQ 100000L
#endif
#define iic_timeout_ms 100
void iic_init(int ch)
{
if(ch == 0)
{
TWSR0 &= ~(1<<TWPS0);
TWSR0 &= ~(1<<TWPS1);
TWBR0 = ((F_CPU / TWI_FREQ) - 16)
/ 2;
}
else
{
TWSR1 &= ~(1<<TWPS0);
TWSR1 &= ~(1<<TWPS1);
TWBR1 = ((F_CPU / TWI_FREQ) - 16)
/ 2;
}
}
int iic_get_status_reg(int ch)
{
if(ch == 0)
{
return TWSR0&TW_STATUS_MASK;
}
return TWSR1&TW_STATUS_MASK;
}
void iic_set_control_reg(int ch, int val)
{
if(ch == 0)
{
TWCR0 = val;
}
else
{
TWCR1 = val;
}
}
int iic_get_control_reg(int ch, int mask)
{
if(ch == 0)
{
return TWCR0&mask;
}
return TWCR1&mask;
}
int iic_wait(int ch, int time_out_ms, int state)
{
int tick = 0;
do
{
if(iic_get_control_reg(ch,(1<<TWINT)))
{
break;
}
_delay_ms(1);
tick++;
} while (tick < time_out_ms);
if(iic_get_status_reg(ch) !=
state)
{
return -1;
}
return 0;
}
int iic_start(int ch)
{
int tick = 0;
int twi_status = 0;
iic_set_control_reg(ch,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN));
do
{
if(iic_get_control_reg(ch,(1<<TWINT)))
{
break;
}
_delay_ms(1);
tick++;
} while (tick<iic_timeout_ms);
twi_status
=iic_get_status_reg(ch);
if(twi_status == TW_START ||
twi_status == TW_REP_START)
{
return 0;
}
return -1;
}
void iic_stop(int ch)
{
iic_set_control_reg(ch,(1<<TWINT)|(1<<TWEN)|(1<<TWSTO));
}
void iic_send_data(int ch, char data)
{
if(ch == 0)
{
TWDR0 = data;
}
else
{
TWDR1 = data;
}
iic_set_control_reg(ch,(1<<TWINT)|(1<<TWEN));
}
int write_iic(int ch, int address, int *data, int len)
{
int i = 0;
if(!data) return -1;
// start
if(iic_start(ch) < 0)
{
return -1;
}
// address
iic_send_data(ch,address |
TW_WRITE);
if(iic_wait(ch,iic_timeout_ms,TW_MT_SLA_ACK) <0)
{
iic_stop(ch);
return -1;
}
//
for(i = 0; i<len;i++)
{
iic_send_data(ch,data[i]);
if(iic_wait(ch,iic_timeout_ms,TW_MT_DATA_ACK) <0)
{
iic_stop(ch);
return -1;
}
}
iic_stop(ch);
return 0;
}
[관련 포스트]
댓글
댓글 쓰기