|
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来反美的!
|