搜索
bottom↓
楼主: tangwei039

从单片机初学者迈向单片机工程师(一份正真的让你成为工程师的贴子)

  [复制链接]

出0入0汤圆

发表于 2010-4-21 22:34:56 | 显示全部楼层
写的很好。。mark

出0入0汤圆

 楼主| 发表于 2010-4-21 22:33:06 | 显示全部楼层
你们顶的多了,我就有心情发贴了。呵呵

出0入0汤圆

 楼主| 发表于 2010-4-21 22:25:49 | 显示全部楼层
我还会继续更新的。搞咱们这行,技巧很重要!!!!

出0入0汤圆

发表于 2010-4-21 21:41:55 | 显示全部楼层
确实写的很用心

出0入0汤圆

发表于 2010-4-21 21:38:18 | 显示全部楼层
回复【楼主位】tangwei039
-----------------------------------------------------------------------
经验之谈,比起那些书本上的东西要实际的多,非常不错!

出0入0汤圆

发表于 2010-4-21 20:28:38 | 显示全部楼层
写的很好!

出0入0汤圆

发表于 2010-4-21 20:26:02 | 显示全部楼层
顶呱呱

好东西可惜不会C
建议楼主写本书吧。那个带箭头的注释是用的什么软件啊?

出0入0汤圆

发表于 2010-4-21 20:17:12 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-21 20:10:43 | 显示全部楼层
真的不错我顶

出0入0汤圆

发表于 2010-4-21 20:00:35 | 显示全部楼层
mark 支持一下

出0入0汤圆

发表于 2010-4-21 19:43:17 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-4-21 19:10:32 | 显示全部楼层
的确不错

出0入0汤圆

发表于 2010-4-21 18:46:16 | 显示全部楼层
顶咯,超好!

出0入0汤圆

发表于 2010-4-21 18:31:22 | 显示全部楼层
当初我要是看过这么好的的帖子的话,就可以少走很多弯路了~。

出0入0汤圆

发表于 2010-4-21 18:27:57 | 显示全部楼层
mark楼主这样以为好心人不多见啊,加油,支持

出75入4汤圆

发表于 2010-4-21 17:08:46 | 显示全部楼层
不错,支持。

出0入0汤圆

发表于 2010-4-21 08:58:07 | 显示全部楼层
从单片机初学者迈向单片机工程师  学习了

出0入0汤圆

 楼主| 发表于 2010-4-21 08:29:20 | 显示全部楼层
“从单片机初学者迈向单片机工程师”之LED主题讨论周
                           第五章--多任务环境下的数码管编程设计


[post]数码管在实际应用中非常广泛,尤其是在某些对成本有限制的场合。编写一个好用的LED程序并不是那么的简单。曾经有人这样说过,如果用数码管和按键,做一个简易的可以调整的时钟出来,那么你的单片机就算入门了60%了。此话我深信不疑。我遇到过很多单片机的爱好者,他们问我说单片机我已经掌握了,该如何进一步的学习下去呢?我并不急于回答他们的问题,而是问他们:会编写数码管的驱动程序了吧?“嗯”。会编写按键程序了吧?“嗯”。好,我给你出一个小题目,你做一下。用按键和数码管以及单片机定时器实现一个简易的可以调整的时钟,要求如下:
8位数码管显示,显示格式如下
时-分-秒
XX-XX-XX
要求:系统有四个按键,功能分别是 调整,加,减,确定。在按下调整键时候,显示时的两位数码管以1 Hz 频率闪烁。如果再次按下调整键,则分开始闪烁,时恢复正常显示,依次循环,直到按下确定键,恢复正常的显示。在数码管闪烁的时候,按下加或者减键可以调整相应的显示内容。按键支持短按,和长按,即短按时,修改的内容每次增加一或者减小一,长按时候以一定速率连续增加或者减少。
结果很多人,很多爱好者一下子都理不清楚思路。其实问题的根源在于没有以工程化的角度去思考程序的编写。很多人在学习数码管编程的时候,都是照着书上或者网上的例子来进行试验。殊不知,这些例子代码仅仅只是具有一个演示性的作用,拿到实际中是很难用的。举一个简单的例子。
下面这段程序是在网上随便搜索到的:
while(1)
{
    for(num=0;num<9;num++)  
    {  
            P0=table[num];  
            P2=code[num] ;  
            delayms(2) ;   
    }
}
看出什么问题来了没有,如果没有看出来请仔细想一下,如果还没有想出来,请回过头去,认真再看一遍“学会释放CPU”这一章的内容。这个程序作为演示程序是没有什么问题的,但是实际应用的时候,数码管显示的内容经常变化,而且还有很多其它任务需要执行,因此这样的程序在实际中是根本就无法用的,更何况,它这里也调用了delayms(2)这个函数来延时2 ms这更是令我们深恶痛绝&#61514;

本章的内容正是探讨如何解决多任务环境下(不带OS)的数码管程序设计的编写问题。理解了其中的思想,无论要求我们显示的形式怎么变化(如数码管闪烁,移位等),我们都可以很方便的解决问题。

数码管的显示分为动态显示和静态显示两种。静态显示是每一位数码管都用一片独立的驱动芯片进行驱动。比较常见的有74LS164,74HC595等。利用这类芯片的好处就是可以级联,留给单片机的接口只需要时钟线,数据线,因此比较节省I/O口。如下图所示:


利用74LS164级联驱动8个单独的数码管
静态显示的优点是程序编写简单。但是由于涉及到的驱动芯片数量比较多,同时考虑到PCB的布线等等因素,在低成本要求的开发环境下,单纯的静态驱动并不合适。这个时候就可以考虑到动态驱动了。
动态驱动的图如下所示(以EE21开发板为例)


由上图可以看出。8个数码管的段码由一个单独的74HC573驱动。同时每一个数码管的公共端连接在另外一个74HC573的输出上。当送出第一位数码管的段码内容时候,同时选通第一位数码管的位选,此时,第一位数码管就显示出相应的内容了。一段时间之后,送出第二位数码管段码的内容,选通第二位数码管的位选,这时显示的内容就变成第二位数码管的内容了……依次循环下去,就可以看到了所有数码管同时显示了。事实上,任意时刻,只有一位数码管是被点亮的。由于人眼的视觉暂留效应以及数码管的余辉效应,当数码管扫描的频率非常快的时候,人眼已经无法分辨出数码管的变化了,看起来就是同时点亮的。我们假设数码管的扫描频率为50 Hz, 则完成一轮扫描的时间就是1 / 50 = 20 ms 。我们的系统共有8位数码管,则每一位数码管在一轮扫描周期中点亮的时间为20 / 8 = 2.5 ms 。
动态扫描对时间要求有一点点严格,否则,就会有明显的闪烁。
假设我们程序 中所有任务如下:

while(1)
{
    LedDisplay() ;    //数码管动态扫描
    ADProcess() ;    //AD采集处理  
    TimerProcess() ;  //时间相关处理  
    DataProcess() ;  //数据处理   
}
LedDisplay() 这个任务的执行时间,如同我们刚才计算的那样,50 Hz频率扫描,则该函数执行的时间为20 ms 。 假设ADProcess()这个任务执行的的时间为2 ms ,TimerProcess()这个函数执行的时间为 1 ms ,DataProcess() 这个函数执行的时间为10 ms 。 那么整个主函数执行一遍的总时间为 20 + 2 + 1 + 10 = 33 ms 。即LedDisplay() 这个函数的扫描频率已经不为50 Hz 了,而是 1 / 33 = 30.3 Hz 。这个频率数码管已经可以感觉到闪烁了,因此不符合我们的要求。为什么会出现这种情况呢? 我们刚才计算的50 Hz 是系统只有LedDisplay()这一个任务的时候得出来的结果。当系统添加了其它任务后,当然系统循环执行一次的总时间就增加了。如何解决这种现象了,还是离不开我们第二章所讲的那个思想。
系统产生一个2.5 ms 的时标消息。LedDisplay() , 每次接收到这个消息的时候, 扫描一位数码管。这样8个时标消息过后,所有的数码管就都被扫描一遍了。可能有朋友会有这样的疑问:ADProcess() 以及 DataProcess() 等函数执行的时间还是需要十几ms 啊,在这十几ms 的时间里,已经产生好几个2.5 ms的时标消息了,这样岂不是漏掉了扫描,显示起来还是会闪烁。能够想到这一点,很不错,这也就是为什么我们要学会释放CPU的原因。对于ADProcess(),TimerProcess(),DataProcess(),等任务我们依旧要采取此方法对CPU进行释放,使其执行的时间尽可能短暂,关于如何做到这一点,在以后的讲解如何设计多任务程序设计的时候会讲解到。
下面我们基于此思路开始编写具体的程序。
首先编写Timer.c文件。该文件中主要为系统提供时间相关的服务。必要的头文件包含。
#include <reg52.h>
#include "MacroAndConst.h"
为了方便计算,我们取数码管扫描一位的时间为2 ms。设置定时器0为2 ms中断一次。
同时声明一个位变量,作为2 ms时标消息的标志
bit g_bSystemTime2Ms = 0 ;              // 2msLED动态扫描时标消息  
初始化定时器0
void Timer0Init(void)
{
    TMOD &= 0xf0 ;  
    TMOD |= 0x01 ;      //定时器0工作方式1
    TH0  =    0xf8 ;      //定时器初始值
    TL0  =  0xcc ;  
    TR0  = 1 ;  
    ET0  = 1 ;  
}
在定时器0中断处理程序中,设置时标消息。
void Time0Isr(void) interrupt 1
{
    TH0  =    0xf8 ;            //定时器重新赋初值
    TL0  =  0xcc ;
    g_bSystemTime2Ms = 1 ;    //2MS时标标志位置位
}
然后我们开始编写数码管的动态扫描函数。
新建一个C源文件,并包含相应的头文件。
#include <reg52.h>
#include "MacroAndConst.h"
#include "Timer.h"
先开辟一个数码管显示的缓冲区。动态扫描函数负责从这个缓冲区中取出数据,并扫描显示。而其它函数则可以修改该缓冲区,从而改变显示的内容。
uint8 g_u8LedDisplayBuffer[8] = {0} ; //显示缓冲区
然后定义共阳数码管的段码表以及相应的硬件端口连接。
code uint8 g_u8LedDisplayCode[]=
{
    0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
    0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,
    0xbf, //'-'号代码
} ;

sbit io_led_seg_cs = P1^4 ;
sbit io_led_bit_cs = P1^5 ;

#define LED_PORT P0

再分别编写送数码管段码函数,以及位选通函数。
static void SendLedSegData(uint8 dat)
{
    LED_PORT      = dat ;   
    io_led_seg_cs = 1 ;        //开段码锁存,送段码数据
    io_led_seg_cs = 0 ;
}

static void SendLedBitData(uint8 dat)
{
    uint8 temp ;
    temp = (0x01 << dat ) ;  //根据要选通的位计算出位码
    LED_PORT      = temp ;
    io_led_bit_cs = 1 ;          //开位码锁存,送位码数据   
    io_led_bit_cs = 0 ;        
}

下面的核心就是如何编写动态扫描函数了。
如下所示:


void LedDisplay(uint8 * pBuffer)
{
    static uint8 s_LedDisPos = 0 ;
    if(g_bSystemTime2Ms)
    {
        g_bSystemTime2Ms = 0 ;

        SendLedBitData(8) ;        //消隐,只需要设置位选不为0~7即可

        if(pBuffer[s_LedDisPos] == '-')      //显示'-'号
        {
            SendLedSegData(g_u8LedDisplayCode[16]) ;            
        }
        else   
        {
            SendLedSegData(g_u8LedDisplayCode[pBuffer[s_LedDisPos]]) ;
        }

        SendLedBitData(s_LedDisPos);

        if(++s_LedDisPos > 7)
        {
            s_LedDisPos = 0 ;   
        }   
    }        
}

函数内部定义一个静态的变量s_LedDisPos,用来表示扫描数码管的位置。每当我们执行该函数一次的时候,s_LedDisPos的值会自加1,表示下次扫描下一个数码管。然后判断g_bSystemTime2Ms时标消息是否到了。如果到了,就开始执行相关扫描,否则就直接跳出函数。SendLedBitData(8) ;的作用是消隐。因为我们的系统的段选和位选是共用P0口的。在送段码之前,必须先关掉位选,否则,因为上次位选是选通的,在送段码的时候会造成相应数码管的点亮,尽管这个时间很短暂。但是因为我们的数码管是不断扫描的,所以看起来还是会有些微微亮。为了消除这种影响,就有必要再送段码数据之前关掉位选。
if(pBuffer[s_LedDisPos] == '-')      //显示'-'号这行语句是为了显示’-’符号特意加上去的,大家可以看到在定义数码管的段码表的时候,我多加了一个字节的代码0xbf:
code uint8 g_u8LedDisplayCode[]=
{
    0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
    0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,
    0xbf, //'-'号代码
} ;
通过SendLedSegData(g_u8LedDisplayCode[pBuffer[s_LedDisPos]]) ;送出相应的段码数据后,然后通过SendLedBitData(s_LedDisPos);打开相应的位选。这样对应的数码管就被点亮了。
if(++s_LedDisPos > 7)
{
    s_LedDisPos = 0 ;   
}
然后s_LedDisPos自加1,以便下次执行本函数时,扫描下一个数码管。因为我们的系统共有8个数码管,所以当s_LedDisPos > 7后,要对其进行清0 。否则,没有任何一个数码管被选中。这也是为什么我们可以用
    SendLedBitData(8) ;        //消隐,只需要设置位选不为0~7即可
对数码管进行消隐操作的原因。
   
下面我们来编写相应的主函数,并实现数码管上面类似时钟的效果,如显示10-20-30
即10点20分30秒。
Main.c
#include <reg52.h>
#include "MacroAndConst.h"
#include "Timer.h"
#include "Led7Seg.h"

sbit io_led = P1^6 ;


void main(void)
{
        io_led = 0 ;      //发光二极管与数码管共用P0口,这里禁止掉发光二极管的锁存输出
        Timer0Init() ;
        g_u8LedDisplayBuffer[0] = 1 ;
        g_u8LedDisplayBuffer[1] = 0 ;
        g_u8LedDisplayBuffer[2] = '-' ;
        g_u8LedDisplayBuffer[3] = 2 ;
        g_u8LedDisplayBuffer[4] = 0 ;
        g_u8LedDisplayBuffer[5] = '-' ;
        g_u8LedDisplayBuffer[6] = 3 ;
        g_u8LedDisplayBuffer[7] = 0 ;
        EA = 1 ;
        while(1)
        {
            LedDisplay(g_u8LedDisplayBuffer) ;
        }
}
将整个工程进行编译,看看效果如何&#61514;





动起来

既然我们想要模拟一个时钟,那么时钟肯定是要走动的,不然还称为什么时钟撒。下面我们在前面的基础之上,添加一点相应的代码,让我们这个时钟走动起来。
我们知道,之前我们以及设置了一个扫描数码管用到的2 ms时标。 如果我们再对这个时标进行计数,当计数值达到500,即500 * 2 = 1000 ms 时候,即表示已经逝去了1 S的时间。我们再根据这个1 S的时间更新显示缓冲区即可。听起来很简单,让我们实现它吧。
首先在Timer.c中声明如下两个变量:
bit g_bTime1S = 0 ;                      //时钟1S时标消息
static uint16 s_u16ClockTickCount = 0 ;  //对2 ms 时标进行计数

再在定时器中断函数中添加如下代码:
    if(++s_u16ClockTickCount == 500)
    {
        s_u16ClockTickCount = 0 ;
        g_bTime1S = 1 ;        
    }
从上面可以看出,s_u16ClockTickCount计数值达到500的时候,g_bTime1S时标消息产生。然后我们根据这个时标消息刷新数码管显示缓冲区:
void RunClock(void)
{
    if(g_bTime1S )
    {
        g_bTime1S = 0 ;
        if(++g_u8LedDisplayBuffer[7] == 10)
        {
            g_u8LedDisplayBuffer[7] = 0 ;
            if(++g_u8LedDisplayBuffer[6] == 6)
            {
                g_u8LedDisplayBuffer[6] = 0 ;
                if(++g_u8LedDisplayBuffer[4] == 10)
                {
                    g_u8LedDisplayBuffer[4]    = 0 ;
                    if(++g_u8LedDisplayBuffer[3] == 6)
                    {
                        g_u8LedDisplayBuffer[3] = 0 ;
                        if(    g_u8LedDisplayBuffer[0]<2)
                        {
                            if(++g_u8LedDisplayBuffer[1]==10)
                            {
                                g_u8LedDisplayBuffer[1] = 0 ;
                                g_u8LedDisplayBuffer[0]++;
                            }  
                        }
                        else
                        {
                            if(++g_u8LedDisplayBuffer[1]==4)
                            {
                                g_u8LedDisplayBuffer[1] = 0 ;
                                g_u8LedDisplayBuffer[0] = 0 ;
                            }  
                        }   
                    }
                }
            }

        }
    }        
}
这个函数的作用就是对每个数码管缓冲位的值进行判断,判断的标准就是我们熟知的24小时制。如秒的个位到了10 就清0,同时秒的十位加1….诸如此类,我就不一一详述了。
同时,我们再编写一个时钟初始值设置函数,这样,可以很方便的在主程序开始的时候修改时钟初始值。
void SetClock(uint8 nHour, uint8 nMinute, uint8 nSecond)
{
    g_u8LedDisplayBuffer[0] = nHour / 10 ;
    g_u8LedDisplayBuffer[1] = nHour % 10 ;
    g_u8LedDisplayBuffer[2] = '-' ;
    g_u8LedDisplayBuffer[3] = nMinute / 10 ;
    g_u8LedDisplayBuffer[4] = nMinute % 10 ;
    g_u8LedDisplayBuffer[5] = '-' ;
    g_u8LedDisplayBuffer[6] = nSecond / 10 ;
    g_u8LedDisplayBuffer[7] = nSecond % 10 ;            
}
然后修改下我们的主函数如下:
void main(void)
{
    io_led = 0 ;      //发光二极管与数码管共用P0口,这里禁止掉发光二极管的锁存输出
    Timer0Init() ;
    SetClock(10,20,30) ;  //设置初始时间为10点20分30秒
    EA = 1 ;
    while(1)
    {
        LedDisplay(g_u8LedDisplayBuffer) ;
        RunClock();
    }
}
编译好之后,下载到我们的实验板上,怎么样,一个简单的时钟就这样诞生了。


至此,本章所诉就告一段落了。至于如何完成数码管的闪烁显示,就像本章开头所说的那个数码管时钟的功能,就作为一个思考的问题留给大家思考吧。
同时整个LED篇就到此结束了,在以后的文章中,我们将开始学习如何编写实用的按键扫描程序。

出0入0汤圆

发表于 2010-4-20 22:59:04 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-20 22:50:55 | 显示全部楼层
mark

出0入264汤圆

发表于 2010-4-20 22:29:37 | 显示全部楼层
回复【78楼】zhfeng
-----------------------------------------------------------------------

你的理解是错的,请再仔细看看程序。

出0入0汤圆

发表于 2010-4-20 22:05:27 | 显示全部楼层
虽然只看了几行但是一定要顶

出0入0汤圆

发表于 2010-4-20 22:05:26 | 显示全部楼层
这段似乎也有问题吧
g_bSystemTime1Ms初值为0,永远无法进行加1动作
void LedStateChange(void)
{
    if(g_bSystemTime1Ms)            //系统1MS时标到
  {
        g_bSystemTime1Ms = 0 ;
        g_u16LedTimeCount++ ;      //LED计数器加一
    if(g_u16LedTimeCount >= 500)  //计数达到500,即500MS到了,改变LED的状态。
    {
            g_u16LedTimeCount = 0 ;
            g_u8LedState  = ! g_u8LedState ;
      }
    }
}
是否应改为:
void LedStateChange(void)
{
    if(!g_bSystemTime1Ms)            //系统1MS时标到
  {
        g_bSystemTime1Ms = 0 ;
        g_u16LedTimeCount++ ;      //LED计数器加一
    if(g_u16LedTimeCount >= 500)  //计数达到500,即500MS到了,改变LED的状态。
    {
            g_u16LedTimeCount = 0 ;
            g_u8LedState  = ! g_u8LedState ;
      }
   }
  }

出0入0汤圆

发表于 2010-4-20 19:57:14 | 显示全部楼层
楼主流弊

出0入0汤圆

发表于 2010-4-20 19:39:20 | 显示全部楼层
有其他的章节吗

出0入0汤圆

发表于 2010-4-20 17:35:22 | 显示全部楼层
看了一半了,挺好,mark一下

出0入0汤圆

发表于 2010-4-20 16:53:02 | 显示全部楼层
以后每天来看2小时,哈哈

出0入0汤圆

发表于 2010-4-20 16:50:10 | 显示全部楼层
顶,谢谢分享

出0入0汤圆

发表于 2010-4-20 16:28:20 | 显示全部楼层
写的很好!!!

出0入0汤圆

发表于 2010-4-20 16:10:03 | 显示全部楼层
收藏,有空要看看。

出0入0汤圆

发表于 2010-4-20 15:35:15 | 显示全部楼层
谢谢啦。收藏!

出0入0汤圆

发表于 2010-4-20 15:33:14 | 显示全部楼层
多谢楼主分享

出0入0汤圆

发表于 2010-4-20 15:12:47 | 显示全部楼层
支持楼主,感谢楼主!继续努力!

出0入0汤圆

发表于 2010-4-20 14:42:27 | 显示全部楼层
谢谢

出0入0汤圆

发表于 2010-4-20 14:41:02 | 显示全部楼层
回复【57楼】tangwei039
-----------------------------------------------------------------------
谢谢,我已改正过来!!!有错误我会及时更正。
-----------------------------------------------------------------------

呵呵,才发现,这个原来有两处~ 还有一处~

附完整程序代码(基于电子工程师之家的单片机开发板)
#include<reg52.h>
sbit LED_SEG  = P1^4;  //数码管段选
sbit LED_DIG  = P1^5;  //数码管位选
sbit LED_CS11 = P1^6;  //led控制位
sbit ir=P1^7;
#define LED P0            //定义LED接口
bit  g_bSystemTime1Ms = 0 ;              // 1MS系统时标
unsigned int  g_u16LedTimeCount = 0 ; //LED计数器
unsigned char g_u8LedState = 0 ;      //LED状态标志, 0表示亮,1表示熄灭

#define LED_ON()      LED = 0x00 ;  //所有LED亮
-----------------------------------------------------------------------
#define LED_OFF()    LED = 0xff ;  //所有LED熄灭
-----------------------------------------------------------------------
麻烦LZ再改一下~
顺便帮顶!

出0入0汤圆

发表于 2010-4-20 14:32:14 | 显示全部楼层
对新手入门非常的好, 顶~

出0入0汤圆

发表于 2010-4-20 14:30:52 | 显示全部楼层
又更新了!再顶~

出0入0汤圆

发表于 2010-4-20 13:37:12 | 显示全部楼层
此文不顶,就太对不起自己了!

出0入0汤圆

发表于 2010-4-20 13:32:19 | 显示全部楼层
这是后面几章的ourdev_547662.doc(文件大小:1.69M) (原文件名:单片机.doc)

出0入0汤圆

发表于 2010-4-20 13:29:15 | 显示全部楼层
mark
写得非常好,期待续集.

出0入0汤圆

发表于 2010-4-20 13:24:31 | 显示全部楼层

出0入131汤圆

发表于 2010-4-20 13:03:37 | 显示全部楼层
顶一个

出0入0汤圆

 楼主| 发表于 2010-4-20 13:00:16 | 显示全部楼层
回复【44楼】arbol
-----------------------------------------------------------------------

谢谢,我已改正过来!!!有错误我会及时更正。

出0入0汤圆

发表于 2010-4-20 12:59:55 | 显示全部楼层
期待合版!支持楼主~

出0入0汤圆

发表于 2010-4-20 12:31:30 | 显示全部楼层
多谢

出0入0汤圆

发表于 2010-4-20 12:23:24 | 显示全部楼层
下次继续来学习.

出0入0汤圆

发表于 2010-4-20 11:47:52 | 显示全部楼层
学习了,谢谢啦!

出0入0汤圆

发表于 2010-4-20 11:39:48 | 显示全部楼层
比起那些教科书来得更实际,通俗易懂,希望能完成全部的内容;尤其是编程方法和技巧方面的知识,让更多的初学者不要再去走弯路了。

出0入0汤圆

发表于 2010-4-20 11:38:14 | 显示全部楼层
mark!

出0入0汤圆

发表于 2010-4-20 11:29:35 | 显示全部楼层
不如推荐一本经典书:
嵌入式微计算机系统实时接口_技术

相信比这些零散的要好太多。

出0入0汤圆

发表于 2010-4-20 11:28:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-20 11:24:11 | 显示全部楼层
支持

出0入0汤圆

发表于 2010-4-20 10:43:45 | 显示全部楼层
支持楼主的分享精神

出0入0汤圆

发表于 2010-4-20 10:19:24 | 显示全部楼层
楼主我是个初学者,想跟你学习,多苦都行,愿意带我请加我QQ:260631865或者我的邮箱xx904fj627@163.com

出0入0汤圆

发表于 2010-4-20 09:22:55 | 显示全部楼层

出0入0汤圆

发表于 2010-4-20 09:14:54 | 显示全部楼层
再支持下!

另外,发现一个笔误:
#define LED_ON()      LED = 0x00 ;  //所有LED亮
#define LED_OFF()    LED = 0xff ;  //所有LED熄灭

这两句,注释双斜杠前不用打分号的。

出0入0汤圆

发表于 2010-4-20 09:13:58 | 显示全部楼层
不错

出0入0汤圆

发表于 2010-4-20 09:06:03 | 显示全部楼层
谢谢
学习

出0入0汤圆

发表于 2010-4-20 09:05:31 | 显示全部楼层
支持楼主.

出0入0汤圆

发表于 2010-4-20 08:57:41 | 显示全部楼层
支持下

出0入0汤圆

发表于 2010-4-20 08:53:47 | 显示全部楼层
支持一下

出0入0汤圆

发表于 2010-4-20 08:51:54 | 显示全部楼层
ddd

出0入0汤圆

发表于 2010-4-20 08:41:09 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-20 08:34:06 | 显示全部楼层
mrak

出0入0汤圆

发表于 2010-4-20 08:16:52 | 显示全部楼层
学习

出0入0汤圆

发表于 2010-4-20 08:08:47 | 显示全部楼层
期待完整版,谢谢!

出0入0汤圆

发表于 2010-4-20 06:59:04 | 显示全部楼层
希望楼主能转成PDF文件发上来

出0入0汤圆

发表于 2010-4-20 06:47:00 | 显示全部楼层
感谢分享

出0入0汤圆

发表于 2010-4-20 06:46:45 | 显示全部楼层
学习,学习啊

出0入0汤圆

发表于 2010-4-20 00:48:07 | 显示全部楼层
收藏

出0入0汤圆

发表于 2010-4-20 00:16:52 | 显示全部楼层
写得不错!!!

出0入0汤圆

发表于 2010-4-20 00:12:21 | 显示全部楼层
地道,收藏,谢谢楼主哥。

出0入0汤圆

发表于 2010-4-19 23:45:34 | 显示全部楼层
写的不错

出0入4汤圆

发表于 2010-4-19 23:35:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-19 23:26:36 | 显示全部楼层
MARK

出0入8汤圆

发表于 2010-4-19 22:57:40 | 显示全部楼层
支持

出0入0汤圆

发表于 2010-4-19 22:53:03 | 显示全部楼层
不错 顶上

出0入0汤圆

发表于 2010-4-19 22:52:06 | 显示全部楼层
写的不错

出0入0汤圆

发表于 2010-4-19 22:48:36 | 显示全部楼层
当然期待了,赶紧上个全集吧

出0入0汤圆

发表于 2010-4-19 22:38:11 | 显示全部楼层
支持一个

出0入0汤圆

发表于 2010-4-19 22:33:14 | 显示全部楼层
期待后续

出0入0汤圆

发表于 2010-4-19 22:30:00 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-19 22:07:26 | 显示全部楼层
真的希望那些,处于初学,而感觉遇到瓶颈的同学,都看看,收获很大的

出0入0汤圆

发表于 2010-4-19 22:06:59 | 显示全部楼层
记号一下

出0入0汤圆

发表于 2010-4-19 22:06:35 | 显示全部楼层
好长……标记一下漫漫看~

出0入0汤圆

 楼主| 发表于 2010-4-19 22:04:01 | 显示全部楼层
今天就到这,明天再更新。我这好东西还不少呢。呵呵

出0入0汤圆

发表于 2010-4-19 22:03:27 | 显示全部楼层
回复【12楼】tangwei039
-----------------------------------------------------------------------

顶起,这一系列文章,我个人真的是看过很多遍了,感觉真的是受益匪浅!

望楼主,继续发布,让更多的人学会实实在在的编程思想

出0入0汤圆

 楼主| 发表于 2010-4-19 22:01:21 | 显示全部楼层
这个没问题。我明天给咱们做成。word或pdf.我只是想让大家都一起学习!!

出0入0汤圆

发表于 2010-4-19 21:58:50 | 显示全部楼层
希望楼主能转成PDF文件发上来,一下就能下载下来啦,多谢!

出0入0汤圆

发表于 2010-4-19 21:54:51 | 显示全部楼层
顶啊

出0入0汤圆

发表于 2010-4-19 21:49:38 | 显示全部楼层
//持LZ,卖春更新!
**************
汗一个!
“支持 LZ, 支持更新!”发出去怎么变成这样子了?!
注释掉~

出0入0汤圆

发表于 2010-4-19 21:38:45 | 显示全部楼层
最重要的是坚持做下去

出0入0汤圆

 楼主| 发表于 2010-4-19 21:38:08 | 显示全部楼层
只要看完我这个贴子,相信你也就成为高手了。相信我。高手也就这样。!!!呵呵

出0入0汤圆

发表于 2010-4-19 21:31:16 | 显示全部楼层
似乎没有写完,希望楼主坚持下去,支持一个!

出0入0汤圆

发表于 2010-4-19 21:29:56 | 显示全部楼层
支持LZ发,最好还有个合集。

出0入0汤圆

 楼主| 发表于 2010-4-19 21:27:57 | 显示全部楼层
看大家需要了。不然就不费这么大的力气了。呵呵!!!

出0入0汤圆

 楼主| 发表于 2010-4-19 21:26:51 | 显示全部楼层
如果大家需要,我把后面也传上来!

KEY篇第一章----按键程序编写的基础

KEY篇第二章----基于状态转移的独立按键程序设计

LED篇第三章----模块化编程初识

LED篇第四章----渐明渐暗的灯

LED篇第五章----多任务环境下的数码管编程设计

出0入0汤圆

发表于 2010-4-19 21:21:54 | 显示全部楼层
通俗易懂
谢谢

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-5-19 07:20

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

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