搜索
bottom↓
回复: 11

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

[复制链接]

出0入0汤圆

发表于 2009-5-15 12:51:29 | 显示全部楼层 |阅读模式
N年前就是玩51的,对它非常熟悉。这次参赛使用89S52,这是我为学生培训做的准备,提供大家参考。

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


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

二、电路参考设计
(原文件名: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[3] = {62536,56536,63536};
code unsigned int pwm_m2[3] = {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[4];
code unsigned char led_7[13]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40,0x79};
code unsigned char position[4]= {0xfe,0xfd,0xfb,0xf7};

void led_display(void)                                // 4位LED数码管动态扫描函数,5ms执行一次
{
        static unsigned char posit;
        P0 = 0xff;                                                // 关全部显示
        P2 = led_7[dis_buff[posit]];        // 输出一位段码
        P0 = position[posit];                        // 显示其中一位
        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.6  start timer      */

        dis_buff[3] = f_type;
        dis_buff[2] = 10;
        dis_buff[1] = 0;
        dis_buff[0] = 0;

        th01_new = pwm_m1[f_type-1] >> 8;
        tl01_new = pwm_m1[f_type-1];
        th02_new = pwm_m2[f_type-1] >> 8;
        tl02_new = pwm_m2[f_type-1];

        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[f_type-1] >> 8;
                                                tl01_new = pwm_m1[f_type-1];
                                                th02_new = pwm_m2[f_type-1] >> 8;
                                                tl02_new = pwm_m2[f_type-1];
                                                dis_buff[3] = 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[1] = delay_time / 10;
                                dis_buff[0] = delay_time % 10;
                               
                                if (m_type_ok)
                                {
                                        if (++move_time >= 3)
                                        {
                                                move_time = 0;
                                                move_on = ~move_on;
                                        }
                                }
                        }

                        if (delay_time_ok)
                                dis_buff[2] = 11;
                        else
                                dis_buff[2] = 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[2] = 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”表示温度的超过或正常。

其它请大家自己分析吧。

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

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2009-5-15 14:33:00 | 显示全部楼层
谢谢马老师提供的资料。
“或许能让更多的人受益吧”  一定的!

出10入120汤圆

发表于 2009-5-15 16:06:09 | 显示全部楼层
建议把数码管改成共阳极的,标准51端口吸入电流比拉出电流大的多 :-)

出0入0汤圆

 楼主| 发表于 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

出10入120汤圆

发表于 2009-5-15 20:05:52 | 显示全部楼层
呵呵,看不懂马老师的楼上的解释。

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

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

出0入0汤圆

 楼主| 发表于 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

请你提供个参考设计。

出10入120汤圆

发表于 2009-5-17 17:57:10 | 显示全部楼层
1、不省电阻确实是这样的,回帖时没考虑这么多。
2、共阳省电是显而易见的,我没说不代表就没有这个优点了。
3、PNP驱动共阳位电极会有问题?我一直这么用。

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

出0入0汤圆

发表于 2009-7-17 21:33:39 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-8-23 12:16:14 | 显示全部楼层
怎么下不了

出0入0汤圆

发表于 2009-8-29 15:40:31 | 显示全部楼层
请问AT89S52有内部晶振吗?以及它新买时需要进行熔丝位设置吗?

出0入8汤圆

发表于 2009-10-10 20:50:54 | 显示全部楼层
SP = 0x80;        //将堆栈空间定义到RAM后128B的空间,让出前128B给变量
怎么用C还要设置SP吗?

出0入8汤圆

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

本版积分规则

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

GMT+8, 2024-4-26 19:01

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

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