打印
[51单片机]

利用定时器分频通过一根IO线往外发送数据(汇编)的问题

[复制链接]
1188|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hbc0602|  楼主 | 2014-3-5 09:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
由于工作需要需要通过一根IO线往外发送8位的命令,以下程序是老板定的一个雏形,不大明白:
流程大概是:定义两个缓存来存放要发送的数据,通过RRC指令从低位开始每1MS往外发一位。
当两个缓存里的值都是0FFH时认为没有数据要发送。发送从低电平开始,高电平结束,中间是数据位共10位。
程序代码:
HBQ_DAB BIT P2.1 ;发送端口

T_NN  DATA 33H
HBQ_DA  DATA 34H  ;要发送的数据缓存
HBQ_DB  DATA 35H        ;要发送的数据缓存
HBQ_DAA   DATA 36H ;缓存发送数据

HBQ_DA_OK  BIT 20H  ;是否需要发送标志

;=====主程序===============
ORG 00H
LJMP START
ORG 0BH
LJMP TM0
此处仍需ORG 0A0H?为什么?
;=======
START: MOV SP,#0C0H
MOV P0,#0FFH
MOV P1,#0FFH
MOV P2,#0FFH
MOV P3,#0FFH  ;IO口初始化

BG_T4:  MOV R0,#0C0H ;开机清00-C0H
BGG:    MOV A,#00H
        MOV @R0,A
        DJNZ R0,BGG

MOV TMOD,#01H   ;选择定时器T0
MOV TCON,#00   ;关闭定时器T0,关闭EA总中断,清除定时T0溢出标志位
MOV TH0,#0B8H
MOV TL0,#00H      ;T0定时10MS初值
SETB TR0  ;启动T0
SETB ET0  ;允许T0中断
SETB EA  ;开放总中断EA

MOV HBQ_DA,#01100111B
JMP $
TM0:  PUSH ACC
    PUSH PSW
;延时10MS进入中断后,关闭T0,重新分配T0初值,再启动T0,实现T0十分频
CLR TCON.4
MOV TH0,#0F8H
MOV TL0,#0CDH  ;定时1ms初值
SETB TCON.4
        ;------------------
        ;1/10ms波特率
        ;如果有数据,就会发送 一个起始位+8个数据位+1个结束位 共10bit
        ;------------------

        INC T_NN  ;中断1MS计数
        MOV A,T_NN
        CLR C
        SUBB A,#10
        JNC TM_001                ;如果CY=0则跳转,当T_NN小于10时,CY=1,往下执行;当T_NN大于等于10时,CY=0,跳转重新给T_NN清零
        ;------------------
JNB HBQ_DA_OK,TM_002      ;HBQ_DA_OK:判断是否在发送状态,为1时是正在发送,为0时没有发送任务

TM_003: MOV A,HBQ_DAA             ;HBQ_DAA:发送时的移位寄存器,发送顺序:从低位输出 ->C ->HBQ_DAB 高位补1,发送完后HBQ_DAA会变成0FFH,如果HBQ_DAA中为0FFH,则认为无发送任务
        SETB C ;假设发送3CH,0011 1100
        RRC A       ;从低位开始发送,发送第一位0后变成1001 1110,CY变成了0
        MOV HBQ_DAB,C   ;HBQ_DAB:DA引脚P2.1,把CY的值给到发送管脚
        MOV HBQ_DAA,A   ;发送了一位之后把没发送的位保留在        HBQ_DAA,同时退出T0中断,等待进入下一个中断继续发送


TM_002: POP PSW
        POP ACC
        RETI ;退出中断

TM_005: MOV HBQ_DAA,HBQ_DA   ;把要发送的数据放在HBQ_DAA缓存
         MOV HBQ_DA,#0FFH ;然后HBQ_DA的内存单元赋值为0FFH

TM_008: CLR HBQ_DAB ;把DA数据接口置0
        SETB HBQ_DA_OK ;设置为1,需要发送
         SJMP TM_006 ;跳转并退出中断

TM_007: MOV HBQ_DAA,HBQ_DB  ;
        MOV HBQ_DB,#0FFH
        SJMP TM_008

TM_001: MOV T_NN,#00 ;发送一个数据开始的准备
         SETB HBQ_DAB ;把DA数据接口置1
                 CLR HBQ_DA_OK ;清除需要发送标志位
         MOV A,HBQ_DA ;待发送的值存放在HBQ_DA
        CJNE A,#0FFH,TM_005 ;判断是否为0FFH,如果不是,说明有值要发送,跳转

         MOV A,HBQ_DB ;如果为0FFH,存到HBQ_DB里去
        CJNE A,#0FFH,TM_007;判断是否为0FFH,如果不是跳转发送,是则退出


TM_006: POP PSW   ;退出中断前出栈
POP ACC
RETI
END
;==========================================================


其中,主程序给T0定时10MS赋了值,然后进入中断后重新赋值,不过赋值的是1MS的定时。
那么从第二次进入中断开始,每次进入中断的间隔是10MS还是1MS?KEIL仿真结果是第一次进入中断10MS,之后每次都是1MS进入。既然这样,为什么不直接定时1MS就完了?

相关帖子

沙发
hbc0602|  楼主 | 2014-3-6 22:52 | 只看该作者
这个帖子就这么沉了?

使用特权

评论回复
板凳
受不了了| | 2014-3-6 22:58 | 只看该作者
本帖最后由 受不了了 于 2014-3-6 23:02 编辑

第一个十毫秒怕对方开机后还没稳定,也或许是从原来的程序拷贝而来所以没有更改,第一次赋值反正不影响后面正式工作

使用特权

评论回复
地板
ayb_ice| | 2014-3-7 07:59 | 只看该作者
如果是单向的话,可以考虑模拟UART TX

使用特权

评论回复
5
hbc0602|  楼主 | 2014-3-7 09:16 | 只看该作者
受不了了 发表于 2014-3-6 22:58
第一个十毫秒怕对方开机后还没稳定,也或许是从原来的程序拷贝而来所以没有更改,第一次赋值反正不影响后面 ...

有那么点道理,但是我觉得不只是这样...

使用特权

评论回复
6
hbc0602|  楼主 | 2014-3-7 09:18 | 只看该作者
ayb_ice 发表于 2014-3-7 07:59
如果是单向的话,可以考虑模拟UART TX

UART TX口用不上。老板就认定了要用一根IO。因为从机也是一根IO来接收,也是定义的1MS接收一位。UART有其他用途。

使用特权

评论回复
7
ayb_ice| | 2014-3-7 09:36 | 只看该作者
hbc0602 发表于 2014-3-7 09:18
UART TX口用不上。老板就认定了要用一根IO。因为从机也是一根IO来接收,也是定义的1MS接收一位。UART有其 ...

都说了模拟了

使用特权

评论回复
8
ayb_ice| | 2014-3-7 09:36 | 只看该作者
hbc0602 发表于 2014-3-7 09:18
UART TX口用不上。老板就认定了要用一根IO。因为从机也是一根IO来接收,也是定义的1MS接收一位。UART有其 ...

都说了模拟了

使用特权

评论回复
9
hbc0602|  楼主 | 2014-3-7 09:46 | 只看该作者
ayb_ice 发表于 2014-3-7 09:36
都说了模拟了

哦。。。不好意思,漏看了模拟两字。这个本来就是用定时器来模拟UART发送吧。只是波特率比较低。

使用特权

评论回复
10
ayb_ice| | 2014-3-7 10:15 | 只看该作者
hbc0602 发表于 2014-3-7 09:46
哦。。。不好意思,漏看了模拟两字。这个本来就是用定时器来模拟UART发送吧。只是波特率比较低。 ...

是岂不更好,模拟对了就可以了

使用特权

评论回复
11
cjseng| | 2014-3-8 09:26 | 只看该作者
hbc0602 发表于 2014-3-7 09:16
有那么点道理,但是我觉得不只是这样...

不知是这样,还会是哪样呢?
第一次的定时时间对后面的程序没有影响,实际上随便定是多长都可以的。我写程序时,这些初始化的程序都是从别的项目直接拷贝过来的,定时器初值也不去管它,重新赋值时改成正确的就行。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

27

帖子

0

粉丝