<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>The Most Amazing Web Resources &#187; Assembler</title>
	<atom:link href="http://stonestreem.com/category/assembler/feed/" rel="self" type="application/rss+xml" />
	<link>http://stonestreem.com</link>
	<description></description>
	<pubDate>Mon, 08 Dec 2008 03:17:40 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<item>
		<title>Interrupt driven routine for Avr 16-bit PWM</title>
		<link>http://stonestreem.com/interrupt-driven-routine-for-avr-16-bit-pwm/</link>
		<comments>http://stonestreem.com/interrupt-driven-routine-for-avr-16-bit-pwm/#comments</comments>
		<pubDate>Thu, 28 Jun 2007 18:44:08 +0000</pubDate>
		<dc:creator>peorex</dc:creator>
		
		<category><![CDATA[Assembler]]></category>

		<guid isPermaLink="false">http://helius.icnhost.net/~peorex/blog/?p=12</guid>
		<description><![CDATA[Target:    ATtiny2313
Uses OCR0A, TCNT0, TCNT1
With ATtiny2313 it is possible to utilize two 16-bit PWM using OC1A and OC1B.
If application needs more than this, say RGB controller, two additional 16-bit channels can be created from native 8-bit OC0A and OC0B. The resolution is true 16-bit, glitch-free. Prescaler can be set to 1.
The software [...]]]></description>
			<content:encoded><![CDATA[<p>Target:    ATtiny2313<br />
Uses OCR0A, TCNT0, TCNT1</p>
<p>With ATtiny2313 it is possible to utilize two 16-bit <a href="http://www.technorati.com/tag/PWM" rel="tag">PWM</a> using OC1A and OC1B.<br />
If application needs more than this, say <a href="http://www.technorati.com/tag/RGB" rel="tag">RGB</a> controller, two additional 16-bit channels can be created from native 8-bit OC0A and OC0B. The resolution is true 16-bit, glitch-free. Prescaler can be set to 1.<br />
The software emulated <strong>PWM</strong> behaves as its hardware counterpart, except that its registers are in data SRAM, here called <code>RegOCR0AL</code> and <code>RegOCR0AH</code>.<br />
A small limitation is that duty cycle can not be too small. The value of <code>RegOCR0AH:RegOCR0AL</code> must be limited to, say FF80h (inverted <strong>PWM)</strong> depending on particular program environment.</p>
<p>In this <a href="http://www.technorati.com/tag/assembler" rel="tag">assembler</a> code example are shown only essential parts of software <strong>PWM</strong> implementation. The goal is to supply the basic idea of how to create 16-bit <strong>PWM</strong> using 8-bit OC and 16-bit timer, in this case OC0A and TCNT1.<br />
Other parts such as initialization and main program are not shown because they are application specific.</p>
<pre>;****************************************************************</pre>
<pre>; ****    CONSTANTS</pre>
<pre>;****************************************************************</pre>
<pre>.equ    TCCR0A_Set_OC_Val    = (1&lt;&lt;COM0A1) | (1&lt;&lt;COM0A0)</pre>
<pre>.equ    TCCR0A_Clear_OC_Val  = (1&lt;&lt;COM0A1) | (0&lt;&lt;COM0A0)</pre>
<p><code></code></p>
<pre>;****************************************************************</pre>
<pre>; ****    GLOBAL VARIABLES</pre>
<pre>;****************************************************************</pre>
<pre>.dseg</pre>
<pre>RegOCR0AL:            .byte    1</pre>
<pre>RegOCR0AH:            .byte    1</pre>
<p><code></code></p>
<pre>;****************************************************************</pre>
<pre>; ****    INTERRUPT VECTORS</pre>
<pre>;****************************************************************</pre>
<pre>.cseg</pre>
<pre>.org    $0000</pre>
<pre>    rjmp    Reset                ; Reset handler                     $0000</pre>
<pre>    rjmp    INT0_Int_Entry       ; External Interrupt0               $0001</pre>
<pre>    rjmp    INT1_Int_Entry       ; External Interrupt1               $0002</pre>
<pre>    rjmp    ICP1_Int_Entry       ; Input capture interrupt 1         $0003</pre>
<pre>    rjmp    OC1A_Int_Entry       ; Timer/Counter1 Compare Match A    $0004</pre>
<pre>    rjmp    OVF1_Int_Entry       ; Overflow1 Interrupt               $0005</pre>
<pre>    rjmp    OVF0_Int_Entry       ; Overflow0 Interrupt               $0006</pre>
<pre>    rjmp    URXC0_Int_Entry      ; USART0 RX Complete Interrupt      $0007</pre>
<pre>    rjmp    UDRE0_Int_Entry      ; USART0 Data Register Empty        $0008</pre>
<pre>    rjmp    UTXC0_Int_Entry      ; USART0 TX Complete Interrupt      $0009</pre>
<pre>    rjmp    ACI_Int_Entry        ; Analog Comparator Interrupt       $000A</pre>
<pre>    rjmp    PCINT_Int_Entry      ; Pin Change Interrupt              $000B</pre>
<pre>    rjmp    OC1B_Int_Entry       ; Timer/Counter1 Compare Match B    $000C</pre>
<pre>    rjmp    OC0A_Int_Entry       ; Timer/Counter0 Compare Match A    $000D</pre>
<pre>    rjmp    OC0B_Int_Entry       ; Timer/Counter0 Compare Match B    $000E</pre>
<pre>    rjmp    USI_START_Int_Entry  ; USI start interrupt               $000F</pre>
<pre>    rjmp    USI_OVF_Int_Entry    ; USI overflow interrupt            $0010</pre>
<pre>    rjmp    ERDY_Int_Entry       ; EEPROM write complete             $0011</pre>
<pre>    rjmp    WDT_Int_Entry        ; Watchdog Timer Interrupt          $0012</pre>
<p><code></code></p>
<pre>;****************************************************************</pre>
<pre>; ****    INTERRUPT ENTRY</pre>
<pre>;****************************************************************</pre>
<pre>.cseg</pre>
<p><code></code></p>
<pre>OC0A_Int_Entry:</pre>
<pre>    push    zl</pre>
<pre>    in      zl, SREG</pre>
<pre>    push    zl</pre>
<pre>    push    zh</pre>
<pre>    push    yl</pre>
<pre>    push    yh</pre>
<pre>;-------------------------------</pre>
<p><code></code></p>
<pre>    lds     yl, RegOCR0AL            ; OCR low byte</pre>
<pre>    lds     yh, RegOCR0AH            ; OCR hihg byte</pre>
<pre>    in      zl, TCNT1L               ; timer low byte</pre>
<pre>    in      zh, TCNT1H               ; timer high byte</pre>
<p><code></code></p>
<pre>    cpi     zh, $FF                  ; top value</pre>
<pre>    breq    _FF_Clear</pre>
<p><code></code></p>
<pre>    sub     zl, yl</pre>
<pre>    sbc     zh, yh</pre>
<p><code></code></p>
<pre>    brcc    RegOCR0AL_Set</pre>
<pre>    cpi     zh, $FE</pre>
<pre>    breq    Wait_a_little            ; FE, &lt;= 200h MCU cycles</pre>
<pre>    brcc    RegOCR0AL_Set            ; FF, &lt;= 100h MCU cycles</pre>
<pre>    rjmp    RegOCR0AL_Clear          ; &gt; 200h MCU cycles</pre>
<p><code></code></p>
<pre>Wait_a_little:</pre>
<pre>    cpi     zl, $E0</pre>
<pre>    brcs    RegOCR0AL_Clear          ; too many MCU cycles, don't wait</pre>
<p><code></code></p>
<pre>    in      zl, TCNT0</pre>
<pre>    cp      zl, yl                   ; RegTCNT0L, RegOCR0AL</pre>
<pre>    brcs    PC - 2</pre>
<pre></pre>
<pre>    rjmp    RegOCR0AL_Set            ; &lt; 100h MCU cycles now</pre>
<p><code></code></p>
<pre>_FF_Clear:</pre>
<pre>    out     OCR0A, zh</pre>
<pre>    ldi     zl, TCCR0A_Clear_OC_Val</pre>
<pre>    out     TCCR0A, zl               ; clear output on compare</pre>
<pre>    rjmp    Leave_OC0A_Int</pre>
<p><code></code></p>
<pre>RegOCR0AL_Set:</pre>
<pre>    out     OCR0A, yl</pre>
<pre>    ldi     zl, TCCR0A_Set_OC_Val</pre>
<pre>    out     TCCR0A, zl               ; set output on compare</pre>
<pre>    rjmp    Leave_OC0A_Int</pre>
<p><code></code></p>
<pre>RegOCR0AL_Clear:</pre>
<pre>    out     OCR0A, yl</pre>
<pre>    ldi     zl, TCCR0A_Clear_OC_Val</pre>
<pre>    out     TCCR0A, zl               ; clear output on compare</pre>
<pre>    rjmp    Leave_OC0A_Int</pre>
<p><code></code></p>
<pre>;------------------------------</pre>
<pre>Leave_OC0A_Int:</pre>
<pre>    pop     yh</pre>
<pre>    pop     yl</pre>
<pre>    pop     zh</pre>
<pre>    pop     zl</pre>
<pre>    out     SREG, zl</pre>
<pre>    pop     zl</pre>
<pre>    reti</pre>
<p><code></code></p>
]]></content:encoded>
			<wfw:commentRss>http://stonestreem.com/interrupt-driven-routine-for-avr-16-bit-pwm/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PIC Arithmetic 16-bit</title>
		<link>http://stonestreem.com/pic-arithmetic-16-bit/</link>
		<comments>http://stonestreem.com/pic-arithmetic-16-bit/#comments</comments>
		<pubDate>Wed, 27 Jun 2007 18:32:12 +0000</pubDate>
		<dc:creator>peorex</dc:creator>
		
		<category><![CDATA[Assembler]]></category>

		<guid isPermaLink="false">http://helius.icnhost.net/~peorex/blog/?p=11</guid>
		<description><![CDATA[Target:    PIC16C71
; Bit definitions

#define    _c      status,0
#define    _z      status,2
#define    _dc     status,1

#define    _gie    intcon, 7

; Macro definitions

Bank1    macro
    bsf [...]]]></description>
			<content:encoded><![CDATA[<p>Target:    <a href="http://www.technorati.com/tag/PIC16C71" rel="tag">PIC16C71</a></p>
<pre>; Bit definitions</pre>
<p><code></code></p>
<pre>#define    _c      status,0</pre>
<pre>#define    _z      status,2</pre>
<pre>#define    _dc     status,1</pre>
<p><code></code></p>
<pre>#define    _gie    intcon, 7</pre>
<p><code></code></p>
<pre>; Macro definitions</pre>
<p><code></code></p>
<pre>Bank1    macro</pre>
<pre>    bsf    status, 5</pre>
<pre>    endm</pre>
<p><code></code></p>
<pre>Bank0    macro</pre>
<pre>    bcf    status, 5</pre>
<pre>    endm</pre>
<p><code></code></p>
<pre>; Mov pointer Work register with Literal</pre>
<pre>MovWL    macro    Literal</pre>
<pre>    movwf    fsr</pre>
<pre>    movlw    low(Literal)</pre>
<pre>    movwf    indf</pre>
<pre>    incf     fsr</pre>
<pre>    movlw    high(Literal)</pre>
<pre>    movwf    indf</pre>
<pre>    endm</pre>
<p><code></code></p>
<pre>; Mov File register from Literal</pre>
<pre>MovFL    macro    File, Literal</pre>
<pre>    movlw    low(Literal)</pre>
<pre>    movwf    File</pre>
<pre>    movlw    high(Literal)</pre>
<pre>    movwf    File + 1</pre>
<pre>    endm</pre>
<p><code></code></p>
<pre>; Compare Literal with File register</pre>
<pre>CmpLF    macro    Literal, File</pre>
<pre>    movf     File + 1, w</pre>
<pre>    sublw    high(Literal)</pre>
<pre>    btfss    _z</pre>
<pre>    goto     $ + 3</pre>
<pre>    movf     File,  w</pre>
<pre>    sublw    low(Literal)</pre>
<pre>    endm</pre>
<p><code></code></p>
<pre>; Compare File register with Literal</pre>
<pre>CmpFL    macro    File, Literal</pre>
<pre>    movlw    high(Literal)</pre>
<pre>    subwf    File + 1, w</pre>
<pre>    btfss    _z</pre>
<pre>    goto     $ + 3</pre>
<pre>    movlw    low(Literal)</pre>
<pre>    subwf    File, w</pre>
<pre>    endm</pre>
<p><code></code></p>
<pre>; Compare File register Destination with File register Source</pre>
<pre>CmpFF    macro    FileD, FileS</pre>
<pre>    movf     FileS + 1, w</pre>
<pre>    subwf    FileD + 1, w</pre>
<pre>    skpz</pre>
<pre>    goto     $ + 3</pre>
<pre>    movf     FileS,  w</pre>
<pre>    subwf    FileD, w</pre>
<pre>    endm</pre>
<p><code></code></p>
<pre>; Add File register Source to File register Destination</pre>
<pre>AddFF    macro    FileD, FileS</pre>
<pre>    movf     FileS, w</pre>
<pre>    addwf    FileD,F</pre>
<pre>    skpnc</pre>
<pre>    incf     FileD + 1</pre>
<pre>    movf     FileS + 1, w</pre>
<pre>    addwf    FileD + 1</pre>
<pre>    endm</pre>
<p><code></code></p>
<pre>; Data declarations</pre>
<p><code></code></p>
<pre>     cblock    0ch</pre>
<pre>AccA    :2</pre>
<pre>AccB    :2</pre>
<pre>W1</pre>
<p><code></code></p>
<pre>Flags   :1</pre>
<pre>    endc</pre>
<p><code></code></p>
<pre>;  Routines</pre>
<p><code></code></p>
<pre>; Mov accumulator A from pointer Work register</pre>
<pre>MovAW</pre>
<pre>    movwf    fsr</pre>
<pre>    movf     indf, w</pre>
<pre>    movwf    AccA</pre>
<pre>    incf     fsr</pre>
<pre>    movf     indf, w</pre>
<pre>    movwf    AccA + 1</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>; Mov pointer Work register from accumulator A</pre>
<pre>MovWA</pre>
<pre>    movwf    fsr</pre>
<pre>    movf     AccA, w</pre>
<pre>    movwf    indf</pre>
<pre>    incf     fsr</pre>
<pre>    movf     AccA + 1, w</pre>
<pre>    movwf    indf</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>; Increment pointer Work register</pre>
<pre>IncW</pre>
<pre>    movwf    fsr</pre>
<pre>    incfsz   indf</pre>
<pre>    return</pre>
<pre>    incf     fsr</pre>
<pre>    incf     indf</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>; Decrement pointer Work register</pre>
<pre>DecW</pre>
<pre>    movwf    fsr</pre>
<pre>    movlw    0ffh</pre>
<pre>    addwf    indf</pre>
<pre>    btfsc    _c</pre>
<pre>    return</pre>
<pre>    incf     fsr</pre>
<pre>    decf     indf</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>; Compare accumulator A with pointer Work register</pre>
<pre>CmpAW</pre>
<pre>    movwf    fsr</pre>
<pre>    incf     fsr</pre>
<pre>    movf     indf, w</pre>
<pre>    subwf    AccA + 1, w</pre>
<pre>    btfss    _z</pre>
<pre>    return</pre>
<pre>    decf     fsr</pre>
<pre>    movf     indf, w</pre>
<pre>    subwf    AccA, w</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>; Compare pointer Work register with accumulator A</pre>
<pre>CmpWA</pre>
<pre>    movwf    fsr</pre>
<pre>    incf     fsr</pre>
<pre>    movf     AccA  + 1, w</pre>
<pre>    subwf    indf, w</pre>
<pre>    btfss    _z</pre>
<pre>    return</pre>
<pre>    decf     fsr</pre>
<pre>    movf     AccA, w</pre>
<pre>    subwf    indf, w</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>; Add pointer Work register to accumulator A</pre>
<pre>AddAW</pre>
<pre>    movwf    fsr</pre>
<pre>    movf     indf, w</pre>
<pre>    addwf    AccA</pre>
<pre>    btfsc    _c</pre>
<pre>    incf     AccA + 1</pre>
<pre>    incf     fsr</pre>
<pre>    movf     indf, w</pre>
<pre>    addwf    AccA + 1</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>; Subtract pointer Work register from accumulator A</pre>
<pre>SubAW</pre>
<pre>    movwf    fsr</pre>
<pre>    movf     indf, w</pre>
<pre>    subwf    AccA</pre>
<pre>    btfss    _c</pre>
<pre>    decf     AccA + 1</pre>
<pre>    incf     fsr</pre>
<pre>    movf     indf, w</pre>
<pre>    subwf    AccA + 1</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>; Subtract accumulator A from pointer Work register</pre>
<pre>SubWA</pre>
<pre>    movwf    fsr</pre>
<pre>    movf     AccA, w</pre>
<pre>    subwf    indf</pre>
<pre>    incf     fsr</pre>
<pre>    btfss    _c</pre>
<pre>    decf     indf</pre>
<pre>    movf     AccA + 1, w</pre>
<pre>    subwf    indf</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>IncBCD</pre>
<pre>; Input:  AccB        Base  address</pre>
<pre>;         AccB + 1    Index</pre>
<pre>; Output: None</pre>
<pre>    movf      fsr, w        ; Store FSR</pre>
<pre>    movwf     w1</pre>
<p><code></code></p>
<pre>    bcf      _c</pre>
<pre>    rrf      AccB + 1, w    ; Get address</pre>
<pre>    addwf    AccB, w</pre>
<pre>    movwf    fsr</pre>
<p><code></code></p>
<pre>    btfsc    AccB + 1, 0</pre>
<pre>    swapf    indf</pre>
<p><code></code></p>
<pre>    movlw    9</pre>
<pre>    subwf    indf</pre>
<pre>    movlw    10</pre>
<pre>    btfss    _dc</pre>
<pre>    addwf    indf</pre>
<p><code></code></p>
<pre>    btfsc    AccB + 1, 0</pre>
<pre>    swapf    indf</pre>
<p><code></code></p>
<pre>    movf     w1, w          ; Restore FSR</pre>
<pre>    movwf    fsr</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>Mul_8</pre>
<pre>; Input:  AccA           Multiplicand</pre>
<pre>;         AccB           Multiplicator</pre>
<pre>; Output: AccA+1:AccA    Result</pre>
<p><code></code></p>
<pre>    clrf     W1</pre>
<pre>    bsf      W1, 3</pre>
<pre>    clrf     AccA + 1</pre>
<pre>    movf     AccB, w</pre>
<pre>    rrf      AccA</pre>
<pre>Mul_SL0001</pre>
<pre>    btfsc    _c</pre>
<pre>    addwf    AccA + 1</pre>
<pre>    rrf      AccA + 1</pre>
<pre>    rrf      AccA</pre>
<pre>    decfsz   W1</pre>
<pre>    goto     Mul_SL0001</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>Div_8</pre>
<pre>; Input:  AccA        Dividend</pre>
<pre>;         AccB        Divisor</pre>
<pre>; Output: AccA        Result</pre>
<pre>;         AccA+1      Remainder</pre>
<p><code></code></p>
<pre>    movlw    8</pre>
<pre>FDiv_Byte</pre>
<pre>    movwf    W1</pre>
<pre>    clrf     AccA + 1</pre>
<pre>Div_SL0001</pre>
<pre>    rlf      AccA</pre>
<pre>    rlf      AccA + 1</pre>
<p><code></code></p>
<pre>    movf     AccB, w</pre>
<pre>    subwf    AccA + 1, w</pre>
<pre>    btfsc    _c</pre>
<pre>    movwf    AccA + 1</pre>
<p><code></code></p>
<pre>    decfsz   W1</pre>
<pre>    goto     Div_SL0001</pre>
<pre>    rlf      AccA</pre>
<pre>    return</pre>
<p><code></code></p>
<pre>FDiv_8</pre>
<pre>    movlw    16</pre>
<pre>    goto     FDiv_Byte</pre>
<p><code></code></p>
<pre>Div_16_8</pre>
<pre>; Input:  AccA+1:AccA    Dividend</pre>
<pre>;         AccB           Divisor</pre>
<pre>; Output: AccA+1:AccA    Result</pre>
<pre>;         AccB+1         Remainder</pre>
<p><code></code></p>
<pre>    clrf     W1</pre>
<pre>    bsf      W1, 4</pre>
<pre>    clrf     AccB + 1</pre>
<pre>Div_SL0002</pre>
<pre>    rlf      AccA</pre>
<pre>    rlf      AccA + 1</pre>
<pre>    rlf      AccB + 1</pre>
<p><code></code></p>
<pre>    movf     AccB, w</pre>
<pre>    subwf    AccB + 1, w</pre>
<pre>    btfsc    _c</pre>
<pre>    movwf    AccB + 1</pre>
<p><code></code></p>
<pre>    decfsz   W1</pre>
<pre>    goto     Div_SL0002</pre>
<pre>    rlf      AccA</pre>
<pre>    rlf      AccA + 1</pre>
<pre>    return</pre>
<p><code></code></p>
]]></content:encoded>
			<wfw:commentRss>http://stonestreem.com/pic-arithmetic-16-bit/feed/</wfw:commentRss>
		</item>
		<item>
		<title>I2C for 8051</title>
		<link>http://stonestreem.com/i2c-for-8051/</link>
		<comments>http://stonestreem.com/i2c-for-8051/#comments</comments>
		<pubDate>Tue, 26 Jun 2007 20:36:38 +0000</pubDate>
		<dc:creator>peorex</dc:creator>
		
		<category><![CDATA[Assembler]]></category>

		<guid isPermaLink="false">http://helius.icnhost.net/~peorex/blog/?p=10</guid>
		<description><![CDATA[Target:    8051
Content of .asm file
; ***************************************************************
; This collection of routines allows an 80x51 microcontroller
; to read and write the I2C devices
; FOSC = 24MHz.
; ***************************************************************

_R         EQU        0

SDA        EQU   [...]]]></description>
			<content:encoded><![CDATA[<p>Target:    8051</p>
<p>Content of <code>.asm</code> file</p>
<pre>; ***************************************************************</pre>
<pre>; This collection of routines allows an 80x51 microcontroller</pre>
<pre>; to read and write the I2C devices</pre>
<pre>; FOSC = 24MHz.</pre>
<pre>; ***************************************************************</pre>
<p><code></code></p>
<pre>_R         EQU        0</pre>
<p><code></code></p>
<pre>SDA        EQU        P3.1</pre>
<pre>SCL        EQU        P3.7</pre>
<p><code><br />
</code></p>
<pre>        RSEG RCODE</pre>
<p><code><br />
</code></p>
<pre>PUBLIC    I2C_Start</pre>
<pre>; void I2C_Start (void);</pre>
<pre>; Send START, defined as high-to-low SDA with SCL high</pre>
<pre>; Input:  None</pre>
<pre>; Output: None</pre>
<pre>; Registers destroyed: A, PSW, R1</pre>
<p><code></code></p>
<pre>I2C_Start:</pre>
<pre>        setb    SDA</pre>
<pre>        mov     A, #5          ; wait Tr + Tsu:dat, prevent "STOP"</pre>
<pre>        mov     R1, #7</pre>
<pre>        setb    SCL            ; release bus</pre>
<pre>        djnz    R1, $          ; wait Tr + Tsu:sta (&gt; 5.7us)</pre>
<p><code></code></p>
<pre>        clr     SDA            ; high-to-low SDA with SCL high</pre>
<pre>        mov     R1, A</pre>
<pre>        djnz    R1, $          ; wait Tf + Thd:sta (&gt; 4.3us)</pre>
<p><code></code></p>
<pre>        clr     SCL            ; SCL low, enable data change</pre>
<pre>        djnz    ACC, $         ; wait Tf + Tlow (&gt; 5us)</pre>
<pre>        ret</pre>
<p><code><br />
</code></p>
<pre>PUBLIC    I2C_Stop</pre>
<pre>; void I2C_Stop (void);</pre>
<pre>; Send STOP, defined as low-to-high SDA with SCL high</pre>
<pre>; Input:  None</pre>
<pre>; Output: None</pre>
<pre>; Registers destroyed: R1</pre>
<pre>; SCL expected low on entry. Return with SCL, SDA high</pre>
<p><code></code></p>
<pre>I2C_Stop:</pre>
<pre>        clr     SDA</pre>
<pre>        nop                    ; wait Tf + Tsu:dat, prevent "START"</pre>
<pre>        mov     R1, #7</pre>
<pre>        setb    SCL            ; prepare for "STOP"</pre>
<pre>        djnz    R1, $          ; wait Tr + Tsu:sto (&gt; 5.7us)</pre>
<p><code></code></p>
<pre>        setb    SDA            ; low-to-high SDA with SCL high</pre>
<pre>        ret</pre>
<p><code><br />
</code></p>
<pre>PUBLIC    I2C_OUTB</pre>
<pre>; bit I2C_OUTB (data BYTE b);</pre>
<pre>; Shift out a byte to the device, most significant bit first.</pre>
<pre>;     Read ACK or NAK from the device.</pre>
<pre>; Input:  R4 - Byte to be shifted out</pre>
<pre>; Output: Carry flag - Clear if there is not acknowledge</pre>
<pre>; Registers destroyed: A, PSW, R1, R4</pre>
<pre>; SCL expected low on entry. Return with SCL low</pre>
<p><code></code></p>
<pre>I2C_OUTB:</pre>
<pre>        setb    C              ; CY = 1, get ACK bit</pre>
<pre>        mov     A, R4          ; byte to be shifted in A</pre>
<pre>        sjmp    I2C_Shift</pre>
<p><code><br />
</code></p>
<pre>PUBLIC    I2C_INB</pre>
<pre>; BYTE I2C_INB (data BYTE SendACK);</pre>
<pre>; Shift in a byte from the device, most significant bit first.</pre>
<pre>;     Send ACK or NAK to the device.</pre>
<pre>; Input:  R4 - 0 - Send NAK to device</pre>
<pre>;              else - Send ACK to device</pre>
<pre>; Output: R4 - Received data byte from device</pre>
<pre>; Registers destroyed: A, PSW, R1</pre>
<pre>; SCL expected low on entry. Return with SCL low</pre>
<p><code></code></p>
<pre>I2C_INB:</pre>
<pre>        mov     A, R4</pre>
<pre>        add     A, #0FFh       ; move ACK bit into CY</pre>
<pre>        cpl     C</pre>
<pre>        mov     A, #0FFh       ; SDA high</pre>
<pre>I2C_Shift:</pre>
<pre>        mov     R1, #9         ; bit counter, 8 bits + ACK</pre>
<pre>L_Next_Bit:</pre>
<pre>        rlc     A              ; move bit7 into CY</pre>
<pre>        mov     SDA, C         ; output bit</pre>
<pre>        mov     R4, #2</pre>
<pre>        djnz    R4, $          ; wait Tr + Tsu:dat + more (3us)</pre>
<p><code></code></p>
<pre>        setb    SCL            ; raise clock</pre>
<pre>        mov     R4, #4</pre>
<pre>        djnz    R4, $          ; wait Tr + Thigh (5us)</pre>
<p><code></code></p>
<pre>        mov     C, SDA         ; input bit</pre>
<pre>        clr     SCL            ; drop clock</pre>
<pre>        djnz    R1, L_Next_Bit ; now wait Tf + Tlow (&gt; 5us)</pre>
<p><code></code></p>
<pre>        cpl     C              ; ACK bit</pre>
<pre>        mov     R4, A</pre>
<pre>        ret</pre>
<p><code><br />
</code></p>
<pre>        END</pre>
<p><code><br />
</code><br />
Example of <code>.c</code> routines for interfacing DS1307, block Read/Write functions<br />
<code><br />
</code></p>
<pre>bit RTCWriteBlock (data BYTE Addr, data BYTE data *p, data BYTE Count)</pre>
<pre>{</pre>
<pre>    bit    Result;</pre>
<p><code></code></p>
<pre>    Result = FALSE;</pre>
<p><code></code></p>
<pre>    I2C_Start ();</pre>
<pre>    if (I2C_OUTB (0xD0))                            // write</pre>
<pre>    {</pre>
<pre>        if (I2C_OUTB (Addr))                        // addr</pre>
<pre>        {</pre>
<pre>            Result = TRUE;</pre>
<pre>            for (; Count; Count--)</pre>
<pre>            {</pre>
<pre>                if (!I2C_OUTB (*p++))</pre>
<pre>                {</pre>
<pre>                    Result = FALSE;</pre>
<pre>                    break;</pre>
<pre>                }</pre>
<pre>            }</pre>
<pre>        }</pre>
<pre>    }</pre>
<pre>    I2C_Stop ();</pre>
<p><code></code></p>
<pre>    return Result;</pre>
<pre>}</pre>
<p><code><br />
</code></p>
<pre>bit RTCReadBlock (data BYTE Addr, data BYTE data *p, data BYTE Count)</pre>
<pre>{</pre>
<pre>    bit    Result;</pre>
<p><code></code></p>
<pre>    Result = FALSE;</pre>
<p><code></code></p>
<pre>    I2C_Start ();</pre>
<pre>    if (I2C_OUTB (0xD0))                            // write</pre>
<pre>    {</pre>
<pre>        if (I2C_OUTB (Addr))                        // addr</pre>
<pre>        {</pre>
<pre>            Result = TRUE;</pre>
<pre>            if (Count)</pre>
<pre>            {</pre>
<pre>                I2C_Start ();</pre>
<pre>                if (Result = I2C_OUTB (0xD1))        // read</pre>
<pre>                {</pre>
<pre>                    while (Count)</pre>
<pre>                    {</pre>
<pre>                        Count--;</pre>
<pre>                        *p++ = I2C_INB (Count);</pre>
<pre>                    }</pre>
<pre>                }</pre>
<pre>            }</pre>
<pre>        }</pre>
<pre>    }</pre>
<pre>    I2C_Stop ();</pre>
<p><code></code></p>
<pre>    return Result;</pre>
<pre>}</pre>
<p><code></code></p>
]]></content:encoded>
			<wfw:commentRss>http://stonestreem.com/i2c-for-8051/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
