![]() |
發(fā)布時間: 2021-9-6 21:05
正文摘要:網(wǎng)上找的,PIC16F873A單片機eeprom 24C02-24C64數(shù)據(jù)抄寫程序,用MPLAB IDE編譯,報告一大堆錯誤,求助大蝦幫忙看看這個匯編程序到底錯在哪里?程序如下: ;****************I2C總線EPROM數(shù)據(jù)抄寫程序** ... |
我給你來個 C 程序試試
|
shumivan 發(fā)表于 2021-9-8 16:03 要提高編程能力,匯編是必須要學(xué)會的, 可以平時不用, 但必須要會, debug的時候,有問題,看一眼編譯出來的匯編,立馬就能明白是什么原因造成的,不會的話,會走很多彎路, 然后,C語言里不好控制的時序問題,進到匯編跟砍瓜切菜一樣。 程序主體都用C, 有些地方(尤其是涉及底層操作的地方)用點匯編,我覺得還是比較有必要的。 |
怎么還在用匯編,我已經(jīng)全忘完了,只會C了 |
Y_G_G 發(fā)表于 2021-9-6 22:29 謝謝您的回復(fù),受教了。最近在寫E2PROM復(fù)制器的程序,就是將兩個24C32,將其中一個里面的數(shù)據(jù),通過單片機復(fù)制到另一個里面去,可總是寫不好,思路一直混亂。請大神給指點個好的思路,按您的思路,我在重新寫程序。 |
代碼不全吧 |
學(xué)PIC的本來就少,你還是用匯編的,而且一個漢字注釋都沒有,你覺得別人能看明白? 這是我以前寫的24C02的驗證程序,已經(jīng)在開發(fā)板上實際驗證過的,你對比一下吧 我已經(jīng)好久沒有用PIC匯編了,指令都快忘記完了 #include <p16f877a.inc> ;包含了PIC16F877A的寄存器聲稱文件 __CONFIG _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _BOREN_ON & _LVP_OFF & _CPD_OFF & _WRT_OFF & _CP_OFF;配置設(shè)置生成的代碼 CBLOCK 020H ;定義連續(xù)變量 COUNT ;計數(shù)用的 DEL1 ;用在延時子程序中 DEL2 ;用在延時子程序中 DEL3 ; DISP_ADDR ;顯示地址用寄存器 DISP_DATA ;顯示數(shù)據(jù)用寄存器 LED_1 ;七段碼的個位 LED_10 ;七段碼的十位 LED_100 ;七段碼的百位 DIV_DATA ;除法用寄存器 DATA_BUF ;數(shù)據(jù)寫入和讀出用的緩沖器 SESHI ;測試用寄存器 ENDC ;結(jié)束定義 #define S1 PORTB,0 ;按置S1 #define S2 PORTB,1 ;按置S2 #define S3 PORTB,2 ;按置S3 #define COM0 PORTD,0 ; #define COM1 PORTD,1 ; #define COM2 PORTD,2 ; #define COM3 PORTD,3 ;定義幾個顯示的RA端口 #define CY STATUS,0 ;C為標志位,減法有借位=0,無借位=1 #define SCL PORTD,4 ;時鐘信號線 #define SDA PORTD,7 ;數(shù)據(jù)信號線 #define SDA_C TRISD,7 ;數(shù)據(jù)方向控制寄存器 ORG 00H ; NOP ;這條指令是仿真要有的 GOTO MAIN ;跳過中斷子程序 ORG 020H ; MAIN BSF STATUS,RP0 ;RP0=1,RP1=0,指令選擇BANK1 BCF STATUS,RP1 ; ;=============================================================================== ;以下是針對BANK1的操作========================================================== MOVLW 0FFH ; MOVWF TRISB ;PORTB 作為輸入 BCF OPTION_REG,7 ;啟用RB的上拉電阻 BCF INTCON,3 ; MOVLW 00H ; MOVWF TRISC ;PORTC 作為輸出-數(shù)據(jù) MOVWF TRISD ;PORTD 作為輸出-位選 CLRF TRISE ;RD工作于正常的IO模式 ;以下是針對BANK0的操作========================================================== BCF STATUS,RP0 ;選擇BANK0 CLRF PORTC ; CLRF PORTD ;=============================================================================== MOVLW D'123' ;默認數(shù)據(jù)是000 MOVWF DISP_DATA MOVLW D'8' ;默認地址是0 MOVWF DISP_ADDR ;=============================================================================== LOOP BTFSS S1 ;按鍵1是1就跳過下一條指令 CALL S1_DISP ;調(diào)用S1處理程序 BTFSS S2 ;S2沒有按下就跳過下一條指令 CALL S2_DISP ;按下就調(diào)用S2處理子程序 BTFSS S3 ;S3沒有按下就跳過下一條指令 CALL S3_DISP ;按下就中用S3處理子程序 CALL DISPLAY ;顯示 GOTO LOOP ;主程序在這循環(huán) ;=============================================================================== READ_DATA;讀出一個字節(jié)---------------------------------------------------------- BCF SCL ; BSF SDA ;SDA1 BSF SCL ; 1 BCF SDA ;SDA1>>0,起始信號 BCF SCL ; ;----------------------------------------------------------------------- MOVLW 0A0H ;0A0H為寫命令,完整的輸入8個位的地址 CALL WRITE_BYTE ;寫入"寫"模式指令 MOVFW DISP_ADDR ;寫入地址 CALL WRITE_BYTE ; ;----------------------------------------------------------------------- BCF SCL ; BSF SDA ;SDA1 BSF SCL ; BCF SDA ;SDA1>>0,起始信號 BCF SCL ; ;----------------------------------------------------------------------- MOVLW 0A1H ;0A1H為讀命令,完整的輸入8個位的地址 CALL WRITE_BYTE ;寫入"寫"模式指令 CALL READ_BYTE ;讀出一個字節(jié) MOVWF DISP_DATA ;----------------------------------------------------------------------- BCF SCL ; BCF SDA ;SDA0 BSF SCL ; BSF SDA ;SDA0>>1,停止信號 BCF SCL ; BCF SDA RETURN ;=============================================================================== WRITE_DATA;寫入一個字節(jié)--------------------------------------------------------- BCF SCL ; BSF SDA ;SDA1 BSF SCL ; 1 BCF SDA ;SDA1>>0,起始信號 BCF SCL ; ;----------------------------------------------------------------------- MOVLW 0A0H ;0A0H為寫命令,完整的輸入8個位的地址 CALL WRITE_BYTE ;寫入"寫"模式指令 MOVFW DISP_ADDR ;寫入地址 CALL WRITE_BYTE ; MOVFW DISP_DATA CALL WRITE_BYTE ;----------------------------------------------------------------------- BCF SCL ; BCF SDA ;SDA0 BSF SCL ; BSF SDA ;SDA0>>1,停止信號 BCF SCL ; BCF SDA RETURN ;=============================================================================== READ_BYTE;讀一個字節(jié)處理程序*************************************************** BSF STATUS,RP0 ;選擇BANK1 BSF SDA_C ;SDA作為輸入 BCF STATUS,RP0 ;選擇BANK0 MOVLW D'8' MOVWF COUNT ;要讀出的字節(jié)是8 BCF SCL ;時鐘0 R_B_LOOP BCF CY ; BSF SCL ;時鐘上升沿 BTFSC SDA ;是0就跳過下一條指令 BSF CY ;是1,置位緩沖器的0位 RLF DATA_BUF,F ;左移一次,從最高位開始讀出 BCF SCL ;時鐘下降 DECFSZ COUNT,F ;檢測是否完成了8個字節(jié) GOTO R_B_LOOP ; MOVFW DATA_BUF ;讀取到的數(shù)據(jù)保存到W BSF STATUS,RP0 ;選擇BANK1 BCF SDA_C ;SDA作為輸出 BSF SDA ; BSF SCL ; BCF SCL ; BCF SDA ; BCF STATUS,RP0 ;選擇BANK0 RETURN ;=============================================================================== WRITE_BYTE;寫入一個字節(jié)********************************************************* BSF STATUS,RP0 ;選擇BANK1 BCF SDA_C ;SDA作為輸出 BCF STATUS,RP0 ;選擇BANK0 MOVWF DATA_BUF ; MOVLW D'8' ; MOVWF COUNT ; BCF SCL ;時鐘0 W_B_LOOP BCF SDA ;清除輸出線 BTFSC DATA_BUF,7 ;最高位如果是0就跳過下一條指令 BSF SDA ;最高位是1,置位D_I CALL DELAY_5MS ;延時5mS BSF SCL ;時鐘上升 CALL DELAY_5MS BCF SCL ;時鐘下降 CALL DELAY_5MS RLF DATA_BUF,F ;左移一次, DECFSZ COUNT,F ;檢測是否傳送完成8個字節(jié) GOTO W_B_LOOP ;沒有,跳去循環(huán) ;應(yīng)答--------------------------------------------------------------- BSF SDA BSF STATUS,RP0 ;選擇BANK1 BSF SDA_C ;SDA作為輸入 BCF STATUS,RP0 ;選擇BANK0 BSF SCL ; CALL DELAY_5MS ;延時5mS BTFSC SDA ;SDA為0就跳過下一條指令 GOTO $-1 ;SDA為1,跳動循環(huán) BSF STATUS,RP0 ;選擇BANK1 BCF SDA_C ;SDA作為輸出 BCF STATUS,RP0 ;選擇BANK0 BCF SCL ; BCF SDA RETURN ;=============================================================================== ;按一下,數(shù)據(jù)顯示就加1 S1_DISP;S1處理程序************************************************************** BTFSS S1 GOTO $-1 INCF DISP_DATA,F ;數(shù)據(jù)加1,保存到F CALL WRITE_DATA ;寫入數(shù)據(jù) CALL DELAY_5MS CALL READ_DATA ;再讀出數(shù)據(jù) RETURN ;=============================================================================== S2_DISP;S2處理程序************************************************************** BTFSS S2 GOTO $-1 DECF DISP_DATA,F ;數(shù)據(jù)減1,保存到F CALL WRITE_DATA ;寫入數(shù)據(jù) CALL DELAY_5MS CALL READ_DATA ;再讀出數(shù)據(jù) RETURN ;=============================================================================== ;按一下,地址就加1,最大顯示到9 S3_DISP ;S2處理程序************************************************************* BTFSS S3 GOTO $-1 INCF DISP_ADDR,F ;地址的值加1 MOVLW D'10' ;10傳送到W SUBWF DISP_ADDR,W ;地址-W,結(jié)果保存到W BTFSC CY ;c進位為1,地址的值就是大于等于9了 CLRF DISP_ADDR ;地址清零 CALL READ_DATA ;再讀出數(shù)據(jù) RETURN ;=============================================================================== ;顯示程序*********************************************************************** DISPLAY BCF STATUS,RP0 ;選擇BANK0 CLRF LED_1 CLRF LED_10 CLRF LED_100 ;除法部分----------------------------------------------------------------------- MOVFW DISP_DATA ;送顯示數(shù)據(jù)到W DIV_100 MOVWF DIV_DATA ;W的值保存到寄存器 MOVLW D'100' ;W等于100 SUBWF DIV_DATA,W ;數(shù)據(jù)減去100,結(jié)果保存在W BTFSS STATUS,C ;C是1就跳過下一條指令,C=1,F就是大,還可以再減法 GOTO DIV_10 ;C=0,F已經(jīng)小于100,跳轉(zhuǎn)到減10 INCF LED_100,F ;F大,百位加1 GOTO DIV_100 ;再去減一次 ;------------------------------------------------------------------------------- DIV_10 MOVLW D'10' ;W等于10 SUBWF DIV_DATA,W ;DIV_DATRA-10= BTFSS STATUS,C ;C=1,DIV_DATA就比W大 GOTO DIV_1 ; INCF LED_10,F ; MOVWF DIV_DATA ;W數(shù)據(jù)保存到寄存器 GOTO DIV_10 ; ;------------------------------------------------------------------------------- DIV_1 MOVFW DIV_DATA MOVWF LED_1 ;顯示部分----------------------------------------------------------------------- MOVFW LED_1 ;數(shù)據(jù)送到W CALL TAB_LED ;查表 MOVWF PORTC ;W送到端口 BCF COM0 ;低電平,亮燈 CALL DELAY_5MS ;延時5mS BSF COM0 ;高電平,關(guān)燈 ;----------------------------------------------------------------------- MOVFW LED_10 ; CALL TAB_LED ;查表 MOVWF PORTC ; BCF COM1 ; CALL DELAY_5MS ; BSF COM1 ; ;----------------------------------------------------------------------- MOVFW LED_100 ; CALL TAB_LED ;查表 MOVWF PORTC ; BCF COM2 ; CALL DELAY_5MS ; BSF COM2 ; ;----------------------------------------------------------------------- MOVFW DISP_ADDR ;顯示地址 CALL TAB_LED ;查表 MOVWF PORTC ; BCF COM3 ; CALL DELAY_5MS ; BSF COM3 ; ;----------------------------------------------------------------------- RETURN ; ;=============================================================================== ;5mS延時程序******************************************************************** DELAY_5MS MOVLW 3H MOVWF DEL3 MOVLW D'2' ; MOVWF DEL1 ; LOOP_5MS1 MOVLW D'1' ; MOVWF DEL2 ; LOOP_5MS2 DECFSZ DEL2,F ; GOTO LOOP_5MS2 ;100x2=200uS DECFSZ DEL1,F ; GOTO LOOP_5MS1 ; DECFSZ DEL3 GOTO LOOP_5MS1 ; RETURN ; ;=============================================================================== ;BCD碼的表********************************************************************** TAB_LED ADDWF PCL,F ;把W的內(nèi)容疊加到PCL程序計數(shù)器上 RETLW 0FCH ;0 RETLW 060H ;1 RETLW 0DAH ;2 RETLW 0F2H ;3 RETLW 066H ;4 RETLW 0B6H ;5 RETLW 0BEH ;6 RETLW 0E0H ;7 RETLW 0FEH ;8 RETLW 0F6H ;9 END |
Powered by 單片機教程網(wǎng)