machao 发表于 2009-5-15 12:51:29

"天华杯"单片机设计与开发大赛题型示例设计参考方案----培训资料

N年前就是玩51的,对它非常熟悉。这次参赛使用89S52,这是我为学生培训做的准备,提供大家参考。

尽管我说“天华杯”有点丢人,是指它所体现的水平,但能推动和提供学生机会去认真学习也还是有积极的一面。作为教师还是要认真做好培训工作,把自己准备的资料放上来,或许能让更多的人受益吧。


一、示例题:点击此处下载 ourdev_445036.pdf(文件大小:502K) (原文件名:单片机设计与开发大赛题型示例.pdf)

二、电路参考设计http://cache.amobbs.com/bbs_upload782111/files_15/ourdev_445037.jpg
(原文件名:sch.jpg)

三、参考代码

//==================================================================

#include <Reg52.h>
#include <intrins.h>

//********************************************
//        I/O port design
//********************************************
//输入定义

#define Key_null                0xff
#define        Key_f                0xfe
#define        Key_m                0xfd
#define        Key_t                0xfb


//控制输出/输入
sbit m_out                =P3^6;
sbit pwm_out        =P3^7;
sbit err_in        =P1^3;


//函数声明
void led_display(void);

//======
//PWM 电机输出控制 (timer0 中断)
code unsigned int pwm_m1 = {62536,56536,63536};
code unsigned int pwm_m2 = {56536,62536,55536};
unsigned char th01_new,tl01_new;
unsigned char th02_new,tl02_new;
bit pwm_state;
void timer1(void) interrupt 1                        //定时0中断
{
        if(pwm_state)
        {
                TL0 = tl01_new;       
                TH0 = th01_new;         
                pwm_out = 0;
        }
        else
        {
                TL0 = tl02_new;       
                TH0 = th02_new;         
      pwm_out = 1;
        }
        pwm_state = ~pwm_state;
}

bit key_time_ok,time_1s_ok;
unsigned char key_time,time_1s;
void timer0(void) interrupt 3        //定时1中断
{
        TL1 = 0x78;                                        // THTL=0xec78 = 65536 - 5000(5ms)
        TH1 = 0xec;         
        led_display();                                // LED动态扫描
        if (++key_time >= 4)
        {
                key_time = 0;
                key_time_ok = 1;                //10ms到
                if(++time_1s >= 50)
                {
                        time_1s = 0;
                        time_1s_ok = 1;                //1秒到
                }
        }
}

//======
//LED数码管扫描显示驱动
unsigned char dis_buff;
code unsigned char led_7= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40,0x79};
code unsigned char position= {0xfe,0xfd,0xfb,0xf7};

void led_display(void)                                // 4位LED数码管动态扫描函数,5ms执行一次
{
        static unsigned char posit;
        P0 = 0xff;                                                // 关全部显示
        P2 = led_7];        // 输出一位段码
        P0 = position;                        // 显示其中一位
        if(++posit >= 4) posit = 0;
}

//=======================
//按键扫描底层接口
unsigned char read_key(void)
{
        static unsigned char key_press_old = Key_null,key_state = 0 ;
        unsigned char key_value= Key_null,key_press;

        key_press = P1;
        switch (key_state)
        {
                case 0:
                        if(key_press != Key_null) key_state = 1;
                        break;
                case 1:
                        if (key_press != key_press_old)
                        {
                                key_state = 0;
                        }       
                        else
                        {
                                if (key_press == Key_f) key_value = Key_f;
                                if (key_press == Key_m) key_value = Key_m;
                                if (key_press == Key_t) key_value = Key_t;
                                key_state = 2;
                        }
                        break;
                case 2:
                        if (key_press == Key_null) key_state = 0;
                        break;
        }
        key_press_old = key_press;
        return key_value;
}

//=============================================================================
//主程序
//=============================================================================
void main(void)
{
        bit delay_time_ok = 0,m_type_ok = 0, move_on = 0;
        unsigned char f_type = 1,time_type = 0,delay_time = 0,move_time = 0,key;
       
        EA = 0;                                //关闭全局中断
        SP = 0x80;      //将堆栈空间定义到RAM后128B的空间,让出前128B给变量

        P2 = 0x00;
        P3 = 0x00;
        P0 = 0xff;
        P1 = 0xff;

        //Configure Timer0,Mode=1,Interrupt=ENABLED,Clock Source=INTERNAL,Enable Gating Control=DISABLED
        TMOD &= 0XF0;                /* clear Timer 0   */
        TMOD |= 0X01;
        TL0 = 0x78;               
        TH0 = 0xec;         
    ET0 = 1;                        /* IE.1*/
    TR0 = 1;            /* TCON.4 start timer*/

        //Configure Timer1,Mode=1,Interrupt=ENABLED,Clock Source=INTERNAL,Enable Gating Control=DISABLED
        TMOD &= 0X0F;                /* clear Timer 1 control    */
        TMOD |= 0X10;
        TL1 = 0X78;                        // THTL=0xec78 = 65536 - 5000(5ms)                       
        TH1 = 0Xec;                       
        ET1 = 1;                        /* ET0 is IE.3         */
        TR1 = 1;                        /* TCON.6start timer      */

        dis_buff = f_type;
        dis_buff = 10;
        dis_buff = 0;
        dis_buff = 0;

        th01_new = pwm_m1 >> 8;
        tl01_new = pwm_m1;
        th02_new = pwm_m2 >> 8;
        tl02_new = pwm_m2;

        EA = 1;                                //打开全局中断
       
        while(1)
        {
                if (err_in)
                {
                        if(key_time_ok)
                        {
                                key_time_ok = 0;
                                key = read_key();
                                if (key != Key_null)
                                {

                                        if (key == Key_f)
                                        {
                                                if (++f_type >= 4) f_type = 1;
                                                th01_new = pwm_m1 >> 8;
                                                tl01_new = pwm_m1;
                                                th02_new = pwm_m2 >> 8;
                                                tl02_new = pwm_m2;
                                                dis_buff = f_type;
                                        }
                                        else if(key == Key_t)
                                        {
                                                if (++time_type >= 7)
                                                {
                                                        time_type = 0;
                                                        delay_time_ok = 0;
                                                        delay_time = 0;
                                                }
                                                else
                                                {
                                                        delay_time_ok = 1;
                                                        delay_time = time_type * 10;
                                                }
                                        }
                                        else if(key == Key_m)
                                        {
                                                m_type_ok = ~m_type_ok;
                                        }
                                }
                        }

                        if (time_1s_ok)
                        {
                                time_1s_ok = 0;
                                if(delay_time) delay_time-- ;
                                dis_buff = delay_time / 10;
                                dis_buff = delay_time % 10;
                               
                                if (m_type_ok)
                                {
                                        if (++move_time >= 3)
                                        {
                                                move_time = 0;
                                                move_on = ~move_on;
                                        }
                                }
                        }

                        if (delay_time_ok)
                                dis_buff = 11;
                        else
                                dis_buff = 10;

                        if (delay_time_ok && (delay_time == 0))
                        {
                                ET0 = 0;                               
                                pwm_out = 1;
                        }
                        else
                        {
                                ET0 = 1;
                        }

                        if (m_type_ok)        m_out = move_on;
                }
                else
                {
                        ET0 = 0;
                        pwm_out = 1;
                        dis_buff = 12;
                }
        }
}

=============================================================
四、代码简单说明与模拟调试过程
1。本代码是在我设计的“AVR-51多功能实验开发板”上调试实现的。编程工具就是并口的ISP,开发平台KEIL,编程软件SLISP。根据板上资源代码的显示部分与上面所贴图有点改动。

2。代码中简单的把P2口作为LED的8个段的输出口,PO口作为位控,采用共阴LED数码管。由于89S52的I/O口驱动比较小,所以亮度不太高。可以通过调节限流电阻提高亮度。

3。实际板上有一片1413驱动,可以作为LED数码管显示的位驱动,这样亮度就没有问题了。

4。代码中尽量保证RAM的前128B(直接寻址)全部给用户变量使用,把堆栈放在后128B的空间,固定数据的数组定义在FLASH空间(见代码中有CODE声明的数组变量定义)

5。外围的马达的驱动电路、马达、继电器、温度输入检测(此部分电路请自己补充画完)没有接,通过以下的模拟方式验证和调试

6。PWM的输出直接控制板上的一个LED,不同占空比时,LED的亮度变化代表了转速的不同。实际如果有马达的话,只要根据实际情况,改变PWM的频率就可以了。

7。摆动马达控制也可以使用2个LED显示控制I/O的输出情况

8。采用一个I/O输入“1”或“0”表示温度的超过或正常。

其它请大家自己分析吧。

mtxmxt 发表于 2009-5-15 14:33:00

谢谢马老师提供的资料。
“或许能让更多的人受益吧”一定的!

makesoft 发表于 2009-5-15 16:06:09

建议把数码管改成共阳极的,标准51端口吸入电流比拉出电流大的多 :-)

machao 发表于 2009-5-15 17:31:11

lz位LED数码管的电路是标准的,P0口并不提供数码管电流,从上拉电阻获得。P2口也不需要大电流。

2楼的建议没有价值,如果使用共阳的,恐怕设计出的电路还有毛病。见:“天华杯”比赛参考资料----(参考电路点评) http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=3341861&bbs_page_no=1&bbs_id=1003

makesoft 发表于 2009-5-15 20:05:52

呵呵,看不懂马老师的楼上的解释。

1、这个电路在数码管全暗的情况下,上拉电阻的电流完全有P0口吸收。
2、使用共阳电路可以省去PO的上拉电阻,并且看不出这么设计会有什么问题发生。

当然你要是说电路是固定不可改变的,就没有什么好说的了

machao 发表于 2009-5-16 23:49:30

先限定条件:
1。使用89S52的P0口,该口吸入电流最大
2。把数码管改成共阳极

是完全可以,但是要注意:

1。可以省掉P0的上拉8个电阻,但还是需要加8个限流电阻,因此一个电阻也省不掉。
2。此时点亮LED的电流由P0口吸收,与“共阴数码管全暗的情况下,上拉电阻的电流完全有P0口吸收”是相同的, 优点是省电(这个你没有说):不点亮没有电流流过。
3。要注意共阳级驱动的设计,要使用PNP三极管。而且很多人设计出的电路还有毛病。具体例子见帖子:“天华杯”比赛参考资料----(参考电路点评) http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=3341861&bbs_page_no=1&bbs_id=1003

请你提供个参考设计。

makesoft 发表于 2009-5-17 17:57:10

1、不省电阻确实是这样的,回帖时没考虑这么多。
2、共阳省电是显而易见的,我没说不代表就没有这个优点了。
3、PNP驱动共阳位电极会有问题?我一直这么用。

电路很简单,e接VCC,b串一个电阻后连接单片机的IO,当然c就直接连接数码管的位电极了。
其实回帖也不说明什么,仅仅是一点点的疑虑而已。
最近论坛明显有硝烟气氛,上升为口角架就没有意思了,相信我们不会,都没有什么主观的恶意。

stefgq 发表于 2009-7-17 21:33:39

mark

njustxiaosi 发表于 2009-8-23 12:16:14

怎么下不了

ilz_2006 发表于 2009-8-29 15:40:31

请问AT89S52有内部晶振吗?以及它新买时需要进行熔丝位设置吗?

skype 发表于 2009-10-10 20:50:54

SP = 0x80;      //将堆栈空间定义到RAM后128B的空间,让出前128B给变量
怎么用C还要设置SP吗?

skype 发表于 2009-10-10 20:54:10

51单片机复位I\O是都是高电平,在设计电路时要低电平有效才合理呀?
页: [1]
查看完整版本: "天华杯"单片机设计与开发大赛题型示例设计参考方案----培训资料