原创 AT89S52模拟PT2272编码

2008-12-8 00:11 2980 6 6 分类: MCU/ 嵌入式

;;这是遥控发端编码板,编码1-256号。用AT89CS51模拟的,带有键盘
;程序作者:姬瑞江。
;时间:2005年8月16日。
;程序版本:Ver1.2兼容Ver1.0、Ver1.1
;程序功能:驱动LED显示。键盘输入。模拟PT2272编码,数据输出使能延时1.5S,优化时间算法使发送单个数据包时间缩短1/3;REST时间由Ver1.0的4分钟缩短1.8分钟。
;模拟PT2272串行数据输出和数据输出使能。


 


TF2 BIT 0CFH
EXF2 BIT 0CEH
RCLK BIT 0CDH
TCLK BIT 0CCH
EXEN2 BIT 0CBH
TR2 BIT 0CAH
C_T2 BIT 0C9H
CP_RL2 BIT 0C8H
T2CON DATA 0C8H
RCAP2L DATA 0CAH
RCAP2H DATA 0CBH
TL2 DATA 0CCH
TH2 DATA 0CDH
WDTC DATA 0C0H
WDTD DATA 86H
SFDT DATA 0F8H
SFAL DATA 0F9H
SFAH DATA 0FAH
SFCM DATA 0FBH
SFCF DATA 0F7H


        cbit            equ     3fh
 buffer  equ   40h
 codedata equ 41h ;41h-51h is code data
 counterconvert equ 36h
 counterBIT equ 39h
 counterT equ 38h
 Tcounter equ 37h
 ADDR  equ 35h
 DATA4  equ 34h
 key1  equ 52h
 key2  equ 53h
 key3  equ 54h
 key4  equ 55h
 keyposi  equ 56h
 memposi  equ 57h
 uartposi equ 58h
 uartbuf1 equ 59h
 uartbuf2 equ 60h
 uartbuf3 equ 62h
 uartflag equ 61h
 dispposi equ 63h
 addrbuf  equ 64h
 ;delayflag equ 65h
 EXMT  equ 2fh
 on  equ 0F0h ;开态PT2272的引脚Dout值为高4位,此设定F0H为4位都为高
 off  equ 000h ;关态PT2272的引脚Dout值为高4位,此设定00H为4位都为低
        EXMP BIT EXMT.0
 dataout equ P1.7  ;PCM输出引脚
 ampout equ p1.6  ;amp out



 timerH equ 0FFh  ;对于OSC=12Mhz时PCM输出的定时器设定值,
 timerL equ 038h  ;timerH为高字节,timerL为低字节
 write equ 10100000B ;EEPROM写入命令字
 read equ 10100001B ;EEPROM读出命令字



 org 00h  ;程序总入口
 jmp main


 org 0bh  ;timer0的中断入口
 jmp timerint


 org 0023H  ;串口中断的入口
 jmp uartINT


 org 002BH  ;timer2的中断入口
 jmp timer2INT



 org 40h  ;主程序开始地址
;==========================主程序开始于此===================
main:



;此下为测试代码
;test display
; mov r1,#0
;temp1: mov key1,r1
; mov key2,key1
; mov key3,key2
; mov key4,key3
; lcall display
;
; inc r1
; cjne r1,#10,temp
; mov r1,#0
;temp:
; jmp temp1


;~~~~~~~~~~~测试EEPROM
;mov r4,#0


;testread:
;call eepr
;inc r4
;cjne r4,#5,testread
;mov r4,#0
;mov r5,#0
;testeep:
;mov a,r4
;mov r5,a
;call eepw;


;inc r4
;cjne r4,#05h,testeep


;jmp main
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~测试写入eprom


;temp: mov keyposi,#3
; mov addr,#255
; call openon


; mov keyposi,#3
; mov addr,#255
; call shutdown
; jmp temp
;此上为测试代码


 ;=========================================
 mov sp,#66h    ;=
 mov memposi,#00h   ;=
 mov dispposi,#0   ;=
 mov IE,#10110010b   ;=
 setb PT0    ;=
 ;=========================================
 clr et1
 orl PCON,#00000000B
 mov tmod,#021h
 mov TH1,#0E6h
 mov TL1,#0E6h
 setb TR1
 ;timer2初始化
 mov t2con,#00000000h
 mov th2,#0ECH
 mov tl2,#078H
 mov rcap2h,#0ECH
 mov rCAP2L,#078H
 setb tr2
 ;串口设置
 mov SCON,#01010000b
 mov uartposi,#0


 mov     cbit,#6                        ;发送次数基数
        mov     EXMT,#0                        ;按键功能寄存器清0。
 clr dataout
 call clrdisp    ;清除显示
 clr ampout


;=================================================================
;debug:
;  call delay1500ms
;  jmp debug
;=================================================================
waitkey:     ;等待按键与处理按键
 lcall keyscan    ;调用按键处理子程序
 cjne a,#80h,tokeyloop  ;返回编码为80H,则为无按键输入
 mov a,uartflag
 cjne a,#0fh,waitkey  ;串口标志为0fh,说明同步码与地址、命令接收正确,可以进行相应动作,否则继续扫描键盘
 jmp uartok


tokeyloop:
 jmp keyloop    ;有按键按下,转到keyloop进行键盘编码处理


uartINT:   ;===============串口中断程序=============================
 clr EA
 clr RI
 clr TI
 push acc
 push psw
 mov a,SBUF
 mov uartbuf3,a
 mov a,uartposi   ;判断现在接收的是计算机发送的第几位字节
  cjne a,#0,uart1  ;若为0,则接收到的第一个字节若为f5h则位置计数加一
  mov a,uartbuf3
  cjne a,#0F5h,retuart1
  mov uartposi,#1
  jmp retuart
 uart1:
  cjne a,#1,uart2
  mov a,uartbuf3  ;若为1,则接收到的第二个字节是00F,01F,02F时则存于uartbuf1
  cjne a,#00h,uart11
  jmp uart1ok
 uart11: cjne a,#01h,uart12
  jmp uart1ok
 uart12: cjne a,#02h,retuart1
 uart1ok:
  mov uartBUF1,a
  mov uartposi,#2
  jmp retuart


 uart2: cjne a,#2,uart3  ;若为2,则接收到的第三个字节存于uartbuf2
  mov a,uartbuf3
  mov uartBUF2,a
  mov uartposi,#3
  jmp retuart
 uart3: cjne a,#3,retuart1
  mov a,uartbuf3  ;若为3,则接收到的第三个字节若为f5h则转去处理串口接收的数据
  cjne a,#0F5h,retuart1
  mov uartflag,#0fh  ;设置串口接收成功的标志位


retuart1: mov uartposi,#0
retuart:
 pop psw
 pop acc
 setb EA
 reti   ;===============退出串口中断程序=========================


 


uartok:    ;串口接收数据正确,进行相应的操作


  mov uartflag,#00h  ;清除标志位
  mov a,uartbuf1
  cjne a,#0,uartok1  ;开启特定的电动机
;PC发送开启命令,单片机进行相应动作,通过子程序发送编码信号
   mov keyposi,#3
   setb ampout
   call delay1500ms
   mov     cbit,#12         ;发送基数赋值


          call shutrecent ;关闭最近开启的机器
   mov addr,uartbuf2


   call uart2key ;调用子程序将串口数据转为显示代码
                        mov     cbit,#6         ;发送基数赋值
          jmp uartin  ;进入开启机器的程序


 uartok1:
         cjne a,#1,uartok2  ;PC关断相应的机器
   mov keyposi,#2
   mov addr,uartbuf2
   call uart2key
   setb ampout
   call delay1500ms
   mov     cbit,#12
   call shutdown
   jb tr0,$
   call delay500ms
   clr ampout
   jmp retuartok


 uartok2:
  cjne a,#2,retuartok  ;PC控制全部关断电动机
   jmp uartin2  ;进入关断的程序
retuartok:
 jmp waitkey


keyloop:  ;=============按键处理程序============


;===========================按下关断键,关断特定的机器
;shut down key pushed,shut down a sub-device


 cjne a,#0bh,shutall
 ;if wrong ,can not send data
 mov a,key4
 cjne a,#0ffh,shut1   ;无地址输入,退出
 jmp retkeyloop
shut1:


 call key2add    ;将按键输入转化为地址代码
 mov a,keyposi
 cjne a,#0,inputwrong1
 jmp retkeyloop
inputwrong1:
 setb ampout
 call delay1500ms
 mov     cbit,#12
 call shutdown   ;关断指定的机器
 jb tr0,$
 call delay500ms
 clr ampout
 jmp retkeyloop
;===========================复位键按下,关断全部机器
;reset key pushed ,shut down all sub-device
shutall:cjne a,#0Eh,open
 ;r4 is address ,r5 is data ,eepw and eepr is the subprogramm
uartin2:
 mov keyposi,#2
 mov key1,#0ah
 mov key2,#0ah
 mov key3,#0ah
 mov key4,#0ah
 setb ampout
 call delay1500ms
 mov     cbit,#12
 call shutrecent   ;先关断最近开启的机器
 mov     cbit,#6
 call shutdownall   ;关断全部的机器
 mov key1,#0eh
 mov key2,#0eh
 mov key3,#0eh
 mov key4,#0eh
 jb tr0,$
 call delay500ms
 clr ampout
 jmp retkeyloop
;===========================开启特定的机器
;open on a sub-device
open:
 cjne a,#0Fh,clearkey
;open key pushed ,convert the key data to ADD data and send PWM by subPRO
 mov a,key4
 cjne a,#0ffh,open2
 jmp retkeyloop   ;无地址输入,退出
open2:
 call key2add    ;将按键码转换为地址
 mov a,keyposi
 cjne a,#0,inputwrong2
 jmp retkeyloop
inputwrong2:
 setb ampout
 call delay1500ms
 mov     cbit,#12
 call shutrecent   ;关断最近开启的机器
        mov     cbit,#6
 call key2add    ;将按键码转换为地址


uartin: mov a,memposi   ;根据eeprom的存贮位置将地址码存入,保证存贮信息为最后5次开启机器编号
 cjne a,#5,notovermem
 mov memposi,#0
notovermem:
 inc memposi
 mov r4,memposi
 mov r5,addr
 mov addrbuf,r5


 call eepw
 call openon    ;开启机器
 ;call shutother   ;关闭其他机器
;r4 is address ,r5 is data ,eepw and eepr is the subprogramm
 jb tr0,$
 call delay500ms
 clr ampout
 jmp retkeyloop


;清除键按下,清除显示
;clear key pushed, clear the display
clearkey:
 cjne a,#0ch,keyloop1
 call clrdisp
 jmp retkeyloop
;==========================以下为按键位置判断,以在LED上正常显示
keyloop1:
 cjne a,#0ah,filter1
 jmp retkeyloop
filter1:
 cjne a,#0dh,filter2
 jmp retkeyloop
filter2:
 mov r7,keyposi
 cjne r7,#0,keyloop2
 mov key4,a
 mov keyposi,#1
 jmp retkeyloop
 keyloop2:
 cjne r7,#1,keyloop3
 mov key3,key4
 mov key4,a
 mov keyposi,#2
 jmp retkeyloop
 keyloop3:
 cjne r7,#2,keyloop4
 mov key2,key3
 mov key3,key4
 mov key4,a
 mov keyposi,#3
 jmp retkeyloop
 keyloop4:
 cjne r7,#3,retkeyloop
retkeyloop:
        mov     cbit,#6
 jmp waitkey
;=========================子程序部分
;sub programme
;===============看门狗程序
timer2INT:
 push acc
 push psw
 clr TF2
 mov 0A6H,#01EH
 mov 0A6H,#0E1H
 call display
 pop psw
 pop acc
 reti


;===============将计算机传来的地址码转换为键盘码,用于显示
uart2key:


 mov a,addr
 cjne a,#255,uart2key1
 mov key2,#2
 mov key3,#5
 mov key4,#6
 jmp retuart2key
 uart2key1:
 inc a
 mov b,#100
 div ab
 mov key2,a
 mov a,b
 mov b,#10
 div ab
 mov key3,a
 mov key4,b
retuart2key:
 ret
;===============开启特定机器的子程序
openon:
 jb tr0,openon
 mov a,keyposi
 cjne a,#0,notretopenon
 jmp retopenon
 notretopenon:
 mov data4,#on
 call senddata
 retopenon:
 mov key1,#0Eh
 ret
;===============关闭特定机器的子程序
shutdown:
 jb tr0,$
 mov a,keyposi
 cjne a,#0,notretshut
 jmp retshutdown
 notretshut:
 mov data4,#off
 call senddata
 retshutdown:
 mov key1,#4ah
 ret
;===============关闭最近开启机器的子程序
shutrecent:
 mov r4,#1
shutrecent2:
 call eepr
 mov addr,r5
 call shutdown
 inc r4
 cjne r4,#6,shutrecent2
 ret
;===============关闭所有机器的子程序
shutdownall:
 mov r7,#255
shutdownall3:
 mov addr,r7
 call shutdown
 djnz r7,shutdownall3
 mov addr,#0
 call shutdown
 mov r7,#255
shutdownall4:
 mov addr,r7
 call shutdown
 djnz r7,shutdownall4
 mov addr,#0
 call shutdown
 ret


;===============关闭除当前刚开启机器以外机器的子程序
Shutother:
 mov r7,#255
shutother1:
 mov addr,r7
 mov a,addrbuf
 cjne a,addr,shutother2
 call shutdown
shutother2:
 djnz r7,shutother1
 mov addr,#0
 call shutdown
 mov key1,#0EH
 ret


;===============将显示清空的子程序
clrdisp:
 mov keyposi,#0
 mov key1,#0FFh
 mov key2,#0FFh
 mov key3,#0FFh
 mov key4,#0FFh
        ret


clrdis: jnb  EXMP,retdis
 mov keyposi,#0
 mov key1,#0FFh
 mov key2,#0FFh
 mov key3,#0FFh
 mov key4,#0FFh
        clr     exmp
retdis: ret
;===============将键盘输入转换为8位的地址码
key2add:
 mov b,#10
 mov a,key3
 cjne a,#0ffh,shiwei
 mov r4,#0
 mov r5,#0
 jmp gewei
shiwei: mul ab
 mov r4,b
 mov r5,a
 clr c
 mov b,#100
 mov a,key2
 cjne a,#0ffh,baiwei
 jmp gewei
baiwei: mul ab
 clr c
 add a,r5
 mov r5,a
 mov a,b
 addc a,r4
 mov r4,a
;first two byte
gewei: mov a,key4
 cjne a,#0ffh,gewei2
 jmp overflow
gewei2: clr c
 add a,r5
 mov r5,a
 mov a,r4
 addc a,#0
 mov r4,a


;--------------------added


 clr c
 dec r5
 cjne r5,#0ffh,gewei3
 dec r4
;--------------------added


 



gewei3: cjne r4,#0,overflow
 mov addr,r5
 jmp retkey2add
 overflow:
 call clrdisp
 retkey2add:
 ret



;===============LED的显示子程序
;display subprogramme for LED
display:
 mov a,dispposi
 cjne a,#0,disp1
 mov dispposi,#1
 mov a,key1
 call codeconvert
 setb P1.1
 setb P1.2
 setb P1.3
 mov P0,a
 clr P1.0
 jmp retdisp


disp1:
 cjne a,#1,disp2
 mov dispposi,#2
 mov a,key2
 call codeconvert
 setb p1.0
 setb P1.2
 setb P1.3
 mov P0,a
 clr P1.1
 jmp retdisp


disp2:
    cjne a,#2,disp3
 mov dispposi,#3
 mov a,key3
 call codeconvert
 setb P1.0
 setb P1.1
 setb P1.3
 mov P0,a
 clr P1.2
 jmp  retdisp


disp3:
 cjne a,#3,retdisp1


 mov a,key4
 call codeconvert
 setb P1.1
 setb P1.2
 setb P1.0
 mov P0,a
 clr P1.3
retdisp1:
 mov dispposi,#0
retdisp:
 ret


;===============将按键码转换为LED对应的引脚电平状态
codeconvert:
 cjne a,#1,code2
 mov a,#0f9h
 jmp retconvert
 code2:
 cjne a,#2,code3
 mov a,#0a4h
 jmp retconvert
 code3:
 cjne a,#3,code4
 mov a,#0b0h
 jmp retconvert
 code4:
 cjne a,#4,code5
 mov a,#99h
 jmp retconvert
  code5:
 cjne a,#5,code6
 mov a,#92h
 jmp retconvert
  code6:
 cjne a,#6,code7
 mov a,#82h
 jmp retconvert
  code7:
 cjne a,#7,code8
 mov a,#0f8h
 jmp retconvert
  code8:
 cjne a,#8,code9
 mov a,#80h
 jmp retconvert
  code9:
 cjne a,#9,codezero
 mov a,#90h
 jmp retconvert
  codezero:
 cjne a,#00h,codea
 mov a,#0c0h
 jmp retconvert
  codea:
       cjne a,#0ah,codeb
 mov a,#88h
 jmp retconvert
  codeb:
       cjne a,#0bh,codec
 mov a,#83h
 jmp retconvert
  codec:
       cjne a,#0ch,coded
 mov a,#0c6h
 jmp retconvert
  coded:
       cjne a,#0dh,codee
 mov a,#0a1h
 jmp retconvert


  codee:
       cjne a,#0eh,codef
 mov a,#86h
 jmp retconvert
  codef:
       cjne a,#0fh,codep
 mov a,#8eh
 jmp retconvert
   codep:
       cjne a,#01ah,codeu
 mov a,#8ch
 jmp retconvert
   codeu:
       cjne a,#2ah,codey
 mov a,#0c1h
 jmp retconvert
   codey:
       cjne a,#3ah,codeh
 mov a,#91h
 jmp retconvert
   codeh:
       cjne a,#4ah,codel
 mov a,#89h
 jmp retconvert
   codel:
       cjne a,#5ah,retconvert
 mov a,#0c7h
 jmp retconvert
retconvert:
 ret
;===============键盘扫描程序
;keyboard input, output the key
keyscan:
 mov p2,#0fh
 mov a,p2
 orl a,#0f0h
 cpl a
 jz nokey
 lcall delay30ms  ;延时30ms
 lcall scan   ;扫描按键输入
 mov b,a   ;暂时保存键盘输入


 keep:    ;如果一直按键,程序将一直停在此处
     ;此部分保证一次取一个按键码
  mov p2,#0fh
  mov a,p2
  orl a,#0f0h
  cpl a
  jz retkeyscan
 jmp keep


 retkeyscan:


  mov a,b
  mov p2,#0fh
  ret
 nokey:
  mov a,#80h  ;没有按键输入,输入80h 作为标志
 ret
;===============扫描按键输入
 scan:
  mov p2,#7fh  ;first line
 L11: jb p2.0,L12
         call   clrdis          ;条件清空显示
  mov a,#0Eh  ;reset key
  JMP RETKEY
 L12: JB P2.1,L13
         call   clrdis          ;条件清空显示
  mov a,#0Ch  ;clear key
  jmp retkey
 L13: JB P2.2,L14
         call   clrdis          ;条件清空显示
  mov a,#0Ah  ;N/A
  jmp retkey
 L14: JB P2.3,L21
         call   clrdis          ;条件清空显示
  mov a,#0Bh  ;N/A
  jmp retkey



 L21: mov p2,#0BFh  ;SECOND line
  jb p2.0,L22
  call   clrdis          ;条件清空显示
  mov a,#08h  ;8key
  JMP RETKEY


 L22: JB P2.1,L23
         call   clrdis          ;条件清空显示
  mov a,#09h
  jmp retkey
 L23: JB P2.2,L24
         setb    EXMP            ;发送标志置位
  mov a,#0Fh  ;on key
                jmp retkey
 L24: JB P2.3,L31
         setb    EXMP            ;发送标志置位
  mov a,#0Bh  ;off key
  jmp retkey


 L31: mov p2,#0DFh  ;THIRD line
  jb p2.0,L32
  call   clrdis          ;条件清空显示
  mov a,#04h  ;4 key
  JMP RETKEY


 L32: JB P2.1,L33
         call   clrdis          ;条件清空显示
  mov a,#05h  ;5 key
  jmp retkey
 L33: JB P2.2,L34
         call   clrdis          ;条件清空显示
  mov a,#06h  ;6 key
  jmp retkey
 L34: JB P2.3,L41
         call   clrdis          ;条件清空显示
  mov a,#07h  ;7 key
  jmp retkey


 L41: mov p2,#0efh  ;FORTH line
  jb p2.0,L42
  call   clrdis          ;条件清空显示
  mov a,#00h
  JMP RETKEY


 L42: JB P2.1,L43
         call   clrdis          ;条件清空显示
  mov a,#01h  ;1 key
  jmp retkey
 L43: JB P2.2,L44
         call   clrdis          ;条件清空显示
  mov a,#02h  ;2 key
  jmp retkey
 L44: JB P2.3,L21
         call   clrdis          ;条件清空显示
  mov a,#03h  ;3 key
  jmp retkey
retkey:  ret


;===============延时子程序
;delay subprogramms below
delay1500ms:
 mov r7,#14
 dy000:
 mov r6,#100
 dy111:
 mov r2,#200
 djnz r2,$
 djnz r6,dy111
 djnz r7,dy000
 ret


delay500ms:
 mov r7,#50
 dy500:
 mov r6,#200
 djnz r6,$
 djnz r7,dy500
 ret
delay30ms:
 mov r7,#150
 dy0:
 mov r6,#100
 djnz r6,$
 djnz r7,dy0
 ret
delay5ms:
 mov r7,#25
 dy02:
 mov r6,#100
 djnz r6,$
 djnz r7,dy02
 ret
;=============================
;=============================
;=============================
;=============================
;以下的子程序是最重要的子程序之一,功能为将存储在Addr中的8bit地址数据和存储在
;data4中的4bit芯片PT2272数据输出引脚状态数据转化为codedata开始的缓冲区数据
;timer0中断程序根据这些数据输出宽或者窄脉冲进行控制
;=============================
;=============================
;=============================
;=============================


senddata:


 jb tr0,$
 mov r0,#codedata
 mov @r0,#10000000b  ;timer0根据缓冲区的bit位决定此周期是低电平还是高电平,此语句#10000000b是同步码
 inc r0   ;此下的程序根据地址码的0或1写入缓冲区“0”的编码“88h”或“1”的编码“eeh”
 mov @r0,#0
 inc r0
 mov @r0,#0
 inc r0
 mov @r0,#0
 inc r0
 mov counterconvert,#0


 clr c
 convertADD:
  mov a,ADDR
  clr c
  rlc a
  mov ADDR,a
  jc code1


  mov @r0,#088h
  jmp code0


 code1: mov @r0,#0eeh
 code0: inc r0
  inc counterconvert
  mov a,counterconvert
  cjne a,#8,convertADD


  mov counterconvert,#0


 convertDATA:
  mov a,data4
  clr c
  rlc a
  mov data4,a
  jc code11
  mov @r0,#088h
  jmp code00


 code11: mov @r0,#0eeh
 code00: inc r0
  inc counterconvert
  mov a,counterconvert
  cjne a,#4,convertDATA
;====================以上是地址和数据向串行数据格式的转换,timer0中断发送此串行数据
;convert the ADD and DATA to serial data format


 mov r0,#codedata
 mov buffer,@r0


 clr dataout
 mov TH0,#timerH
 mov TL0,#timerL
 mov counterbit,#0
 mov counterT,#0
 mov Tcounter,#0
 setb TR0  ;启动timer0
 ret
;=======================timer0的中断程序
timerint:


 push acc
 push psw
 mov th0,#timerH
 mov tl0,#timerL  ;保护现场


 mov a,buffer
 clr c
 RLC a
 jc setout1
 clr dataout
 jmp setout0
setout1:setb dataout
setout0:mov buffer,a
 inc counterBIT
 mov a,counterBIT
 cjne a,#8,nextBIT  ;判断一个字节是否结束
 inc counterT
 mov counterBIT,#0
 inc R0
 mov a,@R0
 mov buffer,a
nextBIT:    ;一个字节未结束,判断81bit是否结束(一个完整的PT2262的编码转换成此串行数据的长度)


 mov a,counterT
 cjne a,#16,quitINT
 mov counterBIT,#0
 mov counterT,#0
 inc Tcounter
 mov a,Tcounter
 cjne a,cbit,sendagain  ;是否发送8次?
 mov counterBIT,#0
 mov counterT,#0
 mov Tcounter,#0
 clr TR0   ;停止timer0
 ;mov delayflag,#0fh  ;set delay flag
 jmp quitint


sendagain:
 mov r0,#codedata
 mov buffer,@r0
quitINT:
 pop psw
 pop acc
 reti


;=======================timer0中断退出


 


;24C02中带有片内地址寄存器。每写入或读出一个数据字节后,该地址寄存器自动加1,以实现对下一个存储单元的读写。所有字节均以单一操作方式读取。为降低总的写入时间,一次操作可写入多达8个字节的数据。


SCL BIT P3.7  ;定义24C02的串行时钟线
SDA BIT P3.6  ;定义24C02的串行数据线


;读写子程序如下:


;写串行E2PROM子程序EEPW
;R3=10100000(命令1010+器件3位地址+读/写。 器件地址一个芯片,是000)
;(R4)=片内字节地址
;r5内存储要发送的数据
EEPW:


 orl p3,#11000000b
 clr SDA
 mov a,#write ;送器件地址,固定为#write
 acall subs
 mov  a,r4  ;送片内字节地址
 acall subs
  MOV  A,r5
 acall subs
  CLR    SDA  ;SDA置0, 准备送停止信号
  ACALL  DELAY  ;延时以满足传输速率要求
  SETB    SCL  ;发停止信号
  ACALL  DELAY
  SETB    SDA
 CAll delay
  RET


SUBS: MOV R1,#08H  ;发送单字节子程序
subsLOOP:
 CLR SCL
  RLC A
 MOV SDA,C
  NOP
 nop
  SETB SCL
  ACALL  DELAY
  DJNZ R1,subsLOOP ;循环8次送8个bit
  CLR SCL
  ACALL DELAY
  SETB SCL


 mov r7,#25


 eepwdelay:
 mov r6,#100
REP:  MOV C,SDA
       dec r6
 JNC  RETEEPW  ;判应答到否,未到则等待


  cjne r6,#0,rep
 djnz r7,eepwdelay
 ;mov key1,#0fH
 ;mov key2,#0fH
 ;mov key3,#0fH
 ;mov key4,#0fH
RETEEPW:
 CLR SCL
  RET


;DELAY:    ;延时子程序,占用寄存器R7,R6


DELAY:    ;延时子程序,占用寄存器R7,R6
 nop
 nop
 nop
 nop
  RET
;读串行E2PROM子程序EEPR
;R3=10100001(命令1010+器件3位地址+读/写。 器件地址一个芯片,是000)
;(R4)=片内字节地址
;r5 is the data to read


EEPR:  orl p3,#11000000b
 CLR  SDA   ;发开始信号
  MOV  A,#write
 ACALL  SUBS    ;调发送单字节子程序
  MOV  A,R4    ;送片内字节地址
  ACALL  SUBS
 orl p3,#11000000b
 CLR  SDA   ;发开始信号
  MOV  A,#read  ;发送读命令
  ACALL  SUBS
  ACALL  SUBR  ;read data from 24C01
  mov r5,a
 CLR  SDA
  ACALL  DELAY
  SETB  SCL
  ACALL  DELAY
 SETB  SDA   ;送停止信号
 call delay
 RET


SUBR:  MOV   R1,#08H   ;接受单字节子程序
LOOP2:  SETB   SCL
  ACALL  DELAY
  MOV  C,SDA
  RLC  A
  CLR  SCL
  ACALL  DELAY
  DJNZ  R1,LOOP2
  SETB  SDA   ;若是最后一个字节置A=1
   ACALL DELAY
  SETB   SCL
 ACALL  DELAY
  CLR  SCL
  ACALL DELAY
 SETB  SDA    ;应答毕,SDA置1
RET


;程序中多处调用了DELAY子程序(仅两条NOP指令),这是为了满足I2C总线上数据传送速
;率的要求,只有当SDA数据线上的数据稳定下来之后才能进行读写(即SCL线发出正脉冲)。
;另外,在读最后一数据字节时,置应答信号为“1”,表示读操作即将完成。
end


https://static.assets-stash.eet-china.com/album/old-resources/2008/12/8/19d7fd26-7667-4281-9afb-752aab48938f.rar

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
6
关闭 站长推荐上一条 /3 下一条