<p>题目:按一下亮一个灯,再按一下亮两颗灯,直到全亮</p>
<h3>实验说明</h3>
<p>按P32亮一颗LED灯,直至全亮;再加了一个功能,按P33灭一颗LED灯直至全灭</p>
<h3>代码实现</h3>
<h4>按键代码</h4>
<p>key.h</p>
<pre><code>#ifndef __KEY_H
#define __KEY_H
/* Includes ------------------------------------------------------------------*/
#include <AI8051U.H>
#include "delay.h"
#define SW_2 P32 /* 定义SW2的控制引脚 */
#define SW_3 P33 /* 定义SW3的控制引脚 */
#define UP 1 /* 按键抬起 */
#define DOWN 0 /* 按键按下 */
#define SW2 2 /* 定义SW2键值 */
#define SW3 3 /* 定义SW3键值 */
void key_init();
unsigned char scan_key();
#endif
</code></pre>
<p>key.c</p>
<pre><code>#include "key.h"
void key_init()
{
P3M0 = 0; P3M1 = 0; /* 设置P3端口为准双向 */
}
/**
* @brief 扫描哪个按键被按下
* @param 无
* @retval 被按下键的键值
*/
unsigned char scan_key()
{
unsigned char key_value = 0;
if (SW_2 == DOWN)
{
Delay_ms(10); /* 延时消抖 */
if(SW_2 == DOWN)
{
while (SW_2 == DOWN)
; /* 等待按键抬起 */
key_value = SW2;
}
}
else if (SW_3 == DOWN)
{
Delay_ms(10); /* 延时消抖 */
if(SW_3 == DOWN)
{
while (SW_3 == DOWN)
; /* 等待按键抬起 */
key_value = SW3;
}
}
return key_value;
}
</code></pre>
<h4>LED代码</h4>
<p>led.h</p>
<pre><code>#ifndef __LED_H
#define __LED_H
/* Includes ------------------------------------------------------------------*/
#include <AI8051U.H>
#define LED_PORT P0 // 定义LED端口
#define LED_SW P40 // 定义LED组开关
#define LED0 P00 // 定义LED0控制引脚
#define ON 0 // LED点亮
#define OFF 1 // LED熄灭
void LED_Init();
#endif
</code></pre>
<p>led.c</p>
<pre><code>#include "led.h"
void LED_Init()
{
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
LED_PORT = 0xFF;
LED_SW = 0;
}
</code></pre>
<h4>main函数实现</h4>
<p>main.c</p>
<pre><code>#include "led.h"
#include "key.h"
void main()
{
unsigned char key_value = 0;
WTST = 0; // 设置程序指令延时参数
EAXFR = 1; // 扩展寄存器(XFR)访问使能
CKCON= 0; // 提高访问XRAM速度
LED_Init();
key_init();
while(1)
{
key_value = scan_key();
if (key_value == SW2)
{
LED_PORT <<= 1; // 实现亮灯
}
else if (key_value == SW3)
{
LED_PORT = (LED_PORT >> 1) | 0x80; // 实现灭灯
}
}
}
</code></pre>
<h3>实验现象</h3>
<video controls="controls" src="forum.php?mod=attachment&aid=75036"></video>
<h2>第八集 定时器周期性调度任务</h2>
<h3>数组</h3>
<ol>
<li>定义<br />
类型 名称[长度] = {数值};</li>
<li>使用<br />
赋值:名称[索引] = 数值;<br />
<img src="data/attachment/forum/202412/29/231859wy299e7za1b1yueg.png" alt="image.png" title="image.png" /></li>
</ol>
<h3>文件的创建(.c和.h)</h3>
<p>创建程序文件三步,把硬件需要的初始化弄到一个config.c<br />
新建文件并保存<br />
添加到工程<br />
添加引用路径</p>
<p>一般一个.c和一个.h文件执行一个外设或者一个任务或功能。这样可以让代码看起来简洁明了</p>
<p>以下是通过定时器,实现LED0,LED1和LED2以0.5S 1S 2S的频率亮灭<br />
task.h</p>
<pre><code>#ifndef __TASK_H_
#define __TASK_H_
/* Includes ------------------------------------------------------------------*/
#include "type_def.h"
#include ".\led\led.h"
//========================================================================
// 本地变量声明
//========================================================================
typedef struct
{
u8 Run; //任务状态:Run/Stop
u16 TIMCount; //定时计数器
u16 TRITime; //重载计数器
void (*TaskHook) (void); //任务函数
} TASK_COMPONENTS;
//========================================================================
// 外部函数和变量声明
//========================================================================
void Task_Marks_Handler_Callback(void);
void Task_Pro_Handler_Callback(void);
#endif
</code></pre>
<p>task.c</p>
<pre><code>#include "task.h"
//========================================================================
// 本地变量声明
//========================================================================
static TASK_COMPONENTS Task_Comps[]=
{
//状态计数周期函数
{0, 500, 500, LED0_blink}, /* task 1 Period: 500ms */
{0, 1000, 1000, LED1_blink}, /* task 2 Period: 1000ms */
{0, 2000, 2000, LED2_blink} /* task 3 Period: 2000ms */
};
u8 Tasks_Max = sizeof(Task_Comps)/sizeof(Task_Comps);
//========================================================================
// 函数: Task_Handler_Callback
// 描述: 任务标记回调函数.
// 参数: None.
// 返回: None.
// 版本: V1.0,
//========================================================================
void Task_Marks_Handler_Callback(void)
{
u8 i;
for(i=0; i<Tasks_Max; i++)
{
if(Task_Comps.TIMCount) /* If the time is not 0 */
{
Task_Comps.TIMCount--; /* Time counter decrement */
if(Task_Comps.TIMCount == 0) /* If time arrives */
{
/*Resume the timer value and try again */
Task_Comps.TIMCount = Task_Comps.TRITime;
Task_Comps.Run = 1; /* The task can be run */
}
}
}
}
//========================================================================
// 函数: Task_Pro_Handler_Callback
// 描述: 任务处理回调函数.
// 参数: None.
// 返回: None.
// 版本: V1.0
//========================================================================
void Task_Pro_Handler_Callback(void)
{
u8 i;
for(i=0; i<Tasks_Max; i++)
{
if(Task_Comps.Run) /* If task can be run */
{
Task_Comps.Run = 0; /* Flag clear 0 */
Task_Comps.TaskHook(); /* Run task */
}
}
}
</code></pre>
<p>timer.h</p>
<pre><code>#ifndef __TiMER_H
#define __TIMER_H
#include "sys_config.h"
#include <AI8051U.h>
#include "type_def.h"
#include "task.h"
void timer_init(void);
#endif
</code></pre>
<p>timer.c</p>
<pre><code>#include "timer.h"
/**
* @brief 定时器配置
* @param 无
* @retval 无
*/
void timer_init(void)
{
AUXR = 0x80; //Timer0 1T模式, 16位自动重装计时器,
TH0 = (u8)(Timer0_Reload / 256);
TL0 = (u8)(Timer0_Reload % 256);
ET0 = 1; //Timer0 中断使能
TR0 = 1; //Tiner0 运行
}
void Timer0_ISR_Handler (void) interrupt TMR0_VECTOR //进中断时已经清除标志
{
Task_Marks_Handler_Callback(); //任务标记回调函数
}
</code></pre>
<p>main.c</p>
<pre><code>#include "sys_init.h"
//#include "sys_config.h"
#include "task.h"
void main()
{
SYS_Init();
while(1)
{
Task_Pro_Handler_Callback();
}
}
</code></pre>
<h3>实现效果如图</h3>
<video controls="controls" src="forum.php?mod=attachment&aid=78035"></video>
页:
1
[2]