;************************************************************************
*
;* 以 PIC16F877A 為I2C Master 模式存取一串列式 EEPROM 的範例程式 *
;* *
;* Written by: Richard Yang *
;* Sr. Corporate Application Engineer *
;* Microchip Technology Inc. *
;* Date: Oct. 2nd '2002 *
;* Revision: 1.00 *
;************************************************************************
;*****************************************************************************************
; This source code provides a demonstration of the MSSP peripheral
; on the PIC16F87x MCU.
;
;
;*********** The subroutines for EEPROM *****************
;
; EE_Random_Read ; EEPROM Random address Read from EEPROM
; EE_SEQU_Read ; EEPROM Sequential Read form EEPROM
; EE_Ack_Check ; Polling current status of EEPROM
; EE_Page_Write ; Page Write function for EEPROM
; EE_Byte_Write ; Write a byte to EEPROM with address setting
;
;*********** The subroutines for I2C *****************
;
; Init_I2C_Master ; Initial I2C Module for Master Mode , 7-bit address
; StartI2C ; Send a START Condition !!
; StopI2C ; Send s STOP Condition
; RstartI2C ; Send a Repeat Start conditional to I2C
; Non_Ack ; Send a Non-acknowledge signal to I2C
; An_Ack ; Send a acknowledge signal to I2C
; Sebd_Byte ; Send a byte to I2C bus
; RecI2C ; Enable Read a byte form slave device
; I2C_Done : Wait the I2C completed the currect process
;
;*****************************************************************************************
list p=16f877a
#include ; ;*************************************** ; 定義變數在RAM的位址 ; CBLOCK 0x20 I2C_Ctrl I2C_Addr I2C_Data I2C_Page_Length D_Count ENDC cblock 0x40 I2C_Page_Buffer:8 I2C_SEQU_Buffer:8 endc ; ;*************************************** ; 定義中斷的暫存器位址 w_temp EQU 0x72 status_temp EQU 0x73 pclath_temp EQU 0x74 ; ;*************************************** ; 定義 I2C 的位址及腳位 ; EEPROM_CMD equ 0xA0 ; Device adress of Slave Point EE_Read equ .1 EE_Write equ .0 ; #define SCL PORTC,3 ; I2C SCL pin #define SDA PORTC,4 ; I2C SDA pin ; ;******************************************** ; Locates startup code @ the reset vector ;******************************************** Reset_Addr org 0x00 nop goto Main_Init ; org 0x04 goto ISR ; ;*************************************************************************** ;**** The Start Address of ISR is 0x004 ;**** "PUSH" & "POP" 的使用範例 : 適用於像 PIC16F877 有SHARE BANK 的PIC ;*************************************************************************** ISR Push movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register movwf status_temp ; save off contents of STATUS register movf PCLATH,W movwf pclath_temp ; ; Put your interrupt code here ; Pop movf pclath_temp,W movwf PCLATH movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f swapf w_temp,w ; restore pre-isr W register contents ; retfie ; return from interrupt ;---------------------------------------------------------------------- Main_Init pagesel Init_I2C_Master ; Set PAGE to PCLATH Register call Init_I2C_Master ; Init the MSSP for I2C Master ; banksel I2C_Ctrl movlw EEPROM_CMD ; Load EEPROM command address @ 0xA0 movwf I2C_Ctrl ; ; Main ; ;---------------------------------------------------------------------- ; ;* 以下的測試程式會先將一組數字(0x40-0x47)寫入到RMA0x40-0x47的位置 ;* 再用Page Write的方式將8個位元組的資料寫到 EEPROM 後 ;* 進行狀態的偵測EEPROM是否已完成寫入的動作,最後將剛寫 ;* 入的資料以Sequential Read的方式從EEPROM讀出來放在I2C_SEQU_Buffer中 ; Test_Page_RW movlw 0x08 movwf I2C_Page_Length movlw I2C_Page_Buffer _Fill_RAM movwf FSR movwf INDF incf FSR,W decfsz I2C_Page_Length,F goto _Fill_RAM ; Test_Page_Write ; banksel I2C_Ctrl movlw EEPROM_CMD ; Load EEPROM command address @ 0xA0 movwf I2C_Ctrl movlw 0x10 ; Select EEPROM location at 0x00 movwf I2C_Addr movlw .8 movwf I2C_Page_Length call EE_Page_Write ; call EE_Ack_Check ; banksel I2C_Ctrl movlw EEPROM_CMD ; Load EEPROM command address @ 0xA0 movwf I2C_Ctrl movlw 0x10 movwf I2C_Addr movlw .8 movwf I2C_Page_Length call EE_SEQU_Read ; goto $ ; ;--------------------------------------------------------- ; ;* 以下的測試程式會先寫入一個位元組的資料寫到 EEPROM 中 ;* 再進行狀態的偵測是否已完成寫入的動作,最後將剛寫 ;* 入的資料再從EEPROM讀出來放在I2C_Data暫存器中 ; Test_1byte_RW banksel I2C_Ctrl movlw EEPROM_CMD ; Load EEPROM command address @ 0xA0 movwf I2C_Ctrl movlw 0x00 ; Select EEPROM location at 0x00 movwf I2C_Addr movlw 0xAA ; Write data 0x5A to location 0x00 of EEPROM movwf I2C_Data call EE_Byte_Write ; Test2 call EE_Ack_Check ; Polling Acknowledge for next access ; banksel I2C_Data movlw 0x00 ; Clear I2C data buffer movwf I2C_Data ; Test3 banksel I2C_Ctrl movlw EEPROM_CMD ; Load EEPROM command address @ 0xA0 movwf I2C_Ctrl movlw 0x00 movwf I2C_Addr call EE_Random_Read ; goto $ ; ; ;****************************************************** ;* Random Read a Byte from EEPROM ;* ;* Input: ;* - I2C_Ctrl : Control Byte of EEPROM ;* - I2C_Addr : Location of EEPROM ;* Output: ;* - I2C_Data : Read Data from EEPROM ;****************************************************** ; ; Send Command for RANDOM READ : ; " Start+ 0xA0 + EE_Address + ReStart + 0xA1 + Read_Data + NAck + Stop " ; EE_Random_Read call StartI2C ; Set SSPCON2.SEN ; bcf I2C_Ctrl,0 ; set for write Command movf I2C_Ctrl,W ; Send Slave Address to I2C Bus call Send_Byte ; movf I2C_Addr,W ; Send out the Rendom address of EEPROM call Send_Byte ; call RstartI2C ; Send a Repeat Start to I2C ; bsf I2C_Ctrl,0 ; set for Read Command movf I2C_Ctrl,W ; Send Slave Address to I2C Bus call Send_Byte ; call RecI2C ; Enable I2C Receive ; BANKSEL SSPBUF movf SSPBUF,W ; Save to I2C_Data First !! movwf I2C_Data call Non_Ack ; Initial NACK Response !! call StopI2C ; Initial STOP Condition return ; ;*************************************************************** ;* Sequential Read from EEPROM ;* ;* Input: ;* - I2C_Ctrl : Control Byte of EEPROM ;* - I2C_Addr : Start Location of EEPROM ;* - I2C_Page_Length : How many byte need to read ;* Output: ;* - I2C_SEQU_Buffer : Sequential Read Data buffer ;* ;*************************************************************** ; ; Send Command for RANDOM READ : ; " Start+ 0xA0 + EE_Address + ReStart + 0xA1 + Read_Data + NAck + Stop " ; EE_SEQU_Read call StartI2C ; Set SSPCON2.SEN ; bcf I2C_Ctrl,0 ; set for write Command movf I2C_Ctrl,W ; Send Slave Address to I2C Bus call Send_Byte ; movf I2C_Addr,W ; Send out the Rendom address of EEPROM call Send_Byte ; call RstartI2C ; Send a Repeat Start to I2C ; bsf I2C_Ctrl,0 ; set for Read Command movf I2C_Ctrl,W ; Send Slave Address to I2C Bus call Send_Byte ; movlw I2C_SEQU_Buffer movwf FSR ; _Sequ_Loop call RecI2C ; Enable I2C Receive BANKSEL SSPBUF movf SSPBUF,W ; Save to I2C_Data First !! movwf INDF incf FSR,F decfsz I2C_Page_Length,F goto _Cont_Read goto _End_Read _Cont_Read call An_Ack goto _Sequ_Loop ; _End_Read call Non_Ack ; Initial NACK Response !! call StopI2C ; Initial STOP Condition return ; ;****************************************************** ;* EEPROM Acknowledge Polling ;* ;* -- The routine will polling the ACK ;* response from EEPROM ;* -- ACK=0 return ;* -- ACK=1 send Restart & loop check ;* ;****************************************************** ; EE_Ack_Check call StartI2C ; Set SSPCON2.SEN bcf I2C_Ctrl,0 ; Clear for Write Command movf I2C_Ctrl,W ; Send Slave Address to I2C Bus call Send_Byte _Ack_Polling BANKSEL SSPCON2 btfss SSPCON2,ACKSTAT ; Check ACKSTAT bit , 0 = ACK , 1 = NACK
上一篇:PIC16F84单片机产生两组PWM输出实例
下一篇:以C语言完成读写24LCxx系列的EEPROM的实例
推荐阅读最新更新时间:2024-10-25 05:41