witam,
napisałem dwa kody na obsługę i2c
master(atmega644p):
slave (attiny2313)
transmisja zaczyna się normalnie:
sda opada,
potem dołącza scl,
lecz address+rw z jakiegoś powodu to 0xff, oczywiście nie ma ack, a potem scl jest trzymane aż do zadziałania watchdoga i brakuje ramki stopu w i2c
napisałem dwa kody na obsługę i2c
master(atmega644p):
/*
* main.c
*
* Created on: 16 lut 2018
* Author: Mirosław Kardaś
* web: www.atnel.pl
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
// skompilowano dla F_CPU = 16 MHz
#include "usbdrv/usbdrv.h"
// usb user requests
enum {
cmd_cls,
cmd_cls1,
cmd_cls2,
cmd_locate,
cmd_text,
cmd_bck_on,
};
uint8_t data_length;
//---- led macros -----------
enum{
poczatek,
set_i2c_address,
set_e1,
set_e2,
set_v0,
_lcd_clear,
_display_on_off_control,
_set_cursor,
set_cgram_address,
set_bk,
wr_data_ee,
continue_ee,
przeplatane_adres_dane,
przeplatane_dane_adres,
wr_char_to_lcd,
modified_chars_wr,
dummy,
send_byte,
};
#define busy_flag 7
#define LCD_CLEAR 1
#define LCD_HOME 1<<1
#define LCDC_ENTRY_MODE 0x04
#define LCD_EM_SHIFT_CURSOR 0x00
#define LCD_EM_SHIFT_DISPLAY 0x01
#define LCD_EM_LEFT 0x00
#define LCD_EM_RIGHT 0x02
#define LCD_ONOFF 0x08
#define LCD_DISP_ON 0x04
#define LCD_CURSOR_ON 0x02
#define LCDC_CURSOR_OFF 0x00
#define LCDC_BLINK_ON 0x01
#define LCDC_BLINK_OFF 0x00
#define LCD_SHIFT 0x10
#define LCDC_SHIFT_DISP 0x08
#define LCDC_SHIFT_CURSOR 0x00
#define LCDC_SHIFT_RIGHT 0x04
#define LCDC_SHIFT_LEFT 0x00
#define LCD_FUNC 0x20
#define LCD_8_BIT 0x10
#define LCD_4_BIT 0x00
#define LCDC_TWO_LINE 0x08
#define LCDC_FONT_5x10 0x04
#define LCDC_FONT_5x7 0x00
#define LCDC_SET_CGRAM 0x40
#define LCDC_SET_DDRAM 0x80
#define initial_i2c (0 << TWINT) | (0 << TWEA) | (0 << TWWC) | (1 << TWEN) | (0 << TWIE)
#define stop_i2c TWCR = initial_i2c | TWSTO
#define end_of_first_line 0x10
#define end_of_second_line 0x50
const PROGMEM uint8_t do_pozycji[] = {
0x00,
0x40,
0x14,
0x54
};
unsigned char ADDRESS_slavea EEMEM = 0x11;
volatile uint8_t polozenie = 0;
volatile uint16_t Timer1, Timer2, Timer3;
volatile uint8_t obecna_komenda;
void red_on(void){
PORTD &= 1 << 5;
PORTD |= 1 << 7;
}
void green_on(void){
PORTD &= 1 << 7;
PORTD |= 1 << 5;
}
uint8_t wr_cmd_i2c (void){
uint8_t cnt1;
uint8_t cnt2 = 0;
TWCR = initial_i2c;
poczatek_cmd:
cnt2++;
if(cnt2 < 6){
cnt1 = 0;
TWCR = initial_i2c | (1 << TWSTA) | (1 << TWINT);
while(!(TWCR & (1 << TWINT))); //czekaj az zapali sie bit
cnt1++;
if((TWSR != 0x08) && (TWSR != 0x10)) goto poczatek_cmd;
cnt1 = 0;
do
{
TWDR = (0 << 7) | eeprom_read_byte(&ADDRESS_slavea);
TWCR = initial_i2c | (1 << TWINT);
while(!(TWCR & (1 << TWINT))); //czekaj az zapali sie bit
cnt1++;
if((TWSR == 0x38) || (cnt1 > 5)) goto poczatek_cmd;
} while ((TWCR & (1 << TWWC)) || (TWSR != 0x18));
cnt1 = 0;
do
{
TWDR = obecna_komenda;
TWCR = initial_i2c | (1 << TWINT);
while(!(TWCR & (1 << TWINT))); //czekaj az zapali sie bit
cnt1++;
if((TWSR == 0x38) || (cnt1 > 200)) goto poczatek_cmd;
} while ((TWCR & (1 << TWWC)) || (TWSR != 0x28));
return(1);
}
return(0);
}
uint8_t wr_byte_i2c (uint8_t dana){
uint8_t cnt1 = 0;
do
{
TWDR = dana;
TWCR = initial_i2c | (1 << TWINT);
while(!(TWCR & (1 << TWINT))); //czekaj az zapali sie bit
cnt1++;
if(TWSR == 0x28){
return(1);
}
if((TWSR == 0x38) || (cnt1 > 201)){
return(0);
}
} while (TWCR & (1 << TWWC));
return(0);
}
char ibf[] = "123ab678";
// nagłówek funkcji do wymuszenia renumeracji na usb
void usb_reset( void );
usbMsgLen_t usbFunctionSetup( uchar data[8] ) {
usbMsgLen_t len = 0;
usbRequest_t * urq = (usbRequest_t*)data;
switch( urq->bRequest ) {
case cmd_cls:
obecna_komenda = _lcd_clear;
if(wr_cmd_i2c()){
green_on();
}
else{
red_on();
}
stop_i2c;
break;
case cmd_cls1:
obecna_komenda = _set_cursor;
if(wr_cmd_i2c()){
green_on();
if(wr_byte_i2c(0x00)){
for( uint8_t i=0; i < 80; i++ ){
if(wr_byte_i2c(' ')){
green_on();
}
else{
red_on();
break;
}
}
}
else{
red_on();
}
}
else{
red_on();
}
stop_i2c;
break;
case cmd_cls2:
obecna_komenda = _set_cursor;
if(wr_cmd_i2c()){
green_on();
if(wr_byte_i2c(0x14)){
for( uint8_t i=0; i < 80; i++ ){
if(wr_byte_i2c(' ')){
green_on();
}
else{
red_on();
break;
}
}
}
else{
red_on();
}
}
else{
red_on();
}
stop_i2c;
break;
case cmd_locate:
if(urq->wValue.bytes[1] < 4){
obecna_komenda = _set_cursor;
if(wr_cmd_i2c()){
green_on();
if(wr_byte_i2c((urq->wValue.bytes[0]) + (pgm_read_byte(&do_pozycji[urq->wValue.bytes[1]])))){
green_on();
}
else{
red_on();
}
}
else{
red_on();
}
}
else{
obecna_komenda = set_v0;
if(wr_cmd_i2c()){
green_on();
if(wr_byte_i2c(urq->wValue.bytes[0])){
green_on();
}
else{
red_on();
}
}
else{
red_on();
}
}
stop_i2c;
break;
case cmd_text:
obecna_komenda = _set_cursor;
if(wr_cmd_i2c()){
green_on();
if(wr_byte_i2c((urq->wValue.bytes[0]) + (pgm_read_byte(&do_pozycji[urq->wValue.bytes[1]])))){
green_on();
}
else{
red_on();
}
}
else{
red_on();
}
return USB_NO_MSG; // ... ciąg dalszy w funkcji usbFunctionWrite()
break;
case cmd_bck_on:
obecna_komenda = set_bk;
if(wr_cmd_i2c()){
green_on();
}
else{
red_on();
}
if( urq->wValue.word ) {
if(wr_byte_i2c(128)){
green_on();
}
else{
red_on();
}
}
else {
if(wr_byte_i2c(0)){
green_on();
}
else{
red_on();
}
}
stop_i2c;
break;
}
return len;
}
uchar usbFunctionWrite( uchar * data, uchar len ) {
for(uint8_t a = 0; a < len; a++){
if(wr_byte_i2c(0)){
green_on();
}
else{
red_on();
break;
stop_i2c;
}
}
data_length -= len;
if( data_length <= 0 ){ // koniec
stop_i2c;
return 1;
}
else return 0; // oczekiwanie na kolejne dane
}
int main( void ) {
DDRD = (1 << 5) | (1 << 7);
PORTA = 0xff;
PORTB = 0xff;
PORTD = (1 << 0) | (1 << 1) | (1 << 6);
//i2c
TWBR = 3;
//i2c
wdt_enable(WDTO_1S); // aktywacja watchdoga na 1 s
// inicjalizacja sprzętowego Timera0
// do napędu timerów programowych
TCCR0A = (1<<WGM01);
TCCR0A |= (1<<CS02)|(1<<CS00);
TIMSK0 |= (1<<OCIE0A);
OCR0A = F_CPU/1024ul/100ul;
wdt_reset(); // resetuj watchdog
usbInit(); // inicjalizacja V-USB
// wymuszenie enumeracji urządzenia
usb_reset(); // reset urządzenia na magistrali USB
sei(); // globalne zezwolenie na przerwania
while(1) {
usbPoll(); // zdarzenie do obsługi USB
wdt_reset(); // resetuj watchdog
if( !Timer2 ) {
Timer2 = 100;
if( usbInterruptIsReady() ) {
usbSetInterrupt( (unsigned char*)ibf, 8 );
}
}
}
}
void usb_reset( void ) {
usbDeviceDisconnect();
uint8_t i = 0;
while(--i){ // odłączenie się do magistrali USB
wdt_reset(); // na czas większy niż ok 250 ms
_delay_ms(1); //
}
usbDeviceConnect();
}
// napęd timerów programowych
ISR( TIMER0_COMPA_vect, ISR_NOBLOCK ) {
uint16_t n;
n = Timer1;
if( n ) Timer1 = --n;
n = Timer2;
if( n ) Timer2 = --n;
n = Timer3;
if( n ) Timer3 = --n;
}
#ifdef WDIF
void __init3( void ) __attribute__ (( section( ".init3" ), naked, used ));
void __init3( void )
{
/* wyłączenie watchdoga (w tych mikrokontrolerach, w których watchdog
* ma możliwość generowania przerwania pozostaje on też aktywny po
* resecie) */
MCUSR = 0;
_WD_CONTROL_REG = 1 << _WD_CHANGE_BIT | 1 << WDE;
_WD_CONTROL_REG = 0;
}
#endifslave (attiny2313)
/*
* main.c
*
* Created on: 11 sie 2024
* Author: Dzieci
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include <avr/sleep.h>
#include <avr/pgmspace.h>
#define SCL_pin PB7
#define SDA_pin PB5
#define E1_pin PB6
#define E2_pin PB4
#define RS_pin PA1
#define RW_pin PA0
#define BK_pin PD4
#define V0_pin PD5
#define RST_pin PA2
//PB0 - PB3 - 4 mlodsze bity danych wyświetlacza
//PD0 - PD3 - 4 starsze bity danych wyświetlacza
#define SCL (1 << SCL_pin)
#define SDA (1 << SDA_pin)
#define E1 (1 << E1_pin)
#define E2 (1 << E2_pin)
#define RS (1 << RS_pin)
#define RW (1 << RW_pin)
#define BK (1 << BK_pin)
#define V0 (1 << V0_pin)
#define RST (1 << RST_pin)
#define RS_0 PORTA &= ~RS;
#define RS_1 PORTA |= RS;
#define E_1 PORTB |= E
#define E_0 PORTB ^= E
#define RW_0 PORTA &= ~RW;
#define RW_1 PORTA |= RW;
#define BK_0 PORTD &= ~BK;
#define BK_1 PORTD |= BK;
#define SDA_1 DDRB &= ~SDA;
#define SDA_0 DDRB |= SDA;
#define SCL_1 DDRB &= ~SCL;
#define SCL_0 DDRB |= SCL;
#define busy_flag 7
#define rw_twi 7
#define LCD_CLEAR 1
#define LCD_HOME 1<<1
#define LCDC_ENTRY_MODE 0x04
#define LCD_EM_SHIFT_CURSOR 0x00
#define LCD_EM_SHIFT_DISPLAY 0x01
#define LCD_EM_LEFT 0x00
#define LCD_EM_RIGHT 0x02
#define LCD_ONOFF 0x08
#define LCD_DISP_ON 0x04
#define LCD_CURSOR_ON 0x02
#define LCDC_CURSOR_OFF 0x00
#define LCDC_BLINK_ON 0x01
#define LCDC_BLINK_OFF 0x00
#define LCD_SHIFT 0x10
#define LCDC_SHIFT_DISP 0x08
#define LCDC_SHIFT_CURSOR 0x00
#define LCDC_SHIFT_RIGHT 0x04
#define LCDC_SHIFT_LEFT 0x00
#define LCD_FUNC 0x20
#define LCD_8_BIT 0x10
#define LCD_4_BIT 0x00
#define LCDC_TWO_LINE 0x08
#define LCDC_FONT_5x10 0x04
#define LCDC_FONT_5x7 0x00
#define LCDC_SET_CGRAM 0x40
#define LCDC_SET_DDRAM 0x80
////////////////////////////
enum{
poczatek,
set_i2c_address,
set_e1,
set_e2,
set_v0,
_lcd_clear,
_display_on_off_control,
_set_cursor,
set_cgram_address,
set_bk,
wr_data_ee,
continue_ee,
przeplatane_adres_dane,
przeplatane_dane_adres,
wr_char_to_lcd,
modified_chars_wr,
dummy,
send_byte,
};
enum {
wybrany,
przed_ack,
ack,
cgram,
dane,
dalszy,
czekanie_na_zmiane_polozenia,
rw_i2c,
};
const PROGMEM uint8_t const_lcd[] = {
0b0011 << 4,
(4100 + 19) / 20,
0b0011 << 4,
(100 + 19) / 20,
0b0011 << 4,
(37 + 19) / 20,
(1 << 5) | (1 << 4) | (1 << 3) | (0 << 2),
(37 + 19) / 20,
(1 << 3) | (1 << 2) | (0 << 1) | (0 << 0),
(37 + 19) / 20,
(1 << 2) | (1 << 1) | (0 << 0),
(37 + 19) / 20,
1,
(1520 + 19) / 20
}; // or this one 1
uint8_t v0_ee EEMEM; //najstarszy bit 0
uint8_t ADRRESS EEMEM = 0x11; //najstarszy bit 0
uint8_t duszki[5 * 8 * 2] EEMEM; //najstarszy bit 0
volatile uint8_t buf[40]; //najstarszy bit 0
volatile uint8_t do_przeslania;
volatile uint8_t lok_ee;
volatile uint8_t komenda;
volatile uint8_t polozenie;
volatile uint8_t E = E1 | E2;
volatile uint8_t BK_cnt;
volatile uint8_t BK_val;
volatile uint8_t i2c; /*bit0 - 0 avr niewybrany / 1 avr wybrany
bit 1 - 0 adres, 1 - dane
bi2 - 0 - dane /adres / 1 - ack
bit3 - 0 - brak nowych danych, 1 - nowe dane,*/
#define ACK_0 i2c &= ~(1 << ack)
#define ACK_1 i2c |= 1 << ack
#define wybrany_0 i2c &= ~(1 << wybrany)
#define wybrany_1 i2c |= 1 << wybrany
#define przed_ack_0 i2c &= ~(1 << przed_ack)
#define przed_ack_1 i2c |= 1 << przed_ack
#define cgram_0 i2c &= ~(1 << cgram)
#define cgram_1 i2c |= 1 << cgram
#define dane_0 i2c &= ~(1 << dane)
#define dane_1 i2c |= 1 << dane
#define dalszy_0 i2c &= ~(1 << dalszy)
#define dalszy_1 i2c |= 1 << dalszy
#define czekanie_na_zmiane_polozenia_0 i2c &= ~(1 << czekanie_na_zmiane_polozenia)
#define czekanie_na_zmiane_polozenia_1 i2c |= 1 << czekanie_na_zmiane_polozenia
#define czekanie_na_zmiane_polozenia_0 i2c &= ~(1 << czekanie_na_zmiane_polozenia)
#define rw_i2c_0 i2c &= ~(1 << rw_i2c)
#define rw_i2c_1 i2c |= 1 << rw_i2c
////////////////////////////
void piny_na_wyjscia (void){
DDRB |= 0xf;
DDRD |= 0xf;
}
void piny_na_wejscia(void){
DDRB &= ~0xf;
DDRD &= ~0xf;
PORTB &= ~0xf;
PORTD &= ~0xf;
}
void wr_byte (uint8_t a){
RW_0;
piny_na_wyjscia();
E_1;
PORTD = (PORTD & 0xf0) | (a >> 4);
PORTB = (PORTB & 0xf0) | (a & 0x0f);
_delay_us(1); // Krótkie opóźnienie
E_0;
}
void com (uint8_t a){
RS_0;
wr_byte(a);
}
void ustawienie_kursora (uint8_t a){
polozenie = a;
if ((a <= 0x13) || ((a <= 0x53) && (a >= 0x40))){
E = E1;
}
else{
E = E2;
}
com(LCDC_SET_DDRAM | a);
}
inline void lcd_char (uint8_t a){
RS_1;
wr_byte(a);
if(!(i2c & (1 << cgram))){
polozenie++;
do_przeslania++;
czekanie_na_zmiane_polozenia_1;
}
}
void przesuwanie_buf (void){
uint8_t a;
for(a = 0; a < (40 - 1); a++){
buf[a] = buf[a + 1];
}
}
void zapis_do_cgram (void){
uint8_t a;
uint8_t b;
for(a = 5, b = 0; a;){
a--;
b <<= 1;
b |= (buf[a]) >> (do_przeslania - 1) & 1;
}
lcd_char(b);
}
ISR(TIMER0_OVF_vect) { //soft pwm
wdt_reset(); // resetuj watchdog
if (BK_cnt >= 128) { //reset cyklu
BK_cnt = 0;
if (BK_val) BK_1; //jezeli nie zero
}
if (BK_cnt == BK_val) BK_0; //przy zrownaniu sie ustaw na 0
BK_cnt++;
USISR |= 1 << USIOIF;
}
ISR(USI_START_vect){
komenda = 0;
i2c &= ~((1 << ack) | (1 << przed_ack) | (1 << wybrany) | (1 << rw_i2c));
while(PINB & SCL);
USISR = 0xf0;
}
ISR(USI_OVERFLOW_vect) { //soft pwm
uint8_t a;
if(USISR & (1 << USIPF)){
USISR = 0xf0; //czyszczenie flag
i2c &= ~((1 << ack) | (1 << przed_ack) | (1 << wybrany) | (1 << rw_i2c));
komenda = 0;
}
else{
if(i2c & (1 << ack)){
SDA_1;
i2c &= ~((1 << ack) | (1 << przed_ack));
USISR = (1 << USIOIF) | 14; //czyszczenie flag
}
else{
if(i2c & (1 << przed_ack)){
if(!(i2c & (1 << rw_i2c))){
if(i2c & (1 << wybrany)){
if ((do_przeslania < 40) && ((!do_przeslania) || (komenda == send_byte) || (komenda == przeplatane_dane_adres) || (komenda == przeplatane_adres_dane))){
SDA_0;
do_przeslania++;
dalszy_0;
switch(komenda){
case poczatek:
komenda = USIDR;
switch(komenda){
case _lcd_clear:
polozenie = 0;
cgram_0;
E = E1 | E2;
com(LCD_CLEAR);
break;
case set_e1:
E = E1;
break;
case set_e2:
E = E2;
break;
}
komenda = dummy;
break;
case set_v0:
eeprom_update_byte(&v0_ee, USIDR);
OCR0B = USIDR;
break;
case przeplatane_adres_dane:
cgram_0;
if(do_przeslania){
buf[do_przeslania - 1] = USIDR;
}
else{
ustawienie_kursora(USIDR);
dane_1;
}
komenda = przeplatane_dane_adres;
break;
case przeplatane_dane_adres:
cgram_0;
if(do_przeslania){
buf[do_przeslania - 1] = USIDR;
}
else{
lcd_char(USIDR);
dane_0;
}
komenda = przeplatane_adres_dane;
break;
case set_i2c_address:
eeprom_update_byte(&ADRRESS, USIDR & (~(1 << rw_twi)));
komenda = dummy;
break;
case _display_on_off_control:
com(LCD_ONOFF | USIDR);
komenda = dummy;
break;
case set_bk:
BK_val = USIDR;
break;
case _set_cursor:
cgram_0;
ustawienie_kursora(USIDR);
komenda = send_byte;
break;
case set_cgram_address:
cgram_1;
com(LCDC_SET_CGRAM | USIDR);
komenda = send_byte;
break;
case wr_data_ee:
lok_ee = USIDR;
komenda = continue_ee;
break;
case continue_ee:
eeprom_update_byte(&duszki[lok_ee], USIDR);
lok_ee++;
if(lok_ee >= (5 * 8 * 2)){
lok_ee = 0;
}
break;
case wr_char_to_lcd:
cgram_1;
dane_0;
lok_ee = USIDR;
do_przeslania = 8;
eeprom_read_block(&duszki[lok_ee], buf, 5);
eeprom_busy_wait();
lok_ee += 5;
zapis_do_cgram();
break;
case dummy:
SDA_1;
break;
default:
if(do_przeslania){
buf[do_przeslania - 1] = USIDR;
}
else{
lcd_char(USIDR);
}
dalszy_1;
}
}
}
else{
if (eeprom_read_byte(&ADRRESS) == (USIDR & (~(1 << rw_twi)))){
SDA_0;
if(USIDR & (1 << rw_twi)){
rw_i2c_1;
}
else{
rw_i2c_0;
}
wybrany_1;
}
}
i2c ^= (1 << ack) | (1 << przed_ack);
USISR = (1 << USIOIF) | 14; //czyszczenie flag
}
}
else{
if(i2c & (1 << rw_i2c)){
USICR = (1 << USISIE) | (1 << USIOIE) | (1 << USIWM1) | (0 << USIWM0) | (0 << USICS1) | (0 << USICS0) | (0 << USICLK);
if(do_przeslania == 0){
USIDR = OCR0B;
}
else if(do_przeslania == 1){
USIDR = BK_val;
}
else{
USIDR = eeprom_read_byte(&duszki[lok_ee]);
lok_ee++;
}
for(a = 0; a < 8; a++){
USICR = (1 << USISIE) | (1 << USIOIE) | (1 << USIWM1) | (0 << USIWM0) | (0 << USICS1) | (0 << USICS0) | (1 << USICLK);
while(!(PINB & (1 << PB7))); //czekaj na wznios linii
while(PINB & (1 << PB7)); //czekaj na opadniecie linii
}
USICR = (1 << USISIE) | (1 << USIOIE) | (1 << USIWM1) | (0 << USIWM0) | (1 << USICS1) | (1 << USICS0) | (0 << USICLK);
do_przeslania++;
ACK_1;
}
przed_ack_1;
USISR = (1 << USIOIF) | 0; //czyszczenie flag
}
}
}
}
int main (void){
uint8_t a;
uint8_t b;
uint8_t c;
DDRB = E1 | E2;
DDRA = RS | RW;
PORTA = RST;
DDRD = BK | V0;
wdt_enable(WDTO_60MS); // aktywacja watchdoga na 1 s
sei();
ACSR = 1 << ACD;
TCCR0A = (1 << COM0B1) | (0 << COM0B0) | (1 << WGM01) | (1 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (0 << CS01) | (1 << CS00);
TIMSK = (0 << OCIE0A) | (0 << OCIE0B) | (1 << TOIE0);
USICR = (1 << USISIE) | (1 << USIOIE) | (1 << USIWM1) | (0 << USIWM0) | (1 << USICS1) | (1 << USICS0) | (0 << USICLK);
OCR0B = eeprom_read_byte(&v0_ee);
set_sleep_mode(SLEEP_MODE_IDLE);
//LCD INIT
piny_na_wyjscia();
_delay_ms(15);
for (a = 0; a < sizeof(const_lcd); a++){
wr_byte(pgm_read_byte((&const_lcd) + a));
a++;
c = (pgm_read_byte((&const_lcd) + a));
for(b = 0; b < c; b++){
_delay_us(20);
}
}
E = E1;
while(1){
if(do_przeslania){
if(E == (E1 | E2)){ //jeżeli przesłano wyczyśc ekran
E = E1;
_delay_us(1520);
do_przeslania = 0;
}
else{
piny_na_wejscia();
RS_0;
RW_1;
cli();
E_1;
_delay_us(1); // Krótkie opóźnienie
if(!(((1 << busy_flag) >> 4) & PIND)){
do_przeslania--;
if(do_przeslania){
if(i2c & (1 << czekanie_na_zmiane_polozenia)){
czekanie_na_zmiane_polozenia_0;
switch (polozenie) {
case (0x13 + 1):
ustawienie_kursora(0x40);
break;
case (0x53 + 1):
ustawienie_kursora(0x14);
break;
case (0x27 + 1):
ustawienie_kursora(0x54);
break;
case (0x67 + 1):
ustawienie_kursora(0x00);
break;
}
}
else{
if(i2c & (1 << cgram)){
zapis_do_cgram();
}
else{
if(i2c & (1 << dalszy)) lcd_char(buf[0]);
else if ((i2c & (1 << dane))){
lcd_char(buf[0]);
dane_0;
}
else{
ustawienie_kursora(buf[0]);
dane_1;
}
}
przesuwanie_buf();
}
}
sei();
}
E_0;
RW_0;
}
}
//czytaj flage
else{
cli();
if(eeprom_is_ready()){
sleep_enable();
sei();
sleep_cpu();
sleep_disable();
}
sei();
}
}
}
transmisja zaczyna się normalnie:
sda opada,
potem dołącza scl,
lecz address+rw z jakiegoś powodu to 0xff, oczywiście nie ma ack, a potem scl jest trzymane aż do zadziałania watchdoga i brakuje ramki stopu w i2c