搜索
bottom↓
回复: 27

回报阿莫:带任务调度的2051+18B20+HT1380+LS247电子钟

[复制链接]

出0入0汤圆

发表于 2010-4-1 10:35:05 | 显示全部楼层 |阅读模式
从阿莫的网站上下载了很多好资料,学到了很多东西.可是本人一直充当着超级潜水员的角色,嘿嘿,很是过意不去.今天把本人的小制作发上来,为论坛尽一点绵力..做的不好,还望大家包涵.多多指正..

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2010-4-1 10:39:50 | 显示全部楼层

(原文件名:照片-0005.jpg)


(原文件名:照片-0006.jpg)


(原文件名:照片-0007.jpg)


(原文件名:照片-0008.jpg)

点击此处下载 ourdev_542757.rar(文件大小:36K) (原文件名:电子钟百分之98成功备份.rar)

出0入0汤圆

 楼主| 发表于 2010-4-1 10:46:25 | 显示全部楼层
图中的旧电脑是学习并口编程用的.呵呵,不是我的主力电脑.代码压缩包里有整个工程.这里的是方便大家看的
;修改2010年3月2日13时6分58秒
;2: 增加实时时钟HT1380
;3: 删除掉电检测,删除闹钟,删除2051时钟,
;4: 画的PCB和原来的程序定义不一致,.晕.重新定义
;2051+74ls247电子钟         带电池和省电模式进行比较精确的时间显示   
;
        ; ledbit   bit 02h     ;LED灯闪还是不闪        ,为0就闪,为1任何情况下都不闪
                
                 ;45h          31h                                36
                 ;44h          30h                                35
                 ;43h                    2fh                                34
                 ;42h                   2eh                                33
             ;41h          2dh
                 ;40h                   2ch                       
        ;MOV 40H,#08 ;个位寄存器初值
        ;MOV 41H,#00 ;十位寄存器初值
        ;MOV 42H,#00 ;百位寄存器初值
        ;MOV 43H,#00 ;千位寄存器初值
        ;MOV 44H,#00 ;万位寄存器初值
        ;MOV 45H,#00 ;十万位寄存器初值
;系统用内存定义
arlmH        equ  39h
taskidbit  equ  36h   ;任务ID标志位
daydata    equ    35h    ;天数
tempLOK   equ   34h          ;转换好的温度BCD数据
tempHOK   equ   33h
saveinit   equ  32h        ;临时变量,用的是动态变量区
savewait   equ  31h
savesp     equ  30h    ;临时变量保护
oswaitflag  bit  2fh.0   ;进入OSWAIT子程序保护区标志
ostaskswflag bit  2fh.1          ;进入任务切换区标志
osidltask    bit  2fh.2                 ;进入最低优先级任务标志
osinittaskflag bit  2fh.3        ; osswflag.7 ; 中断任务保护区
htreadbit        bit  2fh.4           ;读HT1380标志,一秒一读,1为读
;setarlm                bit  2fh.5         ;进入闹钟设置时的标志,1为进入了
drive           bit  2fh.6;18B20存在标志
t2t        bit  2fh.7;是时间模式下还是温度模式下,为1是温度模式只下边的LED亮并且不闪,为0是时间模式2个LED一起闪
ms1to41           bit  2eh.0
ms1to42           bit  2eh.1

taskidnum  equ  2dh   ;任务ID数
osreadybit  equ 2ch   ;任务准备好标志,准备好为1,
osinitbit  equ  2bh   ;任务被中断位表,被中断了为1
oswaitbit  equ  2ah   ;任务被挂起位表,被挂起了为1
s5                equ  29h                ;5秒定时
displaydataH equ  28h         ;数据管显示数据的高位,BCD压缩码
displaydataL equ  27h    ;数据管显示数据的低位,BCD压缩码
timeH       equ  26h     ;时间RAM
timeL       equ  25h     ;时间RAM
timeS       equ  24h            ;秒单元
TEMPER_L    equ  23h     ;温度
TEMPER_H    equ  22h                                                                                                     ;R6温度时间显示计数        ,4秒一换
oswaitram  equ  09h   ;挂起任务的结构首址,8*3=24,09H到21H
                                                                                                                                                    
maxtask    DATA    2             ;最大任务ID,0也是一个任务
H5MS       DATA    0B2H
L5MS       DATA     05h
sdata      bit p1.3 ;HT时序IO
srst     bit p3.5 ;HT数据IO                         ;
sclk     bit p1.2 ;HT1380复位IO
DQ            bit p3.4 ;18B20
leddianh  bit p1.0  ;LED上秒点,高电平点亮
leddianL  bit p1.1  ;LED下秒点  高电平点亮

key       bit p3.7  ;KEY

;********主程序都从OOH开始

ORG 00H
JMP Main       ;引导程序从Main开始执行
org 0bh
ljmp osinitpro
;******下面是主程序执行体
ORG 030H
Main:  MOV SP,#3aH    ;初始化堆栈,系统欠底
       acall initial
          
                 mov taskidnum,#0       ;任务指针指向第0个任务       
                 mov taskidbit,#1               
                 mov osreadybit,#255
                 setb ea
                 setb et0                ;T0中断充许
             setb tr0                        ;T0定时器开始运行
                  
;用户代码写在这里
;//*****************************************//
keyscan:        setb key
                jb key,ht1380
                mov r3,#10        ;等待50MS
                acall oswait
                setb key
                jb key,ht1380
               
      mov r0,#timeS ;写入的小时和分数据首址     写入时,分,秒数据
      mov @r0,#58h         ;58秒
      inc r0
      mov @r0,#59h         ;59分
      inc r0
      mov @r0,#6h          ;6点
      acall writehms
              mov r3,#63
                acall oswait
                        mov r3,#63        ;等待700MS,防止键又被觛发
                acall oswait

                        mov r3,#63        ;等待700MS,防止键又被觛发
                acall oswait

ht1380:                jbc htreadbit,readtime
                ljmp tasksw
readtime:        acall readhms
                ljmp tasksw

                  ;千位显示
display:          clr p1.7 ;关闭个位,p3.3
                        mov a,displaydataH
                  anl a,#240        ;BCD压缩码的低四位清零
                  jz dis01                         ;千位为零不显示
                 ; anl 90h,#15           ;把P1端口的高4位清零了,低4不变
                swap a
                  anl 0b0h,#240                 ;p3口低4清0,高4不影响
                 orl 0b0h,a        ;BCD码的高4位是千位
                  
                  setb p1.4 ;打开千位 P3.0
dis01:           mov r3,#1       
          acall oswait  
                    ;百位显示
                  clr p1.4 ;p3.0
                  mov a,displaydataH
               
                  anl a,#15        ;BCD压缩码的低四位清零
                  anl 0b0h,#240           ;把P1端口的高4位清零了,低4不变
                  orl 0b0h,a        ;合成
                  setb p1.5   ;P3.1
                  mov r3,#1       
                  acall oswait
                  
                  ;十位显示
                  clr  p1.5 ;p3.1       
                  mov a,displaydataL
                  anl a,#240        ;BCD压缩码的低四位清零
                  swap a
                  anl 0b0h,#240           ;把P1端口的高4位清零了,低4不变
                  orl 0b0h,a        ;合成
                  setb p1.6  ;P3.2
                  mov r3,#1       
                  acall oswait
                  
                  ;个位显示
                  clr p1.6  ; p3.2
                  mov a,displaydataL
       
                  anl a,#15        ;BCD压缩码的低四位清零
                  anl 0b0h,#240           ;把P1端口的高4位清零了,低4不变
                  orl 0b0h,a        ;合成
                  setb p1.7  ;P3.3
                  mov r3,#1       
                  acall oswait
                  ajmp display
                  

; 读出转换后的温度值
;//*****************************************//
;  //       mov r3,#64          ;64光事件模式
;   //      acall oswait
GET_TEMPER:
        jnb t2t, GET_TEMPER_0
            CLR drive
        SETB    DQ            ;释放总线
        ACALL    INIT_1820    ; DS18B20初始化
        JNB    drive,GET_TEMPER_0        ; 若DS18B20不存在则返回
        MOV    A,#0CCH        ; 跳过ROM匹配
        ACALL    WRITE_1820
        MOV    A,#44H        ; 发出温度转换命令
        ACALL    WRITE_1820
      
            mov r3,#63                                ;延时63*5MS=315MS
        acall oswait
        mov r3,#63                                ;延时63*5MS=315MS*2=630ms
        acall oswait
                mov r3,#20                        ;延时24*5MS=120MS  +630ms=750ms, 12位精度时要求的转换时间750MS
        acall oswait
                CLR drive
        SETB    DQ            ;释放总线
        ACALL    INIT_1820    ; DS18B20初始化
        JNB    drive,GET_TEMPER_0        ; 若DS18B20不存在则返回
               
        ACALL    INIT_1820
        MOV    A,#0CCH        ; 跳过ROM匹配
        ACALL    WRITE_1820
        MOV    A,#0BEH        ; 发出读温度命令
        ACALL    WRITE_1820
        ACALL READ_TEMP        ; 将读出的温度数据保存到35H/36H
        acall TEMPER_COV
GET_TEMPER_0: ljmp tasksw                ;



oswait:   ;系统等待信号,延时子程序,               
                  setb oswaitflag                  ;设立进入OSWAIT子程序保护区标志       
          mov  b,#3                          ;计算OSWAITRAM数据地址换算
                  mov  a,taskidnum       
                  mul  ab
                  add   a,#oswaitram                  ;首址
                                          ;取得本任务OSWAITRAM数据结构地址
                  mov r0,a
          mov a,r3
                  mov @r0,a                                                ;从R3处取得第一字节数据
                  inc r0
                  pop   ACC                                           ;取得本任务断点PC指针,
                  mov   @r0,a
                  inc   r0
                  pop   ACC
                  mov   @r0,a
                  mov   a,taskidbit
                  orl        oswaitbit,a                                        ;设立本任务挂起标志
                  cpl a
                  anl   osreadybit,a                                ;设立本任务不能运行标志位置0
                  jb        oswaitflag,oswaitend        ;自认为是精妙之处,oswaitflag为1说明没有被系统中断,可以检测本任务后的一个任务
                        ;oswaitflag为0说明被系统中断过了。根据占先式OS的要求,就会重新从优先级为0的任务开始检测;
         ajmp  taskjc                  ;
oswaitend:clr   oswaitflag                                 ;清除本保护区标志,
                  
tasksw:   ;用户调用的任务切换程序,特点:接着上一个任务,处理下一个任务
                 setb  ostaskswflag                ;任务切换保护区标志的意义,正在切换任务时,来了中断时间,事件标志,都会更新,在这更新前切换任务是不合适的,
                                                                 ;所以,系统检测如果中断了TASKSW后,就会把SP,oswaitbit,osinitbit都恢复到处理之前的状态,
                ;任务切换程序中检测所有可以运行任务,可以运行的原因
                  ;这是任务切换程序的准备工作
                        clr ea
                        mov savesp,sp                                        ;备份SP,挂起标志,中断标志
                        mov savewait,oswaitbit
                        mov saveinit,osinitbit
                        setb ea
                       
                       
                ;任务切换程序
nexttask:   mov a,taskidbit
                        rl  a
                        mov taskidbit,a
                        inc taskidnum
                        mov a,taskidnum
                        cjne a,#maxtask+1,ossw1
                        clr ostaskswflag
                        setb osidltask
                        mov psw,#0
osidl:      orl pcon,#1
                        jmp osidl
ossw1:            mov a,taskidbit
                        anl a,osreadybit                       ;本任务可以运行吗
                        jz nexttask                                    ;不能运行转到下一个,
                        anl a,oswaitbit                                ;可以运行,是否被挂起的,
                        jz  ossw2                                     ;没被挂起就跳到下面的检测
                        ;挂起任务的处理
                    cpl a
                    anl oswaitbit,a                            ;挂起的任务可以运行了,清除其挂起标志,
                  mov  b,#3                          ;计算OSWAITRAM数据地址换算
                  mov  a,taskidnum       
                  mul  ab
                  mov  r0,#oswaitram                  ;首址
                  add   a, r0                         ;取得本任务OSWAITRAM数据结构地址
                  add  a,#2                                                ;不处理第一字节数据,跳过第二字节为了配合欠跳转,
             mov r0,a
                  mov   a,@r0
                  push   ACC                                           ;恢复本任务断点PC指针,
                  dec   r0
                  mov   a,@r0
                  push   ACC
                  jmp   osswend                                        ;跳到断点处
ossw2:   ;中断任务的处理
                  mov a,taskidbit               
                  anl a,osinitbit       
                  jz   ossw3                                     ;也没有中断就跳到OSSW3
                  cpl a
                  anl osinitbit,a                            ;中断的任务可以运行了,清除其中断标志,
                  POP        03h
                  POP        02h
                  POP        01h
                  POP        00h
                  POP        DPL
                  POP        DPH
                  POP        B
                  POP        PSW
                  POP        ACC       
                  jmp   osswend          
ossw3:   ;没有挂起,也没有中断的任务的处理
                 mov dptr,#taskpcmap                  ;各个任务的首PC地址
                 mov  a,taskidnum
                 rl a                                                         ;PC值是双字节,所以要*2
                 mov r3,a
                 movc a,@a+dptr
                 push ACC
                 mov a,r3
                 inc a
                 movc a,@a+dptr
                 push ACC
osswend: clr ostaskswflag                            ;切换结束,清除其开关
                 ret
                                                                         
osinitpro:; 系统中断处理程序 中断程序中检测所有没有准备好的任务,不能运行的原因
                        clr tr0
                        mov th0,#H5MS
                        mov tl0,#L5MS
                        setb tr0
                           
                        jb osidltask,taskjc                          ;这是最低优先级任务的标识
                        jb ostaskswflag,flag1            ;ostaskswflag是TASKSW数据保护区
                        jb oswaitflag,flag0                    ;oswaitflag是WAIT数据保护区需要保护处理就跳到FLAG0,并清零                  
                PUSH        ACC        ;受OS保护的寄存器就这些.
                PUSH        PSW
                PUSH        B
                PUSH        DPH
                PUSH        DPL
                PUSH        00h
                PUSH        01h
                PUSH        02h
                PUSH        03h
;任务被中断了,
                mov a,taskidbit
                orl osinitbit,a        ;把被中断任务的中断标志置1
                ;cpl a
                ;anl osreadybit,a      ;把被中断的任务的准备好标志置0,
                setb osinittaskflag                     ; 中断任务保护区
taskjc:            ;系统用的任务切换,特点:从0任务开始处理,只处理延时和事件的标志
                        mov  a,#1
                        mov taskidbit,a
                        mov r3,a
                        mov r2,#0        ;中断后总是初始化任务指针指向第0个任务
                        mov taskidnum,r2
nextjc:        cjne r2,#maxtask+1,jc2         ;最后一个任务检测完了就结束检测               
jcend:         jbc osinittaskflag,jcend2        ;中断了的任务,已经保存了他的SP等信息,直接到JCEND2,由任务切换程序按该任务的优先级来执行
                jbc osidltask,     jcend666                          ;这是最低优先级任务的标识
                jbc ostaskswflag,  jcend999                ;ostaskswflag是TASKSW数据保护区
                jbc oswaitflag,    jcend2                    ;oswaitflag是WAIT数据保护区需要保护处理就跳到FLAG0,并清零       
                         
jcend999:       
                         POP DPH
                  POP DPL
jcend666:;         // clr ostaskswflag
                         dec sp
                     dec sp
jcend2:                                  ;  出口为任务切换程序PC地址
;        //          anl 2fh,#192      ;2fH是位寻址各种标志寄存器,高2位被用户程序占用,不被清0,低6位被清0
                  acall timer                         ;时间,LED秒点,时间温度切换显示
                 mov a,#low ossw1                         ;这里要直接跳到ossw1,需要注意这里
                 push acc
                 mov a,#high ossw1
                 push acc
                 
                       
jcend333:         reti                                  

jc2:                anl        a,osreadybit                ;中断中就检测OSREADYBIT这个标志
                        jz  noready
jc1:     mov a,r3
         rl a
                        mov r3,a
                        inc r2
                        jmp nextjc
flag0:                ret                                  ;处理的办法,直接返回原数据保护区,不干涉,再由数据区跳到中断区退出
flag1:      mov sp,savesp                                ;恢复被TASKSW子程序更改的SP,挂起标志,中断标志后,重新进行切换
                        mov oswaitbit,savewait
                        mov osinitbit,saveinit
                        PUSH DPL
                    PUSH DPH
                        jmp taskjc
noready:     ;检测不能运行任务的原因
                        mov a,r3
                        anl a,oswaitbit              ;暂只有挂起检测
                        jz  jc1
taskgq:        ;挂起任务的检测工作
                  mov  b,#3                          ;计算OSWAITRAM数据地址换算
                  mov  a,r2       
                  mul  ab
                  mov  r0,#oswaitram                  ;首址
                  add   a, r0                         ;取得本任务OSWAITRAM数据结构地址
                  mov r0,a
                  mov a,@r0
                  ;
                  jb  acc.7,msstart                ;oswaitram.7是数据成以4的延时标志,能延时63*5*4=1260MS;如果这2个标志全没有就是普通延时
                  jb acc.6,jc807                        ;oswaitram.6是有事件标志                
                  jmp jc801                       
msstart:  cpl ms1to41
                  jnb ms1to41,ms14
                   jmp jc1
ms14:          cpl ms1to42
                  jnb ms1to42,jc1

jc801:          dec @r0         
                  mov a,#63                  ;屏B高2位
                  anl a,@r0
                  jnz jc1
jc888:                mov a,r3
                        orl osreadybit,a              ;任务延时时间到,置位可以运行的标志
                        jmp jc1
jc807: ;;1111111111111111111光事件
                  mov a,r2
                  rl a                   ;*2,用的是RL,/2用的是RR,  
                  mov dptr,#sjpc
                  jmp @a+dptr
sjpc:           ajmp task0           ;提供给各个任务的事件处理程序
;原本这里计划要处理事件包括,任务间的通信,一些特殊的任务等,很麻烦,结果一拖再拖后
;没有心情弄了.
                   ajmp task1
                   ajmp task2
                   ajmp task3
                   ajmp task4
                   ajmp task5
                   ajmp task6
                   ajmp task7

task0:

task1:    jb t2t,jc889        ;第二个任务的简单的事件,是否是温度模式
                  jmp jc1
jc889:          mov a,@r0
                  anl a,#191                   ;本任务事件处理完,去除本任务的事件标志
                  mov @r0,a                               
                  jmp jc888                           ;再去去除没准备好的标志
task2:
task3:
task4:
task5:
task6:
task7:
                                                      


initial:  
                   mov r7,#200    ;1S时间       
                   clr a
                   mov s5,a
                   mov tmod,a          ;定时器0工作于模式0,13位定时状态
                   mov th0,#H5MS                ;13位定时器的定时数据计算:取低5位的值做为TL0的数据,高8位的值做为TH0的数据,否则就不会对。
                   mov tl0,#L5MS                        ;定时5MS的初值
                   acall rest1380
                        ret         



;**************************************************************
;DS18B20子程序集
;**************************************************************
;//*****************************************//
; 将从DS18B20中读出的温度数据进行转换
/*18b20中取出的温度TEMPL,和TEMPH. TEMPL中的低四位代表小数位.
                                        正温度的算法: TEMPL中的高四位和TEMPH中的低三位.一起组成正温度时的温度值       
                                                                  TEMPH中的高五位代表正负符号标志.5个0时为正温度,5个1时为负温度
                                        负温度的算法: 负温度的算法基本和正的相同.不同之处在于TEMPL中的高四位和TEMPH中的低三位
                                                                  这个7BIT的数要进行取反加一操作.
                                                                  
//*****************************************/
TEMPER_COV:         /* mov tempLOK,        TEMPER_L
                          MOV tempHOK,  TEMPER_H
                          RET                          */
;精确到99.9的尾数显示 ,模仿人工有小数点的成法
   mov a,TEMPER_L
   mov b,#6
   clr c
   mul ab
   mov r3,a      ; 十位相成的积
   mov b,#10
   div ab                        ;
   clr c
   add a,r3
   mov r3,0f0h
   clr c
   cjne r3,#6,qq11  ;五蛇六入
qq22:  inc a
        jmp qq33
qq11: jc qq33
          jmp qq22       
qq33:mov b,#10
        clr c          ;好象成除法,DA,都与CY有关联
        div ab
        swap  a                 ;十位显示小数部分.个位显示C
        xrl a,0f0h    ;合成

        mov tempLOK,a        ;小数部分
        mov a,TEMPER_L
        anl a,#240
        swap a
        mov r2,a                ;
        mov a,TEMPER_H
        anl a,#7
        swap a
        xrl 02h,a                ;用异或进行数据合成,并把合成后的8位初步温度数据存入R2中
   
    MOV A,TEMPER_H
        anl a,#248   ;看高5位是0还是1
        jz  zentemp
        ;负温
         mov a,r2
         cpl a
         inc a
         anl a,#127
tempout:mov b,#10
                clr c
                div ab
                swap a
                xrl a,0f0h
            mov tempHOK,a                ;温度的整数部分
           ret
zentemp:mov a,r2   ;正温度时更好转换   
                jmp tempout
       


;//*****************************************//                                                                            
; DS18B20初始化程序
;//*****************************************//
; 这是DS18B20复位初始化子程序
INIT_1820:
     SETB DQ
     NOP
     CLR DQ
;主机发出延时537微秒的复位低脉冲
     MOV R0,#134
TSR1:DJNZ R0,$
     SETB DQ;然后拉高数据线
     NOP
     NOP
     MOV R0,#77
TSR2:JNB DQ,TSR3;等待DS18B20回应
     DJNZ R0,TSR2
     AJMP TSR4 ; 延时
TSR3:        djnz r0,tsr3
        SETB drive ; 置标志位,表示DS1820存在
                AJMP TSR5

               
TSR4:CLR drive ; 清标志位,表示DS1820不存在
     AJMP TSR7
TSR5:MOV R0,#7
TSR6:DJNZ R0,TSR6 ; 时序要求延时一段时间
TSR7:SETB DQ
    RET

;//*****************************************//
; 写DS18B20的程序
;//*****************************************//
;写DS18B20的子程序(有具体的时序要求)
WRITE_1820:
        MOV R2,#8;一共8位数据
        CLR C
WR1:
        CLR DQ
        MOV R3,#3
        DJNZ R3,$
        RRC A
        MOV DQ,C
        MOV R3,#11
        DJNZ R3,$
        SETB DQ
        NOP
        DJNZ R2,WR1
        SETB DQ
        nop
        RET

;//*****************************************//
; 读DS18B20的程序,从DS18B20中读出一个字节的数据
;//*****************************************//
; 读DS18B20的程序,从DS18B20中读出两个字节的温度数据
READ_TEMP:
        MOV R4,#2 ; 将温度高位和低位从DS18B20中读出
        MOV R1,#TEMPER_L ; 低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)
       
RE00:MOV R2,#8;数据一共有8位
   
RE01:CLR C
        SETB DQ
        NOP
        CLR DQ
        NOP
        NOP
        SETB DQ
        MOV R3,#2
RE10: DJNZ R3,RE10
        nop
        MOV C,DQ
        MOV R3,#2
RE20: DJNZ R3,RE20
        RRC A
        DJNZ R2,RE01
        MOV @R1,A
        DEC R1
        DJNZ R4,RE00
        RET
;//*****************************************//
;
;**************************************************************
timer:       
                                                            ;最高优先级任务,直接在系统中断中作为子程序调用,
                DJNZ r7,tt1                          ;时间模式
                mov r7,#200
                mov a,S5
                cjne a,#5,tts
                mov S5,#0
                cpl t2t
                setb htreadbit         ;一秒一读
                jmp tt22
tts:        inc S5               
         
                ;LED秒点控制
tt22:          
                   jb t2t,wendu1  
                   setb leddianH                ;时间模式下2个灯一起闪
                   setb leddianL
                   jmp        timeout

tt1:   
                     cjne r7,#100,tt6
;LED秒点半秒控制  
                  
                          jb t2t,wendu1  
                   clr leddianH
                   clr leddianL                ;时间模式下2个灯一起闪          
                   jmp        timeout

wendu1:                    clr leddianH
                        setb leddianL       ;温度模式下下LED只亮不闪
                        mov displaydataH,tempHOK
                        mov displaydataL,tempLOK
tt6:                ret                ;不是整秒或半秒不动LED秒点


timeout:         mov displaydataL,timeL
                 mov displaydataH,timeH                    
                   ret

writehms:           ;写入小时,分秒的子程序
                mov B,#0beh ;BEH为多字节写入的命令
                mov R2,#3  ;只写入小时和分数据和秒
            mov r0,#timeS ;写入的小时和分数据首址
                acall tx   ;调用写入
                ret
readhms: mov B,#0bfh ;0bfh为多字节读出命令               
         mov R2,#3    ;只读出小时,分,秒数据
                 mov r1,#timeS ;读出的时,分,秒数据首址
                 acall rx ;          ;调用读出
          ret
rx:                                      ;        rx接收
         acall htrest_com    ;htrest_com子程序为1830的初始化和命令字节(在B中)的发送
rx_byte1:clr a                  ;准备接收数据
                 clr c
                 mov R3,#8 ;接收位数为8
rx_byte2:nop
                 mov c,sdata  ;数据总线数据传送给C
                 rrc a        ;移入A
                 setb sclk          ;时钟总线置高
                 nop
                 clr sclk           ;时钟下跳,接收有效
                 nop
                 djnz R3,rx_byte2
                 mov @r1,a                ;接收到的数据放入内存缓冲区
                 inc r1                 ;内存地址加一
                 djnz R2,rx_byte1 ;字节未接收完继续
                 nop
                 clr srst                ;逻辑操作完毕,关闭
                 ret
tx:                              ; tx发送
                acall htrest_com
tx_byte1:mov a,@r0        ;传送数据
                 mov R3,#8
tx_byte2:rrc a
                 mov sdata,c
                 nop
                 setb sclk
                 nop
                 clr sclk                ;清时钟总线
                 djnz R3,tx_byte2
                 inc r0
                 djnz R2,tx_byte1 ;多字节传送
                 
                 clr srst
                 ret                                
;入口参数:B
htrest_com: clr srst ;复位端为0,所有数据传送终止
                clr c
                nop
                clr sclk ;清时钟总线
                nop
                setb srst ;复位端为1,逻辑控制有效
                mov a,B ;准备发送命令字节
                mov R3,#8 ;传送位为8
rxtx_byte0:rrc a                     ;将最低位传送给c
                mov sdata,c         ;位传送到数据总线
                nop
                setb sclk                ;时钟上升沿,发送的数据有效
                nop
                clr sclk                ;清时钟总线
                djnz R3,rxtx_byte0 ;8位未完继续               
                ret

rest1380:mov r0,#timeS
         mov @r0,#0    ;数据
          mov B,#8eh  ;8eh命令:写写保护,写0就充许数据写入时分秒单元
          mov R2,#1 ;只写入一个数据                   
         acall tx

          mov r0,#timeS
          mov @r0,#0    ;数据
          mov B,#80h  ;允许工作的命令
          mov R2,#1 ;只写入一个数据                   
         acall tx
         ret       
;任务欠表,决定最终任务的执行顺序                  
taskpcmap: db low keyscan, high keyscan,low GET_TEMPER, high GET_TEMPER,low display, high display
;taskpcmap:  dw  keyscan,GET_TEMPER,display
end
头像被屏蔽

出0入0汤圆

发表于 2010-4-1 10:47:22 | 显示全部楼层
非常感谢!

COOL !

出0入0汤圆

 楼主| 发表于 2010-4-1 11:14:37 | 显示全部楼层
感谢阿莫,过几天再把我用TC3.0写的DOS下的语音程序发上来.包含X86下的PWM语音,ADPCM_2BIT压缩算法..
头像被屏蔽

出0入0汤圆

发表于 2010-4-1 11:17:37 | 显示全部楼层
回复【4楼】bausrpgf6688
感谢阿莫,过几天再把我用TC3.0写的DOS下的语音程序发上来.包含知识要点:X86下的PWM语音,ADPCM_2BIT压缩算法..
-----------------------------------------------------------------------
期待啊。

出0入0汤圆

发表于 2010-4-1 12:22:31 | 显示全部楼层
顶你个用汇编的

出0入0汤圆

发表于 2010-4-11 10:45:09 | 显示全部楼层
hao

出0入0汤圆

发表于 2010-4-11 19:02:05 | 显示全部楼层
汇编=会编!!!  厉害啊   学习下!!!顶楼主

出0入0汤圆

发表于 2010-4-12 08:52:11 | 显示全部楼层
好东西啊,只是没有明白任务调度是一种什么样的运作模式,学习一下。

出0入0汤圆

发表于 2010-4-12 14:23:33 | 显示全部楼层
顶你个汇编男,我汇编很差跟你学学先,以后我也做个啥传上来

出0入0汤圆

 楼主| 发表于 2010-4-14 09:09:21 | 显示全部楼层
谢谢支持和关注我的人。很是报欠这个东西写的很乱。我也没有好好整理。有的时候猛然一看,真的是自己也不知道写的是什么意思了。这个东西最早写的雏形是2008末吧。当时在学习陈明计的SMALL RTOS51,无奈自己就是看不懂任务调度的核心原理。就是用宏汇编写的哪部分,又看了看KEIL里带的哪个时间轮片(不知道对不对??)的任务调度,调度部分也是宏汇编写的,看了有一段时间,最后还是看得很糊涂。最后就想是否可以把任务调度的问题简化些呢。堆欠是先进后出(先进的总是比后进的优先级高,因为优先级高的如果一直占用CPU,优先级低的就不会被执行,优先级低的就不会存在任务欠),这样就和任务0到7形成关联了。优先级高的任务如果不主动放弃执行,优先级低的将抢不到CPU执行权,而优先级低的一直霸占CPU,系统时钟一到将薄夺优先级低的任务的占用。这就是本程序的堆欠处理办法。
任务调度,挂起,中断主要由这几个变量控制:
taskidnum  equ  2dh      ;任务ID数
osreadybit  equ 2ch      ;任务准备好标志,准备好为1,
osinitbit  equ  2bh      ;任务被中断位表,被中断了为1
oswaitbit  equ  2ah      ;任务被挂起位表,被挂起了为1

任务挂起结构:
oswaitram  equ  09h      ;挂起任务的结构首址,8*3=24,09H到21H  
对应如下:
waittime   DB ?          ;由R3复制而来延时时间
taskpc     DW ?          ;任务的断点,即OSWAIT的下一条指令PC地址

而这几个是CPU判断是否是处于非任务区(临界?):
saveinit   equ  32h ;临时变量,用的是动态变量区
savewait   equ  31h
savesp     equ  30h      ;临时变量保护
oswaitflag  bit  2fh.0    ;进入OSWAIT子程序保护区标志
ostaskswflag bit  2fh.1   ;进入任务切换区标志
osidltask    bit  2fh.2   ;进入最低优先级任务标志
osinittaskflag bit  2fh.3  ; osswflag.7 ; 中断任务保护区

系统(??这是系统吗)提供的函数就这2个(汉):
ljmp tasksw ; 任务主动要求放弃CPU。释放控制权,将控制权交到下一个优先级的任务
oswait:   ;系统延时子程序,系统时钟×(1到63)本任务暂不需要CPU控制权了,将控制权交到下一优先级任务。
主要就这么多了。呵呵,很简单吧,系统对CPU,RAM的占用很小,当然功能也很少了。

我也是一个菜鸟,如有不对之处,还请多多拍砖,指正。

出0入0汤圆

发表于 2010-4-15 16:05:52 | 显示全部楼层
楼主能传个原理图看看吗?

出0入0汤圆

发表于 2010-4-15 16:15:54 | 显示全部楼层
汇编还是很难懂啊,呵呵

出0入0汤圆

发表于 2010-9-13 10:31:34 | 显示全部楼层
怎么没有原理图,楼主发一下图共同学习.

出0入0汤圆

发表于 2010-9-13 11:02:47 | 显示全部楼层
哈哈,汇编,顶一下!

出0入0汤圆

发表于 2011-10-14 03:15:46 | 显示全部楼层
期待C语言

出0入0汤圆

发表于 2011-10-14 09:00:46 | 显示全部楼层
汇编啊  我是不会编啊

出0入0汤圆

发表于 2011-10-14 11:24:35 | 显示全部楼层
我帮着传个C51版本的。


/***********************bausrpgf6688 2010年3月作品1602四位初步测试通过*********************/

#include <at892051.h>
#include<intrins.h>
#define uchar unsigned char
#define        uint  unsigned int
#define MAXTASK 4
extern void oswait(uchar);
uchar SAVESP,SAVEWAIT,SAVEINIT;
uchar OSWAITBIT,OSINITBIT,TASKIDBIT,TASKIDNUM,OSREADYBIT;
uchar bdata OSSWFLAG;

uchar OSWAITRAM[3][MAXTASK];                 

/*注意:第一脚是5伏,第二脚是地!和普通的1602相反!

背光已经在内部接到电源上了,常亮。如需控制背光,需要断开液晶背后的J2跳线,从A引出背光线

  第4脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
  第5脚:RW为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作。
  第6脚:E(或EN)端为使能(enable)端 //当E脚由高电平跳变成低电平时液晶块执行命令
1.VDD
2.GND
3.VO
4.RS
5.R/W
6.E
7-14.DB0-DB7                                                                  */

uchar bdata lcdbuff;
uint cpuidl,cpuidl2=0;                                                 //CPU空闲计数
sbit e=P3^7;
sbit rs=P3^4;
sbit rw=P3^5;
sbit led=P3^3;
sbit AN=P3^0;
sbit LCD7=P1^7;
sbit LCD6=P1^6;
sbit LCD5=P1^5;
sbit LCD4=P1^4;
sbit lcdbuff0=lcdbuff^0;
sbit lcdbuff1=lcdbuff^1;
sbit lcdbuff2=lcdbuff^2;
sbit lcdbuff3=lcdbuff^3;
sbit lcdbuff4=lcdbuff^4;
sbit lcdbuff5=lcdbuff^5;
sbit lcdbuff6=lcdbuff^6;
sbit lcdbuff7=lcdbuff^7;

/**************字模*****************/
uchar code cc[12]="I LOVE MCU!";                   //字符加空格总共11个,第十二个是个0
uchar code cc2[9]="CPUWORK=";
/************函数声明***************/
void r_BF();
void w_cdata(void);
void w_com(uchar com);
void w_sting(uchar string[]);
void w_sting2(uchar string2);
void init_lcd();
void cg_w();
void w_word(uchar word);

/************函数说明*********************
**主要用来初始化一些设置显示、输入模式、**
**显示开关、光标、移位、功能、地址                **
******************************************/
void w_com(uchar com){
        r_BF();
        lcdbuff=com;
        rs=0;
        rw=0;
        w_cdata();
}
/*************写字符***************/

/************初始化函数*************/
void init_lcd()
{   w_com(0x2c);                 //功能设置为四位数据总线
        w_com(0x01);                 //清屏
        w_com(0x06);                 //设置显示输入模式(AC指针自加1显示不移位)
        w_com(0x0c);                 //显示开/关设置(设置显示、光标和闪烁开关)
}
/************读忙标志BF*************/
void r_BF()
{
        LCD7=1;                                          //BF端口在DB7
        rs=0;
        rw=1;                                          
        e=1;                                          //RS=0;RW=1;E=1表示读忙标志BF
        while(LCD7);                          //若内部操作位BF忙CPU就等待BF不忙才能操作
        e=0;
}
/*********写命令的公共部分**********
**************函数说明**************
**因为我们定义为四位数据总线所以每**
**发送一字节要做两次发送先发送高四**
**位再发送低四位                                  **
***********************************/
void w_cdata(void)
{
        LCD7=lcdbuff7;
        LCD6=lcdbuff6;
        LCD5=lcdbuff5;
        LCD4=lcdbuff4;
        e=1;                           //当E脚由高电平跳变成低电平时液晶块执行命令
        _nop_();
        _nop_();
        _nop_();
        e=0;                                //当E脚由高电平跳变成低电平时液晶块执行命令
       
        LCD7=lcdbuff3;
        LCD6=lcdbuff2;
        LCD5=lcdbuff1;
        LCD4=lcdbuff0;
        e=1;
        _nop_();
        _nop_();
        _nop_();
        e=0;                               
}


/************函数说明*********************
**用来把自己所创造的字符写入CGROM*********
******************************************/
void w_sting(uchar string[])
{        uchar ii=0,yy;
    while((yy=string[ii++]))
        {
        r_BF();
        rs=1;
        rw=0;
        lcdbuff=yy;
        w_cdata();
        }
}
void w_sting2(uchar string2)
{        uchar ii,yy;
    for(ii=0;ii!=3;ii++)
        {
        switch(ii)
        {
        case 0:     yy=string2/10+48; break;
        case 1:     yy=string2%10+48; break;
        case 2:         yy=37;            break;
        }
        r_BF();
        rs=1;
        rw=0;
        lcdbuff=yy;
        w_cdata();
        }

}

void TaskB(void){
                                                     //任务只在本任务中执行一次
        while(1){
                 w_com(0x01);                 //清屏
                 w_com(0x2c);                 //功能设置为四位数据总线,显示第二行。
                 w_com(0x80+0x02);    //第一行2列。
                     w_sting(cc2);                   
                         w_com(0x80+0x44);    //第二行4列。
                     w_sting(cc);
                 
                 oswait(255);
                 oswait(255);
         oswait(255);
                 w_com(0x2c-0x08);                 //功能设置为四位数据总线,不显示第二行。
                 oswait(255);
                 oswait(255);
         oswait(255);
                 
             }
                    }



void  TaskC(void)
            {  uchar tt;
                   while(1){
                                   cpuidl=TH1;
                                cpuidl=cpuidl<<8;
                                cpuidl=cpuidl|TL1;
                                cpuidl=cpuidl/99;
                                cpuidl=cpuidl+cpuidl2;
                                TH1=0;
                                TL1=0;
                            cpuidl2=cpuidl>>1;
                                tt=        cpuidl2;
                                w_com(0x80+10);    //第一行10列。
                                w_sting2(99-tt);          //CPU占用率
                                oswait(0);
                                }
                }
void  TaskD(void)
            {
                                   while(1){
                                   led=~led;
                                   oswait(10);
                                }
                }

void  TaskE(void)
            {
                                   while(1){
                                   AN=1;
                                while(AN==0) AN=1;
                                   oswait(0);
                                }
                }





void main(void)
{        TASKIDNUM=0;  //;任务指针指向第0个任务
    TASKIDBIT=1;   //;任务指针指向第0个任务
        OSREADYBIT=255;          //所有任务全准备好就绪
        OSSWFLAG=  0;      //
    TMOD = 17;                   //定时器0,1,都工作于16位定时模式
        TL0 = 0x0f0;
        TH0 = 0x0d8;
    TL1 = 0;
        TH1 = 0;                        //定时器1没充许启动和开放中断
        ET0 = 1;
        EA  = 1;
    init_lcd();
        TR0 = 1;
        TaskB();  //这里必需指向所要执行的第一个任务
}

下面是完整的工程:OS_1602_4BIT显示字符ourdev_684816HHAOB0.rar(文件大小:89K) (原文件名:OS_1602_4BIT显示字符.rar)

出0入0汤圆

发表于 2011-10-19 11:38:38 | 显示全部楼层
感谢阿莫,感谢楼主,让我有学习的平台

出0入0汤圆

发表于 2013-2-28 11:40:39 | 显示全部楼层
很不错!!

出0入0汤圆

发表于 2013-7-12 23:55:45 | 显示全部楼层
不错不错!收藏

出0入0汤圆

发表于 2013-7-14 13:36:31 | 显示全部楼层
非常好的资料 收藏了

出0入0汤圆

发表于 2013-7-15 10:09:08 | 显示全部楼层
带任务调度啊。。。羡慕

出0入0汤圆

发表于 2013-7-15 18:26:18 | 显示全部楼层
帮顶 看看

出0入0汤圆

发表于 2013-7-15 18:33:05 | 显示全部楼层
玩 asm 的不多了,

出0入0汤圆

发表于 2013-8-12 00:33:24 | 显示全部楼层
mark               
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-16 02:55

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表