打印

问程序的同学,进来这里吧,别纠结了。(更新9-21)

[复制链接]
38704|176
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
NE5532|  楼主 | 2011-8-2 19:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 NE5532 于 2012-1-12 22:19 编辑

公告:本文已不再更新,后续内容请看本版精华贴中《程序调试黑宝书》一帖

如果你需要提下列问题,请自觉阅读本贴,如果读完以后你还要贴代码,偶就没办法了。

1.I2C程序怎么调
2.为什么我的程序不对,然后贴一堆代码上来
3.为什么我这样写对,那样写不对

首先建立一个观点:程序是搞电子技术里面最最最最简单的东西,因为他最最最说得清楚,你这样写了,处理器就会这样做,如果没有按照你的想法来做,那一定是你没写对。

话说硬件设计还需要很多数据库似的知识支撑,高频还需要黑色艺术细胞,学写程序除了背点语句,掌握一些基本技巧外加做好规划之外,真的不需要啥东西,会说话就会写程序。

现在言归正传,前面说了,程序就是你想处理器做什么。在你动手之前,应该先找张白纸,写下你想干什么,然后画出流程图(贴代码问程序的请扪心自问,是否画了流程图)。再明确程序的模块划分,每个模块的输入、输出变量和占用资源。

模块划分就是把任务拆分成互不相关的部分,比如软主机I2C程序可以拆分成发生启动位、发送停止位、发生一个字节、接收一个字节、发送应答位、发送非应答位、接收一个字节、读取应答位等。

其次是要想方设法从最基本的地方开始调试,来这里贴代码的都是一贴一大篇,要知道我们都不敢这样写代码,何况是自称新手?程序要写一块调一块,细到什么程度?真是菜鸟,就细到写完发送启动位就送出来拿示波器检查,检查边沿、电平和时间参数是否跟自己设计的值一样。

模块有大有小,取决于站在哪个层次看问题和写程序的熟练程度。如果是从一个使用PCF8563的数字钟系统来说,I2C通讯整个可以看成一个模块。另外如果调试技术够成熟,写完整个从器件选址应答过程再看也不迟,甚至连示波器都不需要。

【未完待续】

感谢大家强烈围观,特别还有各位老鸟的围观式鼓励!

上次说到,程序要分模块规划,这是把程序化大为小的基础,特别是对初学者,否则会感觉老虎吃天,无从下口。

这里补充说一下,模块和函数是不同的概念。模块是从程序功能的角度来划分的,函数是为了给程序减肥,把多个地方需要使用的部分写成函数。有时候一个模块刚好就是一个函数,比如lcd_display(*p),也可能一个函数什么模块也不是,单纯是为了减少代码量,比如

FUNC_PORTA_INPUT:
      BSF  STATUS,RP0
      MOVLW 0XFF
      MOVWF PORTA
      BCF  STATUS,RP0
      RETURN

就没有任何模块的意义,只是因为PIC改端口方向很费事,多处需要调用,所以顺便写成函数。再顺便提醒一句——宏不省代码。

现在是初学者最关心的部分,如何调试程序了。我们推荐按照函数或者模块的方式来调试,有的初学者说,我的程序没写完,怎么调?我们说——从你能看到现象的地方开始调起。

比如有人写了个秒表,

char time;

while(1)
{
  func_time(time++);  //计时
  func_disp(time);       //显示
}

现在程序不对了,怎么调呢?

while(1)
{
  time=0;
  func_disp(time);       //显示
}

先把显示调对了,不就可以观察到程序是否按设计运行了么。这里做了一个假设,直接把time赋值为0,有时候一个固定值不够,还要多试两个,最极限情况,就是写个循环来显示全部可能值。

这一关过了,显示就基本正常了,如果程序还不对,那肯定是计时部分程序出了问题。

好了,这次先到这里。下次我们再来讲讲如何跟踪不听话的程序以及这些程序是为啥不听话的。

【未完待续】

我们先打断一下原来的计划,插播一条刚刚收到的消息。这几天问C语言怎么学的人好像有点多,我们可以这样说——会C语言和会写程序是不一样的,会写程序和会搞开发也是不一样的。

语言有很多种,汇编、C、java,甚至中文都是语言,语言是用来表达事情的,编程可以用自然语言么?可以啊!

如果(肚子饿了)
  就:吃饭
否则(继续玩)

是不是感觉跟if语句很像,如果编译器可以认识这个语句,那这几行就可以当计算机语言了。学习C语言,实际是学习如何用计算机看得懂的语言来表达事情罢了。所以会C语言不见得会写程序,人家用汇编一样可以表达呢。

所以我们得到一个结论——学C语言不如学如何去发现问题解决问题,当你有了解决问题的能力,随便找一种语言(前提是好用,例如用汇编写数据库就是自虐)来描述就可以了。

最后再说下开发,搞电子,前期是爱好,后期是吃饭,说白了,用最古老的51单片机,写个龌龊的程序,卖出去每年赚10万和用最ARM,操作系统,java写一个卖不掉的产品,你选哪边?

好了,希望各位纠结C语言语法或者在那里背51汇编指令的同学能够清醒了,偶从不记指令,要用的时候翻书就是了。

今天会再次更新,继续上次的内容。

2011-8-21

睡觉的同学可以醒了!今天我们讲实用技术——如何让不听话的程序听话以及为什么程序不听话。

前面已经说了,程序是搞电子技术里面最最最最简单的东西,这里再加上一条,所有的处理器(只要不是多内核技术的)在同一时间都只能处理1条指令。对这些程序来说,无论你是原生态的裸奔还是花哨的操作系统,程序只能在2个地方被执行——中断里面和中断外面,ARM的各种模式也可以看做中断。

再让我们来回忆一下,只要你按照自己的想法写了程序,写对了,入口条件满足了,程序就应该按照你的想法去执行,当他不听话的时候,只要检查这些条件是不是成立了就可以了。

比如

If(条件A满足;条件B满足;条件C不满足)
{
  D事件;
}

如果这个判断没有照你的预想执行,那么你可以这样检查

首先屏蔽判断语句

//If(条件A满足;条件B满足;条件C不满足)
//{
  D事件;
//}

如果这样写,D事件都没有被执行,那么OK,不关判断语句的事,你先得检查“做D事件”这个语句为啥没正确执行了,这个是基础。

【小结】找程序问题的时候应该从简到繁,排除干扰从核心找起。

现在“做D事件”已经正确了,来找if语句本身的问题

串口发送条件A
串口发送条件B
串口发送条件C
If(条件A满足;条件B满足;条件C不满足)
{
  D事件;
}

这是一种跟踪调试的方法,把单片机串口连接大PC上,用串口助手看下发送出来的条件ABC就知道自己有没有犯啥低级错误了。

【小结】善于用输出通道对程序运行情况进行跟踪,一般来说程序执行不正常都是因为自己编写或者逻辑上犯了低级错误,跟踪一下,就可以发现了。

【注意】有的人(特别是某部分“高手”)会说这不就是仿真器的断点功能么,搞得那么复杂。为啥不用仿真器,我后面再说。初学者请跟着我的思路来做,我可以让你在5年以后在这些“仿真高手”面前笑傲江湖。

如果这里输出都是正确的,那怎么办呢?没关系,咱进来再发发看。

If(条件A满足;条件B满足;条件C不满足)
{

串口发送条件A
串口发送条件B
串口发送条件C

    D事件;
}

如果在这里发现条件ABC出现了错误,那么就要关心下是不是中断的问题了。

【结论】在直线程序前后发生数据莫名其妙改变的,一般都是中断所致。

比如一个经常犯的错误是:

串口中断服务程序
{
从串口缓冲区取数据;
}

串口中断使能;
While(!串口收到数据中断标志)
从串口缓冲区取数据;

因为在串口中断服务程序里面已经读了缓冲区后,硬件已经清除了“串口收到数据中断标志”所以外面的while循环自然等不到这个标志置位了,表现就是程序死机。

程序debug内容太多了,这节课讲不完,先课间休息哈,下次再来。

2011-9-7
今天我们接着讲Debug

一般来说,程序的BUG可以分为两类:逻辑错误和低级错误。逻辑错误是指设计本来就存在错误,比如

if (楼主是火星人)

then

明显这是不可能发生的事,避免逻辑错误主要靠遵守基本的设计规范和画流程图检查。常见的基本设计规范包括

a.动手前先做好程序规划,包括需求分析和画流程图
b.中断内外都在使用的临界资源需注意保护
c.中断内使用了的资源要现场保护和现场恢复
d.PIC单片机retlw查表长度不能超过255
e.变量上电要赋值
f.模块只能操作自己需要的资源(端口、变量位)
g.模块化清晰
h.不要乱GOTO,不管是汇编还是C


至于低级错误,比如常见的

a.单片机没有上电(大家不要笑,真实发生,而且还不是菜鸟所为)
b.没有焊晶体
c.编辑器开的一个工程,编译器开的另一个工程(常见于把工程到处复制备份又不改名字的人)
d.熔丝没有设置
e.汇编程序最后一行没有回车
f.51单片机acall和lcall出现跳飞


这里举例说明下低级错误

比如toshiba 900L系列汇编,必须以回车符结束,结果我们有这样两个文件

[main文件]
.......
#include a.inc

funb:
  nopa
  nopa
  nopa
.......


[a.inc文件]
func:
  nopb
  nopb
  return        ;这行没有敲回车符


结果编译器不认识这个return,在执行了nopb语句以后直接执行了nopa,给人的现象就是调用了func函数,却执行了一个无厘头相关的另一个函数funb。

于此类似的还有PIC单片机汇编的标号问题

lab:
  nup


由于PIC的IDE环境MPLAB允许编号不带冒号,所以被敲错的nop指令将被认作标号,并仅在编译输出一个警告(注意不是错误),而我们大部分人是没有习惯去看编译器的警告信息的,这行指令就这样被放过了。

这些错误都可以通过习惯加以纠正,比如我习惯在汇编文件开头结尾加分隔线

;----------------------------------------------------   ;我是华丽分隔线!!!!

这样即使认掉一行,也是注释行,木有关系。

另外就是要注意看编译器输出的警告信息,不能看到hex文件生成就万事大吉。

我们这里再声明一次“一般来说,问题越奇怪,错误越低级”

先不要看原因,我们来看现象:我们有一个51的汇编程序,keil编译器,在程序临近编写完毕时,发现在程序开始,初始化中间加一个nop程序就要飞,加2-7个nop也要飞,加8个nop就没有飞,此时总中断是没有开的。单片机外设里没有能把程序弄飞的东东。

奇怪吧!








;------------------我是华丽的隐藏分界线,斑竹木删偶哟,怕怕-----------------








原因:本来51汇编是没有call这条指令的,但是keil为了方便懒人,加了这条伪指令。在编译的时候,按理应该自动匹配为acall和lcall,但是这个keil偏偏没有匹配,程序总长度又恰好临界于acall的边界,所以一个nop就可以“让程序飞”

我们是这样找到这个问题的:

首先总中断没有开,那么没有其他程序可以干扰这里;其次外设里没有能够弄死单片机的;那么能飞的情况就剩下乱飞乱跳这一项了,51的查表不会弄死,而且初始化也不需要查表,所以怀疑到call上,查看了指令表后发现这是伪指令(这点确实疏忽了,认为所有单片机都有call指令,如果及早发现,就没有这个问题出现了),看反汇编,发现确实没有正确匹配acall和lcall。

有同学举手:我们不会看反汇编
答:程序校验会不会?先用call编译了以后烧进去,再把一个绝对应该lcall的call改成lcall,编译,校验,看一样不一样就OK啦。

我们遇到的最变态的问题是Toshiba 900L上出的,现象是for循环跑死,出不来。

for (i=0;i<100;i++)
{
  _asm_func();
}


_asm_func();是一个用汇编编写的函数,猜猜死机的原因是啥来着?900L编译器为了加速程序运行,将自动分配寄存器变量并且不打招呼,i变量因为在for内,被判断为“频繁使用”,故分配到了xiz(900L内核的一个32位寄存器)内,而_asm_func();函数内,正好用了这个寄存器,所以for循环的退出条件始终得不到满足,自然死机咯。

这个问题属于比较难找,也比较变态的,最后是通过看反汇编和测试for循环分配寄存器变量的规则找出来的,严格说来属于编译器设计的不完善。

好了,今天的课讲完了,给同学们留个课后作业:单片机程序错误从时间和空间上看有没有规律,如何运用这些规律来找程序错误呢?

【未完待续】

11-9-21
我们现在先来看看上次的课后作业有什么效果。为什么说单片机程序错误从时间和空间上看又规律呢?因为从本质上看,单片机只有一个处理器(多核的暂时木讨论),程序始终要得到CPU才能被执行,这样程序本质上也就分为2类——顺序执行(按书写者的安排运行),和另一类——外部条件触发,例如中断触发或者使用操作系统的模式,模块之间由事件驱动。

应该说顺序执行的程序是最容易找到问题的,因为程序的来龙去脉很清楚,只要在入口和出口进行跟踪就可以找到“什么条件没有正确”,对于有中断或者操作系统(严格来说是多任务系统)来说就没那么幸运了,因为中断部分的执行事件可能完全和设计者所想的相反,就像上面中断标志被抢先清除的例子,但看等待中断标志这一段程序是完全没有错得,除非Debuger能“回过神来”,想到还有个“看不见”的中断在跑,否则打死也想不出来谁清了中断标志。

了解了程序这两个特性以后,就可以用他们来帮助我们Debug,当遇到程序出现问题无从找起时,可以试探性关闭中断,例如

disable IE

func_err
{
}

enable IE

其中开关IE的语句是后面加上去的测试语句,怀疑func_err的执行条件被中断破坏,那么就禁止中断在这里面发生,如果条件依然被破坏,那么绝大部分可能性与中断无关了。

再比如前面举的51单片机汇编编译器的问题,我们在无厘头的情况下可以去找规律比如

init
main

这样执行是正确的

init
thing_a
main

就出现错误,那么索性把thing_a换成nop,如果这样还出现错误,那么可能是跟时间相关,就是main被执行的时间(因为有的中断还是可能在特定时间发生的,假如因为单片机复位的原因,每次都是在相同的地方执行中断,还是可能造成这种现象哟)

那么我们开始加2个NOP,3个NOP,4个NOP,看程序是否正确,当我们加到8个NOP的时候,发现程序对了,然而这很无厘头,因为在main之前,初始化应该是想做多久就做多久的,所以才有了后面去找编译器问题的想法。

好了,我们总结一下今天的内容:程序的执行有顺序和中断两种,包括OS的并发进程在内,找程序BUG的重要步骤之一是确定程序的执行条件是被前面的顺序流程破坏,还是被中断破坏。

【下期预告:谁适合于找BUG?】







评分
参与人数 15威望 +17 收起 理由
ttl_web + 2 很给力!
soul11201 + 1
ocon + 2
baipengwei + 1
sun520up + 1

查看全部评分

相关帖子

沙发
hopewise| | 2011-8-2 20:46 | 只看该作者
不错,学习了.
就我以前的经验来了,最好的学单片机方法是:
1.编程结构----这是最重要的.
  好的编程结构,它能使你调试非常方便,差的编程结构,使你很累.
  比如,我的编程结构是这样的:

;**************程序开始*****************
code    .section   'code'
    org      000h
    jmp     reset
    org      004h                          ;外部中断0
    jmp      ext0_interrupt
    org       008h                          ;定时器0中断
    jmp      t0_isr
    org       0ch                           ;定时器1中断
    jmp      t1_isr
    org       10h                           ;A/D中断,没用到,返回
    reti      
reset:
    snz      STATUS.4                     ;PD位(位4)=0,则是系统上电或执行CLR WDT, 执行HALT则置1.
    jmp      INITIAL                        ;是上电,则执行初始化操作
    mov      a,00000111b                  
    mov      wdts,a
    mov      A,00000000B               ;晶振采用内部的RC(4MHZ)---HIRC,定时器timer0
    mov      CTRL0,A               
    mov      a,10000101b                ;允许WDT中断---WDT时钟来源于内部的RC振荡器,下降沿触发中断
    mov      CTRL1,A
    mov      a,11111111b
    mov      PAC,A  
    .
    .                                              ;其它I/O内容
    .
     jmp      OKWORK                      ;执行halt指令后,还要判断是WDT是在sleep模式溢出(STATUS.5=1)还是正常模式溢出(STATUS.5不定)
INITIAL:         
        mov      a,00000111b                  
        mov      wdts,a
        mov      A,00000000B                  ;晶振采用内部的RC(4MHZ)---HIRC,定时器timer0
        mov      CTRL0,A               
        mov      a,10000101b                  ;允许WDT中断---WDT时钟来源于内部的RC振荡器,下降沿触发中断
        mov      CTRL1,A
        mov      a,11111111b
        mov      PAC,A  
        mov      a,11111111b
        mov      PAPU,A
        mov      a,00101011b              
        mov      PAWK,a                                                   
        mov      a,11111111b
        mov      PA,A
         .
         .                                              ;其它I/O内容(注意:与上面略有区别)
         .
OKWORK:  
       snz      status.5                          ;PD位(位5)=0,则是系统上电或执行CLR WDT, 执行HALT则置1.
       jmp      inital_ram                        ;为0,则执行初始化     
       jmp      sleep_man                      ;为1,则进入sleep状态
inital_ram:
       mov      a,40h                             ;清ram变量
       mov      mp0,a
clrram_loop:        
       clr       iar0
       siz       mp0
       jmp     clrram_loop                        ;clr ram
       mov     a,256-125                         ;125uS中断一次(4MZH,分频率为4)
       mov     tmr0,a
       mov     a,92h
       mov     tmr0c,a  
       mov     a,0ffh
       mov     tmr1,a
       mov     a,01011000b
       mov     tmr1c,a
       mov     a,00001111b                     ;开外中断,定时中断,全局中断                                            
       mov     intc0,a
       clr        intc1
main:  
       mov      a,t_125us
       sub       a,64
       snz       c                             ;到了8mS吗   
       jmp       main                        ;没到,则跳到main
main1:
      clr      t_125us                        ;到了,则清t_125us变量
     snz      halt_b                          ;halt_b 等于1则进入睡眠状态
     jmp      $+2                             ;为0则正常执行指令
     jmp      sleep_man                    ;睡眠管理
     clr        wdt                                ;喂狗
     call       ic1620_init                     ;HT1621初始化
     call       ic1620_drive                   ;HT1621驱动  
     call        dis_translate                  ;LCD的段码转换   
     call        key_scan_man               ;按键扫描管理
     call        led_out_man                 ;按键led灯输出管理   
     call        open_inspection_man      ;马达开门行程开关检测管理  
      call       close_inspection_man      ;马达关门行程开关检测管理
      call       voltage_chk                    ;电池电压检测管理
      call       time_man                       ;时间管理
      call       motor_man                     ;马达驱动管理(开门)                                 
      call       buz_work                       ;蜂鸣器管理
      call       baojing_man                   ;报警输出管理
      call       HM_inspect_man              ;换码开关管理
      call       shuiyin_man                    ;水银开关检测管理
      call       key_deal_man                 ;按键处理管理  
       call      disp_man                       ;显示管理
       call      door_man                       ;门行程开关管理
       call      auto_man                       ;自动锁门管理(关门)
       call      orange_key_led_man        ;橙色键灯管理
       call      blue_key_led_man           ;蓝色键灯管理
       jmp     main
按键扫描,蜂鸣器管理等子程序,一般项目,我基本上copy过来,不用修改.
子程序一个个调好(有的子程序是独立的,故易调好.有的子程序要依靠的其它子程序才能调好.如下面举过例子,其中的变量lock_time来源于按键处理管理子程序.  

;******************************************
;*********************马达驱动(开门)管理***
motor_man:      
        sz       lock_time                        ;有马达驱动信号吗?
        jmp      lock_On_operation          ;有,则ON马达
        clr      dt2                                 ;没有,则关闭马达
        clr      f_magnet
        ret
lock_on_operation:
        sz       position_open
        jmp      off_lock_operation
        set      dt2                              ;驱动马达
        ret
off_lock_operation:
        clr      dt2
        clr      f_magnet
        ret   

2.选中最适合的单片机类型.-----   之前我了解过pic,C51,合泰等,都花一点时间弄了一下(含买仿真器等等),最后比较后,才选中合泰MCU.为啥?
   a.仿真器最方便容易使用.
   b.性价比高.
   c.品质不错.
   d.易买到
   e.学习材料多.

使用特权

评论回复
板凳
autopccopy| | 2011-8-2 21:24 | 只看该作者
新手看例程很重要。

有时有空老鸟帮别人看看程序BUG,就当是一个排错GAME。 :)
如没空就鼓励新手一下吧。

我承认当初看极都不懂的地方都是老鸟帮我指出方便理解很多的。。。 :)

使用特权

评论回复
地板
efen| | 2011-8-2 21:46 | 只看该作者
顶一顶

使用特权

评论回复
5
highgear| | 2011-8-2 22:05 | 只看该作者
顶 NE5532!

顶顶二楼hopewise的程序。
同时,很遗憾的告诉二楼,您的程序结构并不怎么好,更重要的是,可读性不是很好。不论汇编还是C/C++,一个良好的程序首先是要有良好的可读性,甚至可以不用注释。

使用特权

评论回复
6
原野之狼| | 2011-8-3 00:35 | 只看该作者
新手发帖是一门学问

使用特权

评论回复
7
永远的不知| | 2011-8-3 00:39 | 只看该作者
1# NE5532

掌握好发帖原则,才容易得到别人的帮助。

使用特权

评论回复
8
kobesff| | 2011-8-3 01:05 | 只看该作者
顶 NE5532!

顶顶二楼hopewise的程序。
同时,很遗憾的告诉二楼,您的程序结构并不怎么好,更重要的是,可读性不是很好。不论汇编还是C/C++,一个良好的程序首先是要有良好的可读性,甚至可以不用注释。 ...
highgear 发表于 2011-8-2 22:05


能否谈谈您觉得好的程序结构?:)   让俺们新手学习下。

使用特权

评论回复
9
123jj| | 2011-8-3 06:03 | 只看该作者
NE5532老师总结的不错,顶~~~

使用特权

评论回复
10
batsong| | 2011-8-3 08:28 | 只看该作者
顶,单纯的控制逻辑程序确实是电子行业最简单的东西

电路才是难啃的骨头啊

使用特权

评论回复
11
hopewise| | 2011-8-3 08:54 | 只看该作者
它的主周期是固定不变的,如5ms.如果想改变周期,则把下面指令中的数字64改为其它数字,比如,32,则主周期变为4ms(125us*32=4000us=4ms).
      main:  
       mov      a,t_125us
       sub       a,64
       snz       c                             ;到了8mS吗   
       jmp       main                        ;没到,则跳到main
   这种结构的好处是增加功能或删除功能非常方便,更容易调试程序.之前我谈过,先把主周期框架建好(先只有key_scan,蜂鸣器管理,这2个子程序),并关闭看门狗,就变成如下:
main:  
       mov      a,t_125us
       sub       a,64
       snz       c                             ;到了8mS吗   
       jmp       main                        ;没到,则跳到main
main1:
      clr      t_125us                        ;到了,则清t_125us变量   
      call        key_scan_man            ;按键扫描管理                              
      call       buz_man                     ;蜂鸣器管理   
       jmp     main
把只有key_scan,蜂鸣器管理子程序copy过来,按一下按键,测试按键接法对否,ok的话,则编其它独立的子程序,如时间管理子程序:
;***************************************
;**********************时间管理*********
time_man:
        inc       time_1sec
        mov     a,time_1sec
        sub     a,125
        snz     c
        ret
        clr      time_1sec              ;1秒时间到,则清time_1sec变量
        sz      baojing_time          ;报警时间为0吗?
        dec    baojing_time          ;不为0,则baojing_time 减一         
       ret
当然,如果还有其它时间变量,就在time_man主程序里加就行了,非常方便.调好了time_man ,则主程序结构就变为了如下:
main:  
       mov      a,t_125us
       sub       a,64
       snz       c                               ;到了8mS吗   
       jmp       main                         ;没到,则跳到main
main1:
      clr        t_125us                      ;到了,则清t_125us变量   
      call        key_scan_man            ;按键扫描管理                              
      call       buz_man                     ;蜂鸣器管理   
      call       time_man                    ;时间管理
      jmp     main
按这种思路,先易后难的顺序,调试完其它子程序.
最后是打开看门狗.
     这种编程结构有很多优点,如时间平均分,像数码管显示之类,不会产生flash现象(就4位数码管而言,主周期为5ms,太多位,就要专用数码管IC,如TM1629A).
     如果先前是数码管显示,现改用段式LCD,则基本上只需改动显示子程序。
    如果想增加温度方面内容,则在主程序里加上ad_man子程序就OK了,基本上不会其它子程序.
    因为我搞软件的时间不是很久,有很多东西还不会,上面是我的个人看法,仅供参考.
   另外,这种编程结构里的子程序之间是靠变量来传递,如按下某个按键,则在key_scan里置相关标志位,则在按键处理子程序里判断有没有这个标志位,有的话,则处理.
   千万别在子程序里有delay现像,如key_scan子程序里.













        clr     time_1sec                         ;1秒时间到,则清time_1sec变量

使用特权

评论回复
12
老鱼探戈| | 2011-8-3 09:54 | 只看该作者
只有自己先思考过,才能问出有价值的问题,
所以请问问题前自己先思考。

使用特权

评论回复
13
SeaSun| | 2011-8-3 10:47 | 只看该作者
只有自己先思考过,才能问出有价值的问题,
所以请问问题前自己先思考。
老鱼探戈 发表于 2011-8-3 09:54


支持!

自己写的程序先在脑子里运行几遍.  运行到死机了再来问问题.

使用特权

评论回复
14
jack_shine| | 2011-8-3 10:57 | 只看该作者
老手都是从新手走过来的:)

使用特权

评论回复
15
cecwxf| | 2011-8-3 11:01 | 只看该作者
受教。。。

使用特权

评论回复
16
ppppp5553| | 2011-8-3 11:21 | 只看该作者

使用特权

评论回复
17
readdai| | 2011-8-3 14:10 | 只看该作者
本帖最后由 readdai 于 2011-8-3 14:11 编辑

11# hopewise

回hopewise:  个人认为,
main:  
       mov      a,t_125us
       sub       a,64
       snz       c                             ;到了8mS吗   
       jmp       main                        ;没到,则跳到main
main1:
      clr      t_125us                        ;到了,则清t_125us变量   
      call        key_scan_man            ;按键扫描管理                              
      call       buz_man                     ;蜂鸣器管理   
       jmp     main

这里clr   t_125us 改为    t_125us  -= 64; 更好…………
(用C代替写了,呵呵)

使用特权

评论回复
18
luhaitao_2008| | 2011-8-3 14:51 | 只看该作者
顶,为了大家学习嘛

使用特权

评论回复
19
peigang| | 2011-8-3 15:57 | 只看该作者
占个座。

使用特权

评论回复
20
里昻_Lyon| | 2011-8-3 16:11 | 只看该作者
么,待续

使用特权

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

本版积分规则

个人签名:††††看NE5532教学视频,炼就工程技术研发功力†††††††††† 《跟我学DC-DC电源管理技术》【从只会写软件成长为软硬兼施】 《印刷电路板设计进阶》【12年一线设计经验大放送】 《印刷电路板设计基础》【新手别怕,老工程师带你入门!】

159

主题

13769

帖子

586

粉丝