"天华杯"单片机设计与开发大赛题型示例设计参考方案----培训资料
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”表示温度的超过或正常。
其它请大家自己分析吧。 谢谢马老师提供的资料。
“或许能让更多的人受益吧”一定的! 建议把数码管改成共阳极的,标准51端口吸入电流比拉出电流大的多 :-) lz位LED数码管的电路是标准的,P0口并不提供数码管电流,从上拉电阻获得。P2口也不需要大电流。
2楼的建议没有价值,如果使用共阳的,恐怕设计出的电路还有毛病。见:“天华杯”比赛参考资料----(参考电路点评) http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=3341861&bbs_page_no=1&bbs_id=1003 呵呵,看不懂马老师的楼上的解释。
1、这个电路在数码管全暗的情况下,上拉电阻的电流完全有P0口吸收。
2、使用共阳电路可以省去PO的上拉电阻,并且看不出这么设计会有什么问题发生。
当然你要是说电路是固定不可改变的,就没有什么好说的了 先限定条件:
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
请你提供个参考设计。 1、不省电阻确实是这样的,回帖时没考虑这么多。
2、共阳省电是显而易见的,我没说不代表就没有这个优点了。
3、PNP驱动共阳位电极会有问题?我一直这么用。
电路很简单,e接VCC,b串一个电阻后连接单片机的IO,当然c就直接连接数码管的位电极了。
其实回帖也不说明什么,仅仅是一点点的疑虑而已。
最近论坛明显有硝烟气氛,上升为口角架就没有意思了,相信我们不会,都没有什么主观的恶意。 mark 怎么下不了 请问AT89S52有内部晶振吗?以及它新买时需要进行熔丝位设置吗? SP = 0x80; //将堆栈空间定义到RAM后128B的空间,让出前128B给变量
怎么用C还要设置SP吗? 51单片机复位I\O是都是高电平,在设计电路时要低电平有效才合理呀?
页:
[1]