Answer the question
In order to leave comments, you need to log in
Can't run I2C(TWI) on ATmega88 controller?
soldered ATmega88PA breadboard ,
here is a C program in AVRStudio 5.0 that is flashed into it (I make a slave)
#define F_CPU 12000000UL // 1MHz - по умолчанию выставлено в железе
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define ME_ADDR 8 //0b00001000
#define LED_ON 1
#define LED_OFF 2
unsigned char data, flag_new_data=0, status_led=0, stat; ///
unsigned short tek_delay, ddelay=5000;
unsigned char I2C_GetStatus(void) { //чтение статуса
unsigned char status; //переменная хранения
status = TWSR & 0xF8; //маска
return status;
}
void I2C_Init (void) { //инициализация I2C как приемника
TWAR=ME_ADDR;// адрес для обращения
TWCR=(1<<TWEA)//разрешаем подтверждение
|(1<<TWEN)//включаем модуль TWI
|(1<<TWIE)//разрешаем прерывание
|(0<<TWSTA) // формирeт старт // это типа для мастера
|(0<<TWSTO) // сделать Stop.
|(1<<TWINT); // флаг прерывания. Сброс его означает что конечный автомат провернется дальше, а прерывание будет снова уловлено
}
ISR(TWI_vect) {
stat=I2C_GetStatus();
if((stat==0x80) || (stat==0x88)) { //пришли данные от ведущего (0x80 - приняли очередной байт, 0х88 - приняли последний байт)
data=TWDR; ///читаем значение
flag_new_data=1;
}
TWCR|=(1<<TWINT); //сбрасываем флаг
//TWCR = (0<<TWSTA)|
// (0<<TWSTO)|
// (1<<TWINT)|
// (1<<TWEA)| // Enable ACK. Разрешение ответа ACK. Если его включить, то автомат TWI будет отзываться на свой адрес, а также давать ACK во всех случаях когда этого требует протокол. Скажем, после прием байта. Если нам надо послать NACK то бит не ставим.
// (1<<TWEN)|
// (1<<TWIE);
}
void set_led(short set_l){
if(set_l==LED_OFF) { // Setting pin PC0 low in order to turn off LED.
PORTC &= ~(1 << PORTC0);
return;
}
if(set_l==LED_ON) { //Setting pin PC0 high in order to turn on LED.
PORTC |= (1 << PORTC0);
}
}
int main(void)
{
DDRC = 0x1; // делаем PC0 - output
set_led(LED_ON);
_delay_ms(2000);
set_led(LED_OFF);
_delay_ms(2000);
I2C_Init();//инициализация модуля
sei();//разрешение глобальных прерываний
while(1){
if(tek_delay < ddelay) {
tek_delay++;
_delay_ms(1);
}
else {
if(status_led==0) {
set_led(LED_ON);
tek_delay=0;
status_led=1;
}
else {
set_led(LED_OFF);
tek_delay=0;
status_led=0;
}
}
if(flag_new_data==1){
flag_new_data=0;
if(data==23) {
ddelay=300;
tek_delay=0;
}
if(data==114) {
ddelay=1000;
tek_delay=0;
}
}
}
}
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question