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

[ATTiny2313][ASM][AVRstudio] interface z attiny2313

Ranma 25 Wrz 2010 10:55 4380 27
  • #1 8548184
    Ranma
    Poziom 12  
    Wiem że ten temat był już wielokrotnie poruszany przeszukałem forum wielokrotnie nie pomogło mi to ani wujek Google. Pracuje nad tym już długo, za długo.

    Przyjmę każdą radę nawet jak pracować.
    Forum zwracam się do Was bo nie wiem jak to zrobić.

    moim zadaniem jest napisanie interface dla DS1302 z attiny2313 w Asemblerze

    Problem:
    Jednak przy próbie odczytania danych zawsze dostaje same jedynki.
    Próbowałem już napisać flagę zapisu (WP) i nadal tak to wygląda.

    opisałem każdy krok zmagań tu: Link


    oto schemat podłączenia:
    [ATTiny2313][ASM][AVRstudio] interface z attiny2313

    interpretacja analizy stanów logicznych:
    [ATTiny2313][ASM][AVRstudio] interface z attiny2313

    interpretacja analizy stanów logicznych + timming:
    [ATTiny2313][ASM][AVRstudio] interface z attiny2313

    najnowsza analiza stanów:
    [ATTiny2313][ASM][AVRstudio] interface z attiny2313

    
    .NOLIST                                     ; wyłączenie z raportu z kompilacji
    .INCLUDE    "2313def.inc"         ; dołączonego pliku AT90S2313def.inc
    
    .equ DS1302_Port	= PORTB
    .equ DS1302_CE		= 0
    .equ DS1302_IO		= 1
    .equ DS1302_SCLK	= 2
    
    .list
    .listmac
    
    
    ;-----------------------------------------------------------------------------
    .cseg
    
    
    .org	0
    rjmp	ResetProcessor		;
    
    ;-----------------------------------------------------------------------------
    ResetProcessor	:			;
    	cli				;
    	ldi	r16,LOW(RAMEND)	;
    	out	SPL,r16			;
    rjmp	Main		;  powrot do petli
    
    	
    InitDS1302:
    
    	cbi DS1302_Port,DS1302_SCLK		;LOW (stan niski) == cbi PORTB,PORTB2
    	cbi DS1302_Port,DS1302_IO		;LOW (stan niski) == cbi PORTB,PORTB1
    	cbi DS1302_Port,DS1302_CE		;LOW (stan niski) == cbi PORTB,PORTB0
    	
    	sbi DS1302_Port-1,DS1302_SCLK	;output	 == sbi DDRB,DDB2
    	sbi DS1302_Port-1,DS1302_IO		;output	 == sbi DDRB,DDB1
    	sbi DS1302_Port-1,DS1302_CE		;output	 == sbi DDRB,DDB0
    	
    ret	
    
    wait:
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    ret
    
    
    ;wysyłanie polecenia
    	;r16
    SendCode_COMMAND:
    
    
    	CBI DS1302_Port,DS1302_SCLK	;OFF
    
    	;ustaw linie
    	SBRS	r16,0				;jeżeli bit jest wyzerowany
    	CBI DS1302_Port,DS1302_IO	;wyzeruj
    
    	SBRC	r16,0				;jeżeli bit jest ustawiony
    	SBI DS1302_Port,DS1302_IO	;to go ustaw
    	;--------------
    
    	;przesun bity w prawo(ten już wysłano)
    	LSR r16
    	;----------
    
    
    	SBI DS1302_Port,DS1302_SCLK	;ON
    
    	;czekaj
    	rcall wait;	
    	;----------
    
    			;TU DE1302 odczytuje dane
    
    	;czekaj
    	rcall wait;
    	;----------
    
    
    	;czekaj
    	rcall wait;
    	;----------
    
    			;koniec odczytu
    
    
    	CBI DS1302_Port,DS1302_IO	;czyść stan linie
    
    ret
    
    
    
    
    ;TODO - nie testowane
    ;pobieranie danych
    	;r17
    GetCode_DATA:
    	
    
    	CBI DS1302_Port,DS1302_SCLK	;OFF
    	
    
    	;tu ds1302 ustawia wartość
    
    
    	in r17,PINB; todo: zamien na DS1302_Port-??
    
    	;czytaj
    	SBRS	r17,DS1302_IO				;jeżeli bit jest wyzerowany
    	CBR r16,7	;wyzeruj
    
    	SBRC	r17,DS1302_IO				;jeżeli bit jest ustawiony
    	SBR r16,7	;to go ustaw
    	;--------------
    
    	;przesun bity w prawo(ten już wysłano)
    	LSL r16
    	;----------
    
    
    	SBI DS1302_Port,DS1302_SCLK	;ON
    
    	;czekaj
    	rcall wait;
    	;----------
    
    	;czekaj
    	rcall wait;
    	;----------
    
    ret
    ;---------------
    ;wysyła się od tyłu
    	;r16 - command
    	;r17 - data
    WriteData:
    
    	SBI DS1302_Port,DS1302_CE	;ON - transmisja rozpoczeta
    
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    
    		nop ; nic nie porzeba
    
    		mov r16,r17
    		
    
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    
    ret
    
    ;odczyt danych
    	;r16
    	;r17
    ReadData:
    
    	SBI DS1302_Port,DS1302_CE	;ON - transmisja rozpoczeta
    
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    		rcall SendCode_COMMAND;
    
    		clr r16
    			;cbi DS1302_Port,	DS1302_IO		;LOW (stan niski) == cbi PORTB,PORTB1
    			cbi PINB,	DS1302_IO				;PINB 
    			cbi DS1302_Port-1,	DS1302_IO		;DDRB
    
    		rcall GetCode_DATA;
    		rcall GetCode_DATA;
    		rcall GetCode_DATA;
    		rcall GetCode_DATA;
    		rcall GetCode_DATA;
    		rcall GetCode_DATA;
    		rcall GetCode_DATA;
    		rcall GetCode_DATA;
    
    
    	CBI DS1302_Port,DS1302_CE	;OFF - transmisja zakończone
    ret
    
    
    ;ustala czy czytamy czy zapisujemy
    	;r16
    	;r17
    ;jeżeli BIT0 w r16 HI  - odczyt
    ;jeżeli BIT0 w r16 LOW - zapis
    SendCode:
    
    	rcall InitDS1302
    
    		SBRS	r16,0
    		rcall WriteData
    		SBRC	r16,0
    		rcall ReadData
    
    	rcall InitDS1302;CBI DS1302_Port,DS1302_CE	;OFF - transmisja zakonczona
    ret
    
    
    ;-----------------------------------------------------------------------------
    Main:
    
    
    	;flaga zapisu (ustaw na 0)
    		;moge zapisywac zmiany
    	ldi r16,0x8E;   0b10001110
    	ldi r17,0b00000000
    		rcall SendCode
    	;-------------------------
    
    Main2:
    	;odczytaj flage zapisu
    	;---------------------------
    	ldi r16,0x8F;
    		rcall SendCode
    	;-------------------------
    
    
    	;czekaj---------------------
    	rcall wait
    	rcall wait
    	rcall wait
    	;-------------------------
    
    rjmp  Main2
    ;-----------------------------------------------------------------------------
    .exit
    
  • Pomocny post
    #2 8548483
    Andrzej__S
    Poziom 28  
    Nie mam w tej chwili czasu na analizowanie całego kodu, ale na początek mialbym kilka uwag:
    
    
    ; jak już piszesz coś takiego
    .equ DS1302_Port   = PORTB
    
    ; to pod spodem dodaj np.
    .equ DS1302_DDR   = DDRB
    .equ DS1302_PIN   = PINB
    
    ; nie używaj takich konstrukcji
    
       sbi DS1302_Port-1, DS1302_SCLK
    
    ; bo po co się domyślać, co się znajduje pod adresem o 1 mniejszym
    ; od adresu portu B
    
    ; nie lepiej napisać zamiast tego
    
       sbi DS1302_DDR, DS1302_SCLK ;???
    
    ; dobrze jest także zdefiniować sobie rejestry przykładowo w ten sposób
    
    .def byte_to_send  = r16 ; bajt do wysłania
    .def received_byte = r17 ; odebrany bajt
    .def i             = r18 ; iterator
    .def command       = r19 ; bajt zawierający instrukcję
    .def data          = r 20 ; bajt zawierający dane
    
    ; i później używać np.
       mov byte_to_send, command
    
    ; zamiast np.
       mov r16, r17
    
    

    Taki zapis znacznie ułatwia analizowanie kodu. Jeśli oczekujesz, że ktoś będzie chciał Tobie pomóc, postaraj się maksymalnie mu to ułatwić.

    Nazwa procedury SendCode_COMMAND jest myląca. Ta procedura wysyła pojedynczy bit, a nie "COMMAND". Poza tym zamiast pisać:
    
          rcall SendCode_COMMAND; 
          rcall SendCode_COMMAND; 
          rcall SendCode_COMMAND; 
          rcall SendCode_COMMAND; 
          rcall SendCode_COMMAND; 
          rcall SendCode_COMMAND; 
          rcall SendCode_COMMAND; 
          rcall SendCode_COMMAND;
    

    lepiej byłoby napisać procedurę (SendCode_COMMAND), która w pętli wysyła cały bajt danych.

    Jak już naopisałem, nie analizowałem dokładnie kodu, ale zastanawiam się, co chciałeś osiągnąć pisząc (w procedurze ReadData):
    
             cbi PINB,   DS1302_IO            ;PINB
    

    Tego typu instrukcji używa się raczej w odniesieniu do PORTx, a nie PINx. Wpisywanie (ustawianie) wartości do PINx może powodować problemy.

    Odnośnie schematu. Nie narysowałeś, jak jest zasilany mikrokontroler. Z tego samego napięcia? Jeśli z innego, to czy te napięcia są takie same? Masy ("minusy") napięć zasilających są ze sobą połączone?

    Jak znajdę więcej czasu, to jeszcze tu zajrzę. Tymczasem może przemyśl to, co teraz napisałem.
  • #3 8548662
    Ranma
    Poziom 12  
    zastosowałem się do rad:

    
    .NOLIST                                     ; wyłączenie z raportu z kompilacji
    .INCLUDE    "2313def.inc"         ; dołączonego pliku AT90S2313def.inc
    
    .equ DS1302_Port	= PORTB
    .equ DS1302_CE		= 0
    .equ DS1302_IO		= 1
    .equ DS1302_SCLK	= 2
    
    .list
    .listmac
    
    
    ;-----------------------------------------------------------------------------
    .cseg
    
    
    .org	0
    rjmp	ResetProcessor		;
    
    ;-----------------------------------------------------------------------------
    ResetProcessor	:			;
    	cli				;
    	ldi	r16,LOW(RAMEND)	;
    	out	SPL,r16			;
    rjmp	Main		;  powrot do petli
    
    	
    DS1302_INIT:
    
    	cbi DS1302_Port,DS1302_SCLK		;LOW (stan niski) == cbi PORTB,PORTB2
    	cbi DS1302_Port,DS1302_IO		;LOW (stan niski) == cbi PORTB,PORTB1
    	cbi DS1302_Port,DS1302_CE		;LOW (stan niski) == cbi PORTB,PORTB0
    	
    	sbi DS1302_Port-1,DS1302_SCLK	;output	 == sbi DDRB,DDB2
    	sbi DS1302_Port-1,DS1302_IO		;output	 == sbi DDRB,DDB1
    	sbi DS1302_Port-1,DS1302_CE		;output	 == sbi DDRB,DDB0
    	
    ret	
    
    ;wysyłanie polecenia
    	;r16
    DS1302_INPUT_COMMAND_BYTE:
    
    
    	CBI DS1302_Port,DS1302_SCLK	;OFF
    
    	;ustaw linie
    	SBRS	r16,0				;jeżeli bit jest wyzerowany
    	CBI DS1302_Port,DS1302_IO	;wyzeruj
    
    	SBRC	r16,0				;jeżeli bit jest ustawiony
    	SBI DS1302_Port,DS1302_IO	;to go ustaw
    	;--------------
    
    	;przesun bity w prawo(ten już wysłano)
    	LSR r16
    	;----------
    
    
    	SBI DS1302_Port,DS1302_SCLK	;ON
    
    	;czekaj
    	rcall wait;	
    	;----------
    
    			;TU DE1302 odczytuje dane
    
    	;czekaj
    	rcall wait;
    	;----------
    
    
    	;czekaj
    	rcall wait;
    	;----------
    
    			;koniec odczytu
    
    
    	CBI DS1302_Port,DS1302_IO	;czyść stan linie
    
    ret
    
    
    
    
    ;TODO - nie testowane
    ;pobieranie danych
    	;r17
    DS1302_OUTPUT_DATA_BYTE:
    	
    
    	CBI DS1302_Port,DS1302_SCLK	;OFF
    	
    
    	;tu ds1302 ustawia wartość
    
    
    	in r17,PINB; todo: zamien na DS1302_Port-??
    
    	;czytaj
    	SBRS	r17,DS1302_IO				;jeżeli bit jest wyzerowany
    	CBR r16,7	;wyzeruj
    
    	SBRC	r17,DS1302_IO				;jeżeli bit jest ustawiony
    	SBR r16,7	;to go ustaw
    	;--------------
    
    	;przesun bity w prawo(ten już wysłano)
    	LSL r16
    	;----------
    
    
    	SBI DS1302_Port,DS1302_SCLK	;ON
    
    	;czekaj
    	rcall wait;
    	;----------
    
    	;czekaj
    	rcall wait;
    	;----------
    
    ret
    ;---------------
    ;wysyła się od tyłu
    	;r16 - command
    	;r17 - data
    DS1302_WriteData:
    
    	SBI DS1302_Port,DS1302_CE	;ON - transmisja rozpoczeta
    
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    
    		nop ; nic nie porzeba
    
    		mov r16,r17
    		
    
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    
    ret
    
    ;odczyt danych
    	;r16
    	;r17
    DS1302_ReadData:
    
    	SBI DS1302_Port,DS1302_CE	;ON - transmisja rozpoczeta
    
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    		rcall DS1302_INPUT_COMMAND_BYTE
    
    		clr r16
    			;cbi DS1302_Port,	DS1302_IO		;LOW (stan niski) == cbi PORTB,PORTB1
    			cbi PINB,	DS1302_IO				;PINB 
    			cbi DS1302_Port-1,	DS1302_IO		;DDRB
    
    		rcall DS1302_OUTPUT_DATA_BYTE
    		rcall DS1302_OUTPUT_DATA_BYTE
    		rcall DS1302_OUTPUT_DATA_BYTE
    		rcall DS1302_OUTPUT_DATA_BYTE
    		rcall DS1302_OUTPUT_DATA_BYTE
    		rcall DS1302_OUTPUT_DATA_BYTE
    		rcall DS1302_OUTPUT_DATA_BYTE
    		rcall DS1302_OUTPUT_DATA_BYTE
    
    
    	CBI DS1302_Port,DS1302_CE	;OFF - transmisja zakończone
    ret
    
    
    ;ustala czy czytamy czy zapisujemy
    	;r16
    	;r17
    ;jeżeli BIT0 w r16 HI  - odczyt
    ;jeżeli BIT0 w r16 LOW - zapis
    DS1302_SendCode:
    
    	rcall DS1302_Init
    
    		SBRS	r16,0
    		rcall DS1302_WriteData
    		SBRC	r16,0
    		rcall DS1302_ReadData
    
    	rcall DS1302_Init;CBI DS1302_Port,DS1302_CE	;OFF - transmisja zakonczona
    ret
    
    
    ;odczekaj
    wait:
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    	nop	nop
    ret
    
    ;-----------------------------------------------------------------------------
    Main:
    
    
    	;flaga zapisu (ustaw na 0)
    		;moge zapisywac zmiany
    	ldi r16,0x8E;   0b10001110
    	ldi r17,0b00000000
    		rcall DS1302_SendCode
    	;-------------------------
    
    Main2:
    	;odczytaj flage zapisu
    	;---------------------------
    	ldi r16,0x8F;
    		rcall DS1302_SendCode
    	;-------------------------
    
    
    	;czekaj---------------------
    	rcall wait
    	rcall wait
    	;-------------------------
    
    rjmp  Main2
    ;-----------------------------------------------------------------------------
    .exit
    
    
  • #4 8549683
    Andrzej__S
    Poziom 28  
    Ranma napisał:

    zastosowałem się do rad:


    Naprawdę?
    Moim zdaniem, albo nie przeczytałeś uważnie tego, co napisałem, albo nie zrozumiałeś.
    Jeżeli nie przeczytałeś dokładnie to przeczytaj jeszcze raz. Chyba nie oczekujesz, że ja napiszę ten program za Ciebie?
    Jeżeli czegoś mie zrozumiałeś, to się nie wstydź, tylko po prostu zapytaj.

    Z tego, co zauważyłem to chyba tylko zmieniłeś nazwę procedury z SendCode_COMMAND na DS1302_INPUT_COMMAND_BYTE, i wcale nie o to chodziło, bo to nadal jest wysyłanie jednego bitu, a nie całego bajtu. Mam wrażenie, że resztę moich sugestii zignorowałeś.
  • #5 8550208
    Ranma
    Poziom 12  
    zmieniłem na

    
    rcall DS1302_INPUT_COMMAND_BYTE 
    rcall DS1302_OUTPUT_DATA_BYTE
    


    bo tak to jest nazywane w dokumentacji "COMMAND BYTE" i "DATA BYTE".

    co do


    to mam to z "Mikrokontrolery AVR ATtiny w praktyce" - Rafał baranowski:

    Przykład 2.2 Konfiguracje Lini w trybie wyjściowym i jego odwracanie
    
    sbi DDRA,DDA2
    cbi PORTA,PORTA2
    sbi PINA,PINA2
    
  • #6 8550419
    Andrzej__S
    Poziom 28  
    Ranma napisał:

    co do



    to mam to z "Mikrokontrolery AVR ATtiny w praktyce" - Rafał baranowski:

    Przykład 2.2 Konfiguracje Lini w trybie wyjściowym i jego odwracanie
    
    sbi DDRA,DDA2
    cbi PORTA,PORTA2
    sbi PINA,PINA2
    


    Zauważ tylko różnicę, że tutaj jest sbi, a nie cbi. Chyba trochę źle zrozumiałeś, co robi ten kod. W kodzie poniżej opisałem, co robią poszczególne instrukcje.
    
    sbi DDRA,DDA2       ; ustawia pin 2 portu A jako wyjście
    cbi PORTA,PORTA2    ; zeruje pin 2 portu A
    sbi PINA,PINA2      ; odwraca wartość pinu 2 portu A
                        ; ponieważ przedtem na pinie 2 było 0
                        ; to teraz będzie 1
    sbi PINA,PINA2      ; jeżeli teraz napiszesz drugi raz to samo
                        ; wartość pinu 2 zmieni się z powrotem z 1 na 0
    

    W Twoim kodzie to nie za bardzo ma zastosowanie. Prawdopodobnie chciałeś ustawić wyjście na 0, więc powinieneś odwołać się do PORTx, a nie do PINx.

    Ranma napisał:

    bo tak to jest nazywane w dokumentacji "COMMAND BYTE" i "DATA BYTE".

    Nadal mnie nie rozumiesz. Nazywasz procedurę w stylu Send_BYTE, a tak naprawdę ta procedura nie wysyła całego bajtu tylko jeden bit. Później wywołujesz ją osiem razy, żeby wysłać cały bajt.

    Oczywiście to nie ma znaczenia, jak nazwiesz procedurę. Jeżeli napisana jest prawidłowo, będzie działać niezależnie od nazwy. Chodzi tylko o to, że kiedy ktoś inny będzie analizował ten kod (lub nawet Ty sam po jakimś czasie), ta nazwa może wprowadzać w błąd.

    Właściwie to najlepiej byłoby nie zmieniać nazwy, tylko tak przerobić procedurę tak, żeby faktycznie wysyłała od razu cały bajt.
  • #7 8550500
    Ranma
    Poziom 12  
    Dla mnie bardzo istotne jest jak się nazywa procedura teraz o co z tym chodziło rozumiem:)

    ah! rozumiałem, poprawie i zdam raport.

    Odczytałem Pana wiadomość, dziękuje nie robię to sam dla siebie z ambicji i fascynacji dlatego pisze to ASM żeby dokładnie wszystko zrozumieć:)
  • #8 8550548
    sulfur
    Poziom 24  
    Andrzej__S napisał:
    
    sbi DDRA,DDA2       ; ustawia pin 2 portu A jako wyjście
    cbi PORTA,PORTA2    ; zeruje pin 2 portu A
    sbi PINA,PINA2      ; odwraca wartość pinu 2 portu A
                        ; ponieważ przedtem na pinie 2 było 0
                        ; to teraz będzie 1
    sbi PINA,PINA2      ; jeżeli teraz napiszesz drugi raz to samo
                        ; wartość pinu 2 zmieni się z powrotem z 1 na 0
    



    Obawiam się, że się kolega myli. Instrukcja sbi ustawia bit, a nie odwraca jego stan. Do odwracania stanu służy alternatywa wykluczająca. W związku z tym moim zdaniem linijka czwarta nie będzie miała żadnego pożytecznego efektu.
  • #9 8550557
    Andrzej__S
    Poziom 28  
    ATtiny2313 datasheet napisał:

    However, writing a logic one to a bit in the PINx Register, will result in a toggle in the corresponding bit in the Data Register.
  • #10 8550586
    Ranma
    Poziom 12  
    zamieniłem:
    DS1302_INPUT_COMMAND_BYTE

    na
    DS1302_SEND_BIT


    oraz:
    DS1302_OUTPUT_COMMAND_BYTE

    na



    nowa procedura odczytu:
    
    DS1302_ReadData:
    
    	SBI DS1302_Port,DS1302_CE	;ON - transmisja rozpoczeta
    
    		;COMMAND BYTE
    		rcall DS1302_SEND_BIT; BIT0 (R/W)
    		rcall DS1302_SEND_BIT; BIT1 (A0)
    		rcall DS1302_SEND_BIT; BIT2 (A1)
    		rcall DS1302_SEND_BIT; BIT3 (A2)
    		rcall DS1302_SEND_BIT; BIT4 (A3)
    		rcall DS1302_SEND_BIT; BIT5 (A4)
    		rcall DS1302_SEND_BIT; BIT6 (R/C)
    		rcall DS1302_SEND_BIT; BIT7 ('1')
    		;_________________________
    
    		clr r16
    
    			;przygotowanie do odczytu
    			cbi PORTB,	PORTB1    ; zeruje pin 2 portu A
    			cbi DDRB,  DDB1       ; ustawia pin 2 portu A jako wyjście 
    			
    		;DATA BYTE
    		rcall DS1302_GET_BIT; BIT0 (D0)
    		rcall DS1302_GET_BIT; BIT1 (D1)
    		rcall DS1302_GET_BIT; BIT2 (D2)
    		rcall DS1302_GET_BIT; BIT3 (D3)
    		rcall DS1302_GET_BIT; BIT4 (D4)
    		rcall DS1302_GET_BIT; BIT5 (D5)
    		rcall DS1302_GET_BIT; BIT6 (D6)
    		rcall DS1302_GET_BIT; BIT7 (D7)
    		;_________________________
    
    	CBI DS1302_Port,DS1302_CE	;OFF - transmisja zakończone
    ret
    


    Zaraz zobaczę zmiany analizatorem.
  • #11 8550627
    sulfur
    Poziom 24  
    Andrzej_S: mam zatem rozumieć, że jeżeli port pracuje jako wyjście, to żeby zmienić stan na porcie wystarczy do rejestru odpowiedniego pin na pozycję zapisać jedynkę ?
  • #12 8550692
    Andrzej__S
    Poziom 28  
    sulfur napisał:

    Andrzej_S: mam zatem rozumieć, że jeżeli port pracuje jako wyjście, to żeby zmienić stan na porcie wystarczy do rejestru odpowiedniego pin na pozycję zapisać jedynkę ?

    Tak chyba wynika z tego, co napisali w datasheet :). Nie testowałem tej techniki na sprzęcie, ale w symulatorze tak to działa. I to nie tylko wtedy, kiedy dany pin jest ustawiony jako wyjście. Wpisujesz 1 do jakiegoś bitu PINx, a wartość odpowiedniego bitu w PORTx zostaje odwrócona.
  • #13 8550703
    sulfur
    Poziom 24  
    Nie omieszkam spróbować, ale jeśli to prawda, to ma u mnie kolega duże piwo.

    To jest kod generowany przez gcc:

    Cytat:
    PINC |= 1;
    70: 98 9a sbi 0x13, 0 ; 19
    PINC |= 1;
    72: 98 9a sbi 0x13, 0 ; 19
    PORTC ^= _BV(1);
    74: 85 b3 in r24, 0x15 ; 21
    76: 92 e0 ldi r25, 0x02 ; 2
    78: 89 27 eor r24, r25
    7a: 85 bb out 0x15, r24 ; 21
  • Pomocny post
    #14 8550764
    Andrzej__S
    Poziom 28  
    Proponowałbym zacząć od początku. Krok po kroku, nie wszystko na raz :)

    #1
    Napisałeś w temacie, że używasz ATtiny2313.
    W kodzie napisałeś:
    
    .INCLUDE    "2313def.inc"         ; dołączonego pliku AT90S2313def.inc
    

    Więc jakiego właściwie używasz, bo to jednak nie to samo. Jeżeli masz ATtiny2313 powinieneś napisać:
    
    .INCLUDE    "tn2313def.inc"
    

    a jeśli to ATtiny2313A
    
    .INCLUDE    "tn2313Adef.inc"
    


    #2
    Zdefiniowałeś sobie port B jako:
    
    .equ DS1302_Port   = PORTB
    

    Proponuję zdefiniować jeszcze:
    
    .equ DS1302_DDR   = DDRB
    .equ DS1302_PIN   = PINB
    

    Później zamiast pisać:
    
       sbi DS1302_Port-1, DS1302_SCLK   ;output    == sbi DDRB,DDB2
    

    można napisać:
    
       sbi DS1302_DDR, DS1302_SCLK
    

    i nawet bez komentarza będzie wiadomo o co chodzi. Po jakimś czasie sam byś się zastanawiał, co to jest 'DS1302_Port-1' i czy to faktycznie jest DDRB.

    #3
    Z tego samego powodu proponuję ponazywać sobie rejestry, przykładowo:
    
    .def byte_to_send  = r16 ; bajt do wysłania 
    .def received_byte = r17 ; odebrany bajt 
    .def i             = r18 ; iterator 
    .def command       = r19 ; bajt zawierający instrukcję 
    .def data          = r20 ; bajt zawierający dane
    

    Dzięki temu kod jest bardziej czytelny, nawet jeśli nie ma komentarzy, bo zamiast pisać:
    
       MOV r16, r19
       ...
       LSR r16
    

    można napisać:
    
       MOV byte_to_send, command
       ...
       LSR byte_to_send
    


    To tylko takie zmiany "kosmetyczne", ale naprawdę ułatwiają pracę.

    Może na początek wystarczy.
  • #15 8550965
    Ranma
    Poziom 12  
    nowa wersja.

    działanie:
    0. usuniecie flagi zapisu
    1. odczyt flagi
    2. zapisz do RAM 0b01111110
    3. odczyt z RAM

    Teraz nadal brak jakiejkolwiek reakcji DS1302 brak odczytu.
    Są 'szumy'? na ostatnich bajtach (na opadających zboczach,czyli jak by to) w odczycie ale nie odpowiadają wartości zapisanej.

    Z dokumentacji wynika że zbocze narastające i opadajace maja miec max
    500ns dla 5V
    2000ns dla 2V

    Zegar ma podpięte oba źródła zasilania (5+2V) attiny jest zasilany z programatora.

    Myślec gdzie dalej szukać problemu

    
    .NOLIST                                     ; wyłączenie z raportu z kompilacji
    .INCLUDE    "tn2313def.inc"         ; dołączonego pliku AT90S2313def.inc
    
    .equ DS1302_Port	= PORTB
    .equ DS1302_DDR		= DDRB
    .equ DS1302_PIN		= PINB
    
    .equ DS1302_CE		= 0
    .equ DS1302_IO		= 1
    .equ DS1302_SCLK	= 2
    
    .def command_byte	= r16
    .def data_byte		= r17
    
    .list
    .listmac
    
    
    ;-----------------------------------------------------------------------------
    .cseg
    
    
    .org	0
    rjmp	ResetProcessor		;
    
    ;-----------------------------------------------------------------------------
    ResetProcessor	:			;
    	cli				;
    	ldi	r16,LOW(RAMEND)	;
    	out	SPL,r16			;
    rjmp	Main		;  powrot do petli
    
    
    DS1302_INIT:
    
    	cbi DS1302_Port,DS1302_SCLK		;LOW (stan niski) == cbi PORTB,PORTB2
    	cbi DS1302_Port,DS1302_IO		;LOW (stan niski) == cbi PORTB,PORTB1
    	cbi DS1302_Port,DS1302_CE		;LOW (stan niski) == cbi PORTB,PORTB0
    	
    	sbi DS1302_DDR,DS1302_SCLK		;output	 == sbi DDRB,DDB2
    	sbi DS1302_DDR,DS1302_IO		;output	 == sbi DDRB,DDB1
    	sbi DS1302_DDR,DS1302_CE		;output	 == sbi DDRB,DDB0
    	
    ret	
    
    ;wysyłanie polecenia
    	;polcenie w rejestrze: command_byte
    DS1302_SEND_BIT:
    
    	;ustaw linie
    	SBRS	command_byte,0		;jeżeli bit jest wyzerowany
    	CBI DS1302_Port,DS1302_IO	;wyzeruj
    
    	SBRC	command_byte,0		;jeżeli bit jest ustawiony
    	SBI DS1302_Port,DS1302_IO	;to go ustaw
    	;--------------
    
    	;przesun bity w prawo(ten już wysłano)
    	LSR command_byte
    	;----------
    
    	;DS1302 odczytuje dane na zboczu wzrastającym
    	SBI DS1302_Port,DS1302_SCLK	;ON
    
    	;czekaj
    	rcall wait;	
    	;----------
    
    			;TU DS1302 odczytuje dane
    
    	;czekaj
    	rcall wait;
    	;----------
    
    
    	;czekaj
    	rcall wait;
    	;----------
    
    		;koniec odczytu
    
    	CBI DS1302_Port,DS1302_SCLK	;OFF
    	CBI DS1302_Port,DS1302_IO	;wyzeruj-dzieki temu bedzie widoczny koniec stanu wysokiego
    
    
    	;czekaj
    	rcall wait;
    	;----------
    
    
    	;czekaj
    	rcall wait;
    	;----------
    
    ret
    
    
    
    
    ;TODO - nie testowane
    ;pobieranie danych
    	;r17
    DS1302_GET_BIT:
    	
    
    	;DS1302 wysyła dane na zboczu wzrastającym
    	CBI DS1302_Port,DS1302_SCLK	;OFF
    	;____________________________________
    
    		;czekaj
    		rcall wait;
    		;----------
    
    		
    			;>
    			;tu ds1302 ustawia wartość
    			;>
    
    
    		in r17,DS1302_PIN; todo: zamien na DS1302_Port-??
    
    		;czytaj
    		SBRS	r17,DS1302_IO				;jeżeli bit jest wyzerowany
    		CBR data_byte,7	;wyzeruj
    
    		SBRC	r17,DS1302_IO				;jeżeli bit jest ustawiony
    		SBR data_byte,7	;to go ustaw
    		;--------------
    
    		;przesun bity w lewo(ten już odczytano)
    		LSL data_byte
    		;----------
    
    		;czekaj
    		rcall wait;
    		;----------
    		;czekaj
    		rcall wait;
    		;----------
    	;____________________________________
    
    
    	SBI DS1302_Port,DS1302_SCLK	;ON
    
    	;czekaj
    	rcall wait;
    	;----------
    
    	;czekaj
    	rcall wait;
    	;----------
    
    	;czekaj
    	rcall wait;
    	;----------
    
    
    ret
    ;---------------
    ;wysyła się od tyłu
    	;r16 - command
    	;r17 - data
    DS1302_WriteData:
    
    	;COMMAND BYTE
    	rcall DS1302_SEND_BIT; BIT0 (R/W)
    	rcall DS1302_SEND_BIT; BIT1 (A0)
    	rcall DS1302_SEND_BIT; BIT2 (A1)
    	rcall DS1302_SEND_BIT; BIT3 (A2)
    	rcall DS1302_SEND_BIT; BIT4 (A3)
    	rcall DS1302_SEND_BIT; BIT5 (A4)
    	rcall DS1302_SEND_BIT; BIT6 (R/C)
    	rcall DS1302_SEND_BIT; BIT7 ('1')
    	;_________________________
    
    	mov command_byte,data_byte;przepisanie na rzecz procedury 'DS1302_SEND_BIT'
    
    	;DATA BYTE
    	rcall DS1302_SEND_BIT; BIT0 (D0)
    	rcall DS1302_SEND_BIT; BIT0 (D1)
    	rcall DS1302_SEND_BIT; BIT0 (D2)
    	rcall DS1302_SEND_BIT; BIT0 (D3)
    	rcall DS1302_SEND_BIT; BIT0 (D4)
    	rcall DS1302_SEND_BIT; BIT0 (D5)
    	rcall DS1302_SEND_BIT; BIT0 (D6)
    	rcall DS1302_SEND_BIT; BIT0 (D7)
    	;_________________________
    
    ret
    
    ;odczyt danych
    	;r16
    	;r17
    DS1302_ReadData:
    
    		;COMMAND BYTE
    		rcall DS1302_SEND_BIT; BIT0 (R/W)
    		rcall DS1302_SEND_BIT; BIT1 (A0)
    		rcall DS1302_SEND_BIT; BIT2 (A1)
    		rcall DS1302_SEND_BIT; BIT3 (A2)
    		rcall DS1302_SEND_BIT; BIT4 (A3)
    		rcall DS1302_SEND_BIT; BIT5 (A4)
    		rcall DS1302_SEND_BIT; BIT6 (R/C)
    
    		;_________________________
    		;UWAGA!: BIT7 ('1')
    			;ustaw linie
    			SBRS	command_byte,0		;jeżeli bit jest wyzerowany
    			CBI DS1302_Port,DS1302_IO	;wyzeruj
    
    			SBRC	command_byte,0		;jeżeli bit jest ustawiony
    			SBI DS1302_Port,DS1302_IO	;to go ustaw
    			;--------------
    
    			;DS1302 odczytuje na zboczu wzrastającym
    			SBI DS1302_Port,DS1302_SCLK	;ON
    			rcall wait
    					;daj mu czas na odczytanie
    			rcall wait
    			rcall wait
    		;_________________________
    
    			cbi DS1302_PORT,DS1302_IO   ; wyłącz weznętrzne podciąganie linie 1 portu B
    			
    			;ustaw I/O jako port WEJSCIA
    			;DS1302 poda dane na opajacym zboczu SCLK
    			;cbi DS1302_DDR,DS1302_IO	; włącz tryb wejsciowy lini 1 portu B
    				;to samo:  cbi DDRB, DDB1
    			;cbi DS1302_PORT,DS1302_IO   ; wyłącz weznętrzne podciąganie linie 1 portu B
    				;to samo:  cbi PORTB, PORTB1
    			nop					; oczekuj na ustalenie stanu wejscia (1 cykl zegarowy)
    
    		;DATA BYTE
    		rcall DS1302_GET_BIT; BIT0 (D0)
    		rcall DS1302_GET_BIT; BIT1 (D1)
    		rcall DS1302_GET_BIT; BIT2 (D2)
    		rcall DS1302_GET_BIT; BIT3 (D3)
    		rcall DS1302_GET_BIT; BIT4 (D4)
    		rcall DS1302_GET_BIT; BIT5 (D5)
    		rcall DS1302_GET_BIT; BIT6 (D6)
    		rcall DS1302_GET_BIT; BIT7 (D7)
    		;_________________________
    
    ret
    
    
    ;ustala czy czytamy czy zapisujemy
    	;r16
    	;r17
    ;jeżeli BIT0 w r16 HI  - odczyt
    ;jeżeli BIT0 w r16 LOW - zapis
    DS1302_SendCode:
    
    	rcall DS1302_Init
    
    		SBI DS1302_Port,DS1302_CE	;ON
    
    			SBRS	command_byte,0	;jezeli to komenda zapisu
    			rcall DS1302_WriteData	;wywolaj procedure zapisu
    			SBRC	command_byte,0	;jezeli to komenda odczytu
    			rcall DS1302_ReadData	;wywolaj procedure odczytu
    
    	rcall DS1302_Init		;koniec pracy (note także 'czysci' DS1302_CE)
    ret
    
    
    ;odczekaj
    wait:
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    ret
    
    
    ;-----------------------------------------------------------------------------
    Main:
    
    
    	;---------------------------
    	;flaga zapisu (ustaw na 0) > moge wprowadzać zmiany
    	ldi command_byte,0x8E		;polecenie (0b10001110)
    	ldi data_byte,0b00000000	;wartosc
    		rcall DS1302_SendCode
    	;-------------------------
    
    Main2:
    
    	
    	;---------------------------
    	;odczytaj flage zapisu
    	ldi command_byte,0x8F		;polecenie
    	clr data_byte		 		;tu beda dane odczytane
    		rcall DS1302_SendCode
    	;-------------------------
    
    	;zapisz do RAM 0b01111110
    	ldi command_byte,0xC0		;polecenie (0b10001110)
    	ldi data_byte,0b01111110	;wartosc
    		rcall DS1302_SendCode
    
    	;odczytaj z RAM
    	ldi command_byte,0xC1		;polecenie (0b10001110)
    	ldi data_byte,0b00000000	;wartosc
    		rcall DS1302_SendCode
    
    	;czekaj---------------------
    	rcall wait
    	rcall wait
    	rcall wait
    	rcall wait
    	rcall wait
    	rcall wait
    	rcall wait
    	;-------------------------
    
    rjmp  Main2
    ;-----------------------------------------------------------------------------
    .exit
    
    


    Dodano po 24 [minuty]:

    działający kod w bacom jest tu: https://www.elektroda.pl/rtvforum/topic1569770.html

    może ktoś mi dać/z kompilować .*hex ?
  • #16 8552298
    Andrzej__S
    Poziom 28  
    Ranma napisał:

    Z dokumentacji wynika że zbocze narastające i opadajace maja miec max
    500ns dla 5V
    2000ns dla 2V

    Nie "mają mieć" tylko "mogą mieć". To, jakie będą zbocza narastające i opadające nie zależy od programu, tylko od sprzętu (schemat, projekt PCB, długości przewodów itd.). Czas narastania i opadania zboczy należy uwzględnić w swoim programie, ale program na te czasy nie ma wpływu.

    Ranma napisał:

    Myślec gdzie dalej szukać problemu

    Ja myślę, że problem leży prawdopodobnie w opóźnieniach. Ty dajesz jakieś opóźnienia, ale chyba niepotrzebnie takie duże i niekoniecznie w odpowiednich miejscach. Żeby to stwierdzić, w kodzie powinien być większy porządek, bo na razie trudno się połapać.

    Zacząłbym od tego:
    Ranma napisał:

    
    ;----------------------------------------------------------------------------- 
    .cseg 
    
    
    .org   0 
    rjmp   ResetProcessor      ; 
    
    ;----------------------------------------------------------------------------- 
    ResetProcessor   :         ; 
       cli            ; 
       ldi   r16,LOW(RAMEND)   ; 
       out   SPL,r16         ; 
    rjmp   Main      ;  powrot do petli
    


    Jeżewli nie będziesz używał w swoim programie przerwań, tablicę wektorów można pominąć i zacząć od razu pisać program. W związku z tym instrukcja rjmp ResetProcessor i etykieta ResetProcessor są zbędne. Przy okazji, moim skromnym zdaniem, główny program lepiej mieć na początku. Przeniosłem więc 'Main' na początek. Wygląda to tak:
    
    ;******** początek programu **********************
    .cseg
    .org 0
    ;---- wyłączenie flagi globalnej przerwań ----
       cli
    
    ;---- zainicjowanie wskaźnika stosu ----
       ldi   r16, LOW(RAMEND)
       out   SPL, r16
    
    ;---- przeniesiona głowna część programu ---
    
       ;flaga zapisu (ustaw na 0) > moge wprowadzać zmiany
       ldi command_byte,0x8E      ;polecenie (0b10001110) 
       ldi data_byte,0b00000000   ;wartosc
          rcall DS1302_SendCode 
       ;------------------------- 
    
    ;===== pętla główna ==================================
    main_loop: 
       ;--------------------------- 
       ;odczytaj flage zapisu 
       ldi command_byte,0x8F      ;polecenie 
       clr data_byte             ;tu beda dane odczytane 
          rcall DS1302_SendCode 
       ;------------------------- 
    
       ;zapisz do RAM 0b01111110 
       ldi command_byte,0xC0      ;polecenie (0b10001110) 
       ldi data_byte,0b01111110   ;wartosc 
          rcall DS1302_SendCode 
    
       ;odczytaj z RAM 
       ldi command_byte,0xC1      ;polecenie (0b10001110) 
       ldi data_byte,0b00000000   ;wartosc 
          rcall DS1302_SendCode 
    
       ;czekaj--------------------- 
       rcall wait 
       rcall wait 
       rcall wait 
       rcall wait 
       rcall wait 
       rcall wait 
       rcall wait 
       ;------------------------- 
    
    rjmp  main_loop
    ;===== koniec pętli głównej ==========================
    
    ;---- teraz pozostałe procedury ----
    
    


    Następna sprawa. Zamiast używać jakichś wartości nie wiadomo skąd:
    
       ldi command_byte,0x8E      ;polecenie (0b10001110)
    

    lepiej jest zdefiniować sobie (na początku programu) przykładowo coś takiego:
    
    .equ CMD        = 0b10000000
    .equ RAM        = 0b01000000
    .equ CLOCK      = 0b00000000
    .equ READ       = 0b00000001
    .equ WRITE      = 0b00000000
    ; --- adresy ---
    ; przesunięte o 1 pozycję w lewo, ponieważ na pozycji LSB
    ; jest bit kierunku transmisji (R/!W)
    .equ ADDR_SEC    = (0x00<<1)
    .equ ADDR_MIN    = (0x01<<1)
    .equ ADDR_HRS    = (0x02<<1)
    .equ ADDR_DATE   = (0x03<<1)
    ; ... i tak dalej
    

    i później w kodzie można użyć takich przykładowych poleceń:
    
       ldi command_byte, CMD | CLOCK | ADDR_SEC | WRITE ; komenda ustawiająca sekundy w zegarze
       ldi command_byte, CMD | RAM | (0x05<<1) | READ ; komenda odczytująca wartość komórki RAM o adresie 0x05
    

    Od razu widać co wysyłamy. Założę się, że jak sięgniesz po ten kod za miesiąc, to sam się będziesz zastanawiał, co to znaczy 'polecenie(0b10001110)'. Jeśli ktoś inny analizuje taki kod, jak Ty napisałeś, to musi sięgać co chwilę do dokumentacji i analizować, które bity do czego służą i co chciałeś osiągnąć. Zwykle to skutecznie zniechęca do udzielania pomocy.

    Pamiętaj, że to na razie tylko zmiany mające na celu poprawę czytelności Twojego kodu. Te zmiany nie spowodują, że program zacznie działać.

    Następnym razem spróbujemy przystąpić do zbudowania porządnego algorytmu transmisji.
  • #17 8554821
    Ranma
    Poziom 12  
    Ok sporo się nauczyłem:D to dobrze
    szkoda ze nadal nie ma właściwych odczytów-dostaje zawsze 0b11111111 :/

    Wprowadziłem następujące zmiany:
    (całe źródło w załączniku)

    podział na 2 pliki:
    'main.asm' < tu jest program
    'ds1302.asm' < tu jest interface

    działanie programu:
    1 usuwa flage
    2 czyta bajt z flagą
    3 zapis do RAM[1] wart 0b01111110
    4 odczyt z RAM[1]
    5 czekaj na nic, skocz do 3


    przyklad polecen:
    zapis flagi WP:
    ldi command_byte,	CMD | CLOCK | ADDR_WPFLAG | WRITE; komenda usuwająca WP
    ldi data_byte,		0b00000000	;wartosc

    zapis do RAM:
    ldi command_byte,	CMD | RAM | ADDR_RAM1 | WRITE	; komenda usuwająca WP
    ldi data_byte,		0b01111110	;wartosc



    na dziś koniec pracy. Sprawdzę timing jutro. Naprawdę chciałbym zobaczyć timming i analizę stanów logicznych działającej komunikacji. Eh to by tak ułatwiło sprawę.
  • #18 8555835
    Andrzej__S
    Poziom 28  
    napisał:

    Naprawdę chciałbym zobaczyć timming i analizę stanów logicznych działającej komunikacji. Eh to by tak ułatwiło sprawę.

    Przecież timingi masz w datasheet. Poza tym, to wcale nie jest takie pewne, że sprawa byłaby łatwiejsza. Moim zdaniem łatwiej jest napisać program od początku, niż analizować kod wyprodukowany przez kompilator BASCOM. Napisanie programu w assemblerze wcale nie jest takie skomplikowane, tylko trzeba podejść do tego metodycznie, krok po kroku.

    Na początek algorytm. Może być w postaci tekstowej. Otwierasz sobie dokument DS1302 datasheet na stronie 11 i na podstawie niego piszesz (najpierw wysyłanie danych, czyli Figure 6):

    Założenie wstępne - wszystkie linie sterujące (DS1302_CE, DS1302_IO, DS1302_SCLK) są wyjściami i mają stan niski.

    W celu wysłania bajtu danych postępujemy następująco:
    #1 Ustawiamy stan wysoki na linii DS1302_CE.
    #2 Czekamy czas odrobinę dłuższy od (tCC - tDC) = 4us - 200ns (patrz rysunek z timingiem i tabelka z wartościami opóźnień). Przyjmujemy wariant najmniej optymistyczny. Później, jak już układ będzie działał możemy spróbować zmniejszyć czasy opóźnień.
    #3 Ustawiamy wartość iteratora na 8, ponieważ będziemy wysyłać osiem bitów i tworzymy etykietę, ponieważ następne kroki będą powtarzane do momentu wysłania wszystkich ośmiu bitów (command_byte).
    #4 Ustawiamy wyjście danych - DS1302_IO - odpowiednio do wartości bitu LSB w rejestrze command_byte.
    #5 Wprowadzamy opóźnienie równe tDC = 200ns (dobrze jest wstępnie dodać chociaż jeden takt zegara procesora do tego czasu).
    #6 Ustawiamy linię DS1302_SCLK w stan wysoki.
    #7 Czas trwania stanu wysokiego wynosi 1000ns, więc musimy teraz odczekać.
    #8 Ustawiamy linię DS1302_SCLK w stan niski.
    #9 Czas trwania stanu niskiego wynosi 1000ns, więc musimy teraz odczekać. Ponieważ jednak za chwilę będzie wysyłany następny bit, po którego ustawieniu na linii DS1302_IO i tak czekamy 200ns, możemy te 1000ns zmniejszyć do 800ns.
    #10 Przesuwamy rejestr command_byte o jedną pozycję w lewo, ustawiając w ten sposób następny bit do wysłania na pozycji LSB.
    #11 Zmniejszamy wartość iteratora i jeśli nie osiągnął jeszcze wartości 0, powtarzamy kroki od #4 do #11, czyli musimy teraz wykonać skok do etykiety ustawionej w punkcie #3. Jeżeli iterator osiągnął wartość 0, przechodzimy do punktu następnego.
    #12 Ustawiamy wartość iteratora na 8, ponieważ będziemy wysyłać osiem bitów i tworzymy etykietę, ponieważ następne kroki będą powtarzane do momentu wysłania następnych ośmiu bitów (data_byte).
    #13 Ustawiamy wyjście danych - DS1302_IO - odpowiednio do wartości bitu LSB w rejestrze command_byte.
    #14 Wprowadzamy opóźnienie równe tDC = 200ns.
    #15 Ustawiamy linię DS1302_SCLK w stan wysoki.
    .... i tak dalej.

    Resztę spróbuj dopisać sam z uwzględnieniem czasów tCCH i tCWH.

    Nie napisałeś, jakiej częstotliwości używasz do taktowania mikrokontrolera, więc przyjąłem maksymalną = 20MHz (1 takt = 50ns).
    W rozwinięciu na kod wyglądałoby to mniej więcej tak:
    
    ; ===================================================
    ; proceduraa Write_BYTE wysyłająca byte danych
    ; do odpowiedniej komórki pamięci/rejestru układu DS1302
    ; wejście:
    ;    command_byte - bajt zawierający komendę (CMD),
    ;                   przeznaczenie danych (RAM|CLOCK),
    ;                   kierunek transmisji (READ | WRITE),
    ;                   adres komórki pamięci/rejestru (ADDR_xxx)
    ;    data_byte    - bajt zawierający dane do wysłania
    ; wyjście:
    ;    brak
    Write_BYTE:
    
    ; ****** #1 ******
       SBI DS1302_Port,DS1302_CE
    
    ; ****** #2 ******
    ; 4us - 200ns = 3800ns
    ; 3800ns / 50ns = 76 taktów
    ; na początku należy zdefiniować jakiś wolny rejestr jako delay
       LDI delay, 26
    delay_loop1:
       DEC delay        ; 1 takt
       BRNE delay_loop1 ; 2 takty
                        ; -----
                        ; 3 takty * 26 = 78 ( w przybliżeniu)
    
    ; ****** #3 ******
    ; na początku należy zdefiniować jakiś wolny rejestr jako i
       LDI i, 8
    send_byte_loop1:
    
    ; ****** #4 ******
       SBRS	command_byte, 0       ; jeżeli LSB w command_byte = 0
       CBI DS1302_Port, DS1302_IO   ; linia DS1302_IO = 0
    
       SBRC	command_byte, 0       ; jeżeli LSB w command_byte = 1
       SBI DS1302_Port, DS1302_IO   ; linia DS1302_IO = 1
    
    ; ****** #5 ******
    ; dla pewności 5 taktów
       nop
       nop
       nop
       nop
       nop
    
    ; ****** #6 ******
       SBI DS1302_Port, DS1302_SCLK
    
    ; ****** #7 ******
    ; 1000ns / 50ns = 20 taktów
       LDI delay, 7
    delay_loop2:
       DEC delay        ; 1 takt
       BRNE delay_loop1 ; 2 takty
                        ; -----
                        ; 3 takty * 7 = 21 ( w przybliżeniu)
    
    ; ****** #8 ******
       CBI DS1302_Port, DS1302_SCLK
    
    ; ****** #9 ******
    ; 800ns / 50ns = 16 taktów
       LDI delay, 6
    delay_loop3:
       DEC delay        ; 1 takt
       BRNE delay_loop1 ; 2 takty
                        ; -----
                        ; 3 takty * 6 = 18 ( w przybliżeniu)
    
    ; ****** #10 ******
       LSL command_byte
    
    ; ****** #11 ******
       DEC i
       BRNE send_byte_loop1
    
    ; ****** #12 ******
       LDI i, 8
    send_byte_loop2:
    
    ; ****** #13 ******
       SBRS	data_byte, 0          ; jeżeli LSB w data_byte = 0
       CBI DS1302_Port, DS1302_IO   ; linia DS1302_IO = 0
    
       SBRC	data_byte, 0          ; jeżeli LSB w data_byte = 1
       SBI DS1302_Port, DS1302_IO   ; linia DS1302_IO = 1
    
    ; ****** #14 ******
       nop
       nop
       nop
       nop
       nop
    
    ; ****** #15 ******
       SBI DS1302_Port, DS1302_SCLK
    
    ; ++++++ reszta kodu +++++
    
       RET
    
    ; ==== koniec Write_BYTE =================================
    
    


    TO NIE JEST GOTOWY KOD. Nie sprawdzałem jego działania. W tej chwili nie mam nawet takiej możliwości. Ja tylko pokazałem metodykę działania podczas pisania programu.

    Jeśli napiszesz program w przedstawiony powyżej sposób, to w zasadzie wystarczą Ci dwie procedury: Write_BYTE i Read_BYTE, bez konieczności kilkakrotnego wywoływania procedur typu xxx_SEND_BIT czy xxx_READ_BIT. Można ewentualnie wydzielić powtarzające się opóźnienia do osobnych podprocedur.

    Resztę spróbuj dopisać sam. Zwróć uwagę na formatowanie, wcięcia, oznaczanie początku i końca procedury itp. Ja nie pisałem zbyt obszernych komentarzy, tylko odnosiłem się do poszczególnych punktów algorytmu, ale normalnie dobrze jest opisywać dokładniej, co się robi. Jak piszesz tylko dla siebie, pisz jak Ci pasuje. Jak przedstawiasz kod na forum, postaraj się, żeby był czutelny także dla innych. Jeżeli kod będzie napisany zgodnie z zaleceniami, a nadal coś nie będzie działać, może łatwiej będzie się dopatrzyć błędu. Myślę jednak, że jeśli podejdziesz do tego metodycznie, to pomoc forum nie będzie Ci potrzebna :).

    P.S. Zwróć uwagę podczas pisania procedury Read_BYTE (lub jak tam ją sobie nazwiesz) na kierunek "wsuwania" bitów do rejestru odbiorczego, bo masz nieprawidłowy. Pierwszy odebrany bit wpisujesz do rejestru na pozycję MSB (bit 7, czyli prawidłowo), ale później przesuwasz go w lewo (czyli nieprawidłowo). To nie jest przyczyna błędu, bo powinieneś wtedy otrzymywać same zera, a nie same jedynki. Zresztą zastanawiam się też, jak to sprawdzasz, co odebrałeś, bo w kodzie się nie dopatrzyłem.
  • #19 8555928
    Ranma
    Poziom 12  
    Panie Andrzej'u sporo mi pan napisał:D dziękuje za to same cenne rady
    ok zaczynam analizę i prace nad poprawkami.

    sprawdzam to analizatorem stanów logicznych.
    [wgrywam program i na sczytuje zmiany na liniach począwszy od pierwszego wzrastającego zbocza lini CE]
  • #20 8560191
    Andrzej__S
    Poziom 28  
    Program to jedna sprawa. Nie wiem jakiej częstotliwości używasz do taktowania procesora, ale niezależnie od tego najprawdopodobniej miałeś zły timing.

    Ważniejsza sprawa to SCHEMAT. Teraz dopiero dokładniej mu się przyjrzałem. Jeśli masz układ połączony tak, jak na przedstawionym przez Ciebie rysunku w pierwszym poście, to on na pewno nie będzie działał. Baterię podtrzymującą musisz podłączyć:
    "plus" do VCC1
    "minus" do GND
    Do VCC2 podłączasz "plus" napięcia zasilającego mikroprocesor, a "minus" tego napięcia również do GND.

    Mam tylko nadzieję, że nie uszkodziłeś w międzyczasie układu.

    Dodano po 47 [minuty]:

    Obejrzałem jeszcze zdjęcie zmontowanego układu na płytce stykowej. Wygląda na to, że baterię masz podłączoną prawidłowo (czyli nie tak, jak na schemacie): minus do pinu 4 (GND), a plus do pinu 8 (VCC1). Nie widzę jednak, jak masz zasilony mikroprocesor, ale najprawdopodobniej innym napięciem (z jakiegoś zasilacza?). Musisz w takim przypadku połączyć masy, czyli pin 10 z AAtiny2313 z pinem 4 DS1302. Dodatkowo pin 20 ATtiny2313 (VCC) musisz połączyć z pinem 1 DS1302 (VCC2).
  • #21 8565555
    Ranma
    Poziom 12  
    przepraszam za krótka przerwę.

    1. Używam attinego bez żadnego kwarcu-z tego co rozumiem to powinno być 20Mhz.

    2. Z tego co zrozumiałem nie miałem zwartych mas obu układów, teraz DS1302 i attiny mają wspólna masę.

    zasilanie, z programatora 5V
    "+" DO [VCC attiny]
    "-" DO [GND attiny]

    bateria 2.8V
    "+baterii" do (VCC1 ds1302)
    "-bateri" do (GND ds1302)

    zwarcie mas i zasilania
    (VCC1 z DS1302) do [VCC attiny]
    (GND z DS1302) do [GND attiny]

    oto nowa wersja połączenia:
    [ATTiny2313][ASM][AVRstudio] interface z attiny2313
  • #22 8565642
    Andrzej__S
    Poziom 28  
    Cytat:

    zwarcie mas i zasilania
    (VCC1 z DS1302) do [VCC attiny]
    (GND z DS1302) do [GND attiny]

    Powinno być "VCC2 z DS1302", ale połączone masz chyba dobrze.

    Dobrze byłoby dać jeszcze jakieś kondensatory w zasilaniu +5V z programatora jak najbliżej układów.

    Procesor taktujesz chyba wewnętrznym generatorem RC, bo nie widzę kwarcu. Jakiej częstotliwości używasz?
  • #23 8565789
    Ranma
    Poziom 12  
    ok, wiec teraz uznaje połączenia za prawidłowe - nie ma juz odpowiedzi 0b11111111.

    Kondensatory na zasilaniu?

    Tak wewnętrznym generatorem RC (nie wiem-szukam).
    Cytat:

    ATtiny2313: 0 - 10 MHz @ 2.7 - 5.5V, 0 - 20 MHz @ 4.5 - 5.5V

    Może wygodniej było by kupić kwarc 1Mhz i wpiąć bez niczego?
  • #24 8565997
    Andrzej__S
    Poziom 28  
    Ranma napisał:

    Kondensatory na zasilaniu?

    Równolegle do napięcia zasilającego 5V z programatora na płytce stykowej dobrze byłoby dać jeden kondensator elektrolityczny 10 uF i dodatkowo 2 kondensatory ceramiczne 100nF jak najbliżej nóżek zasilających każdy z układów. Będzie większa pewność, że ewentualne kłopoty nie są spowodowane spadkami napięcia na przewodach zasilających, a co za tym idzie niestabilnym napięciem zasilającym.

    Ranma napisał:

    Tak wewnętrznym generatorem RC (nie wiem-szukam).

    Domyślnie mikrokontroler ustawiony jest na wewnętrzny generator RC 1MHz, jeżeli nie zmieniałeś nic w fusebitach.

    Ranma napisał:

    Może wygodniej było by kupić kwarc 1Mhz i wpiąć bez niczego?

    No bez niczego to się nie da. Trzeba jeszcze dać dwa kondensatory (~22pF) i odpowiednio ustawić fusebity w mikrokontrolerze.
  • #25 8566046
    Ranma
    Poziom 12  
    ok nic nie zmieniałem w fuse bitach. Więc jest 1Mhz to by się zgadzało z odczytami:) OK tego nie będę zmieniał, nie potrzeba.

    dobrze, kondensatory:
    1 elektrolityczny 10 uF
    2 ceramiczne 100nF

    z rana kupię, bo nie mam tych elementów

    Dodano po 3 [godziny] 3 [minuty]:

    nowa obserwacja, bardzo ciekawa:

    układ robi się gorący pod wpływem nowego oprogramowania/podłączenia!

    Dodano po 2 [minuty]:

    prawdopodobnie nowy kod już działa!
    Otrzymałem pierwsze prawidłowe odczyty, z tej okazji nazywam te wersje wersją 1.0.
    Dokonam jednak jeszcze szereg testów w celu potwierdzenia.

    Dodano po 1 [godziny] 11 [minuty]:

    na 99% procent działa oto dowód, proszę potwierdzić moje przypuszczenia bo sam sobie nie wierze z radości. To ogromna satysfakcja dla mnie.

    [ATTiny2313][ASM][AVRstudio] interface z attiny2313
  • #26 8567631
    Andrzej__S
    Poziom 28  
    Ranma napisał:

    układ robi się gorący pod wpływem nowego oprogramowania/podłączenia!

    Który układ robi się gorący? Jak bardzo "gorący"? To raczej nie jest pozytywne zjawisko. Mam nadzieję, że nie włączałeś trickle-charger w DS1302, bo ta bateria, którą tam masz podłączoną raczej nie nadaje się do ładowania.
  • #27 8567958
    Ranma
    Poziom 12  
    nagrzewa się DS1302. Jest lekko ciepły.
    Nic nie modyfikowałem z trickle-charger.
  • #28 8568196
    Andrzej__S
    Poziom 28  
    Ranma napisał:

    układ robi się gorący pod wpływem nowego oprogramowania/podłączenia!
    ....
    nagrzewa się DS1302. Jest lekko ciepły.

    Ktoś mnie tu wprowadza w błąd. "Gorący" a "lekko ciepły" to jednak dosyć zdecydowana różnica.

    Nawet jeśli robi się "lekko ciepły" (nadal nie jestem pewien, co to dokładnie oznacza), to i tak trochę dziwne, sądząc po parametrach poboru prądu podanych w datasheet. Układ powinien pobierać maksymalnie kilkanaście mW mocy. No, ale najważniejsze, że działa :)
REKLAMA