list p=16f628A ;************************************************************** ;* Pinbelegung ;* ---------------------------------- ;* PORTA: 0 SDA out ;* 1 CLK in ;* 2 SDA in ;* 3 CLK out ;* 4 - ;* 5 - ;* 6 - ;* 7 - ;* ;* PORTB: 0 : 7segment kijelzõ anódok ;* 1 ;* 2 ;* 3 ;* 4 ;* 5 ;* 6 ;* ;************************************************************** ; ;sprut (zero) Bredendiek 12/2003 ; ; Temperaturmessung mit LM75 ; ; Prozessor 16F628 ; ; Prozessor-Takt 10 MHz ; ; IIC am PortA ; 7 segment PortB ; ; ; ; ;********************************************************** ; Includedatei für den 16F628 einbinden #include ERRORLEVEL -302 ;SUPPRESS BANK SELECTION MESSAGES ; Configuration festlegen: ; Power on Timer, kein Watchdog, HS-Oscillator, kein Brown out, kein LV-programming __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_OFF & _BODEN_OFF & _INTRC_OSC_NOCLKOUT & _LVP_OFF & _MCLRE_ON ; Variablen festlegen buf equ 0x22 ; puffer für I2C Temp_h equ 0x23 ; Temperatur in grad Temp_l equ 0x24 ; 0.5°C auf Bit 7 count equ 0x2B ; universeller zähler loops equ 0x2C ; timer für wait loops2 equ 0x2D ; timer für wait ; 8-Bit Rechenregister xw0 EQU 0x32 ;LSB ; 8-Bit Rechenregister f0 EQU 0x3A ;LSB ; Dezimalstellen HdH EQU 0x4B ;3 Hunderter HdZ EQU 0x4C ;2 Zehner HdE EQU 0x4D ;1 Einer HdX EQU 0x4E ; Puffer für eine Dezimalstelle dig2 equ 0x51 dig3 equ 0x52 One equ 0x53 W_TEMP equ 0x54 STATUS_TEMP equ 0x55 ; für I2C #define SDAo PORTA,0 ;Daten output #define SDAi PORTA,2 ;Daten input #define SCL PORTA,3 ;Takt #define SCLo PORTA,3 ;Takt #define SCLi PORTA,1 ;Takt input ;******************************************************** org 0 goto Init ;******************************************************** ; Das Programm beginnt mit der Initialisierung org 0x04 goto ISR Init bsf STATUS, RP0 ; Bank 1 movlw B'00000000' ; PortB alle outputs movwf TRISB movlw B'00110110' ; PortA 0,3,6,7 out a többi input movwf TRISA bcf STATUS, RP0 ; Bank 0 clrf PORTA clrf PORTB banksel PORTA CLRF PORTA ;Initialize PORTA by setting MOVLW 0X07 ;Turn comparators off MOVWF CMCON banksel TRISA movlw b'00010110' movwf TRISA clrf TRISB movlw b'10000100' movwf OPTION_REG banksel PORTA movlw .96 bsf PORTA,6 movwf TMR0 movlw b'10100000' movwf INTCON clrf One clrf PORTA mainloop ;Temp messen call i2c_on ; Bus aktiv movlw H'91' ; 1001 0001 call i2c_tx ; LM75 zum lesen adressieren call i2c_rxack movwf Temp_h ; Byte in Speicherzelle Datenpuffer retten call i2c_rx movwf Temp_l ; Byte in Speicherzelle Datenpuffer retten call i2c_off ; Bus freigeben ; Temp anzeigen movfw Temp_h movwf f0 call Hex2Dez8 movlw D'250' ; 250 ms Pause movfw HdZ ;Amit ide írok azt kiirja a kijelzõkre movwf dig2 movfw HdE movwf dig3 call WAIT goto mainloop ;***************************************************************** ; Routinen für I2C ; Bus übernehmen i2c_on ; W senden i2c_tx ; Byte empfangen i2c_rx (nach w und RXData und SSPBUF) ; Bus freigeben i2c_off ;***************************************************************** i2c_reset bsf SDAo bsf SCLo nop movlw 9 movwf buf i2c_reset1 nop bcf SCLo nop nop nop nop nop bsf SCLo nop decfsz buf, f goto i2c_reset1 nop call i2c_on nop bsf SCLo nop nop bcf SCLo nop call i2c_off return i2c_on ; wenn SDA und SCL beide High, dann SDA auf Low ziehen bsf SCL ; failsave bsf SDAo ; failsave ;testen, ob der Bus frei ist btfss SCLi goto i2c_on ; Taktleitung frei? btfss SDAi goto i2c_on ; Datenleitung frei? bcf SDAo nop bcf SCL return i2c_tx ; w über i2c senden ; takt ist unten ; daten sind unten call WrI2cW ; 8 Bit aus W nach I2C ; ACK muß nun empfangen werden ; Takt ist low bsf SDAo ;Datenleitung loslassen bsf SCL ; ACK Takt high i2c_tx2 btfss SCLi goto i2c_tx2 nop ;i2c_tx1 ; btfsc SDAi ; ACK empfangen? ; goto i2c_tx1 ; nein SDA ist high bcf SCL ; ja , Takt beenden bcf SDAo return i2c_rxack ; takt ist unten ; daten sind unten call RdI2cW ; 8 von I2C nach W ; Takt ist unten ; ACK muß nun gesendet werden bcf SDAo nop nop nop nop bsf SCL i2c_rxack1 btfss SCLi goto i2c_rxack1 nop bcf SCL bcf SDAo return i2c_rx ; takt ist unten ; daten sind unten call RdI2cW ; 8 von I2C nach W ; Takt ist unten ; kein ACK nop nop bsf SDAo nop bsf SCL i2c_rx1 btfss SCLi goto i2c_rx1 nop bcf SCL bcf SDAo return i2c_off ; SCL ist Low und SDA ist Low nop nop bsf SCL nop bsf SDAo return ;***************************************************** ; I2C-Peride ist 2,5 µs ; PIC-Zyklus ist 4/10MHz = 0,4µs ; -> Takt muß für 3 Zyklen H und für 3 Zyklen L sein ; + 1 Zyklus Reserve ;schiebt das Byte aus W in den I2C ; MSB zuerst ; 78 Takte WrI2cW ; Takt unten, Daten unten ; Datenbyte in w movwf buf movlw 8 movwf count ; 8 Bits WrI2cW1 ; Datenleitung setzen bcf SDAo rlf buf,f btfsc STATUS,C ; 0? bsf SDAo ; nein, 1 nop bsf SCL ; Taht high WrI2cW2 btfss SCLi goto WrI2cW2 bcf SCL ; Takt low decfsz count,f ; 8 Bits raus? goto WrI2cW1 ; nein return ; ja ;liest das Byte aus I2C nach W ; takt ist unten ; daten sind unten RdI2cW clrf buf movlw 8 movwf count bsf SDAo ;failsave RdI2cW1 nop clrc btfsc SDAi setc rlf buf,f bsf SCL ; Takt high RdI2cW2 btfss SCLi goto RdI2cW2 bcf SCL ; Takt low decfsz count,f ; 8 Bits drinn? goto RdI2cW1 ; nein movfw buf ; ja fertig return ;***************************************************************** ;Zeitverzögerung um loops * 1 ms ; 10 MHz externer Takt bedeutet 2,5 MHz interner Takt ; also dauert 1 ms genau 2500 Befehle ; 250 Schleifen a 10 Befehle sind 2500 Befehle = 1 ms WAIT top movlw .250 ; timing adjustment variable (1ms) movwf loops2 top2 nop ; sit and wait nop nop nop nop nop nop decfsz loops2, F ; inner loops complete? goto top2 ; no, go again ; decfsz loops, F ; outer loops complete? goto top ; no, go again retlw 0 ; yes, return from subWAIT Hex2Dez8 ; 8-bit (f1) in 3-stellen BCD movlw 0x64 movwf xw0 call Hex2Dez1 ; 100er movfw HdX movwf HdH movlw 0x0A movwf xw0 call Hex2Dez1 ; 10er movfw HdX movwf HdZ movfw f0 movwf HdE return Hex2Dez1 clrf HdX decf HdX, f HdLoop incf HdX, f movf xw0, w ; f0=f0-xw0 subwf f0, f btfsc STATUS, C ;Überlauf goto HdLoop ;Stelle 1 mehr movf xw0,W ; low byte addwf f0,F ; low byte add return ISR MOVWF W_TEMP ;copy W to temp register, ;could be in either bank SWAPF STATUS,W ;swap status to be saved into W BCF STATUS,RP0 ;change to bank 0 regardless ;of current bank MOVWF STATUS_TEMP ;save status to bank 0 Movlw .96 movwf TMR0 bcf INTCON,T0IF bcf PORTA,6 bcf PORTA,7 movf One,f btfsc STATUS,Z goto Msdon Lsdon bcf One,0 movlw high Bcdto7seg movwf PCLATH movf dig3,w call Bcdto7seg movwf PORTB banksel PORTA bsf PORTA,7 SWAPF STATUS_TEMP,W ;swap STATUS_TEMP register ;into W, sets bank to original ;state MOVWF STATUS ;move W into STATUS register SWAPF W_TEMP,F ;swap W_TEMP SWAPF W_TEMP,W ;swap W_TEMP into W retfie Msdon bsf One,0 movlw high Bcdto7seg movwf PCLATH movf dig2,w call Bcdto7seg movwf PORTB banksel PORTA bsf PORTA,6 SWAPF STATUS_TEMP,W ;swap STATUS_TEMP register ;into W, sets bank to original ;state MOVWF STATUS ;move W into STATUS register SWAPF W_TEMP,F ;swap W_TEMP SWAPF W_TEMP,W ;swap W_TEMP into W retfie org 0x300 Bcdto7seg addwf PCL,f dt 0X3F, 0X06, 0X5b, 0X4f, 0x66, 0x6d, 0x7d, 0x07,0x7f, 0x6f End