logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Rozwiązano] I2C na ATmega644P: Kod Master nie działa poprawnie, co może być przyczyną?

NewTornus 18 Sie 2024 13:51 246 5
REKLAMA
  • #1 21194939
    NewTornus
    Poziom 7  
    witam,
    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;
        }
    #endif

    slave (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
  • REKLAMA
  • #2 21195542
    excray
    Poziom 41  
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #3 21196017
    ex-or
    Poziom 28  
    NewTornus napisał:
    napisałem

    Ty czy Kardaś? ;-)

    Mam poważne wątpliwości czy kombinacja softwareowego USB i synchronicznego (busy waits!) TWI ma szansę zadziałać.
  • REKLAMA
  • #4 21196031
    NewTornus
    Poziom 7  
    ex-or napisał:
    Ty czy Kardaś?

    No ta w zasadzie popodmieniałem nazwy komend w przypadku mastera, ale w tym przykładzie nie ma dużo więcej do roboty, jak uda się stworzyć własną apkę na kompa to trochę pozmieniam (dodam więcej case'ów xd).

    Dużym problemem było to, że nie zaznaczyłem zapisu eepromu w eclipse, ale nadal są błędy
    teraz już chyba tylko po stronie slave'a:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Dodano po 8 [minuty]:

    Jak debugować programowo sprzętowo takie gównienko jak attiny2313?
  • REKLAMA
  • #5 21203863
    NewTornus
    Poziom 7  
    ex-or napisał:
    Mam poważne wątpliwości czy kombinacja softwareowego USB i synchronicznego (busy waits!) TWI ma szansę zadziałać.

    Chyba faktycznie te synchroniczne i2c nie działa, bo mi się rozłącza z usb. już się bawię z isr:
    nwm o co chodzi z tym attiny ale mi hardware nie działał choćbym się zesrał, ostatecznie na scl dałem mniej więcej taki Schemat obwodu z tranzystorami i rezystorami, pokazujący napięcia i połączenia. układzik
    warto by dodać jeszcze mosfeta, żeby wykrywał zerowanie resetu przez programator i nie musiał go odlutowywać na czas programowania, ale to inna sprawa.
    kod na slave ostatecznie mi wyszedł taki, jeszcze nie do końca sprawdzony bo teraz master mi się z usb rozłącza:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
REKLAMA