冰封眸 发表于 2024-12-20 22:12:20

<h2>第六集 课后作业</h2>
<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 &lt;AI8051U.H&gt;
#include &quot;delay.h&quot;

#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 &quot;key.h&quot;

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 &lt;AI8051U.H&gt;

#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 &quot;led.h&quot;

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 &quot;led.h&quot;
#include &quot;key.h&quot;

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 &lt;&lt;= 1;                        // 实现亮灯
      }
      else if (key_value == SW3)
      {
            LED_PORT = (LED_PORT &gt;&gt; 1) | 0x80;    // 实现灭灯
      }
    }
}
</code></pre>
<h3>实验现象</h3>
<video controls="controls" src="forum.php?mod=attachment&amp;aid=75036"></video>

冰封眸 发表于 2024-12-29 23:31:49

<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 &quot;type_def.h&quot;
#include &quot;.\led\led.h&quot;

//========================================================================
//                               本地变量声明
//========================================================================
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 &quot;task.h&quot;

//========================================================================
//                               本地变量声明
//========================================================================

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&lt;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&lt;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 &quot;sys_config.h&quot;
#include &lt;AI8051U.h&gt;
#include &quot;type_def.h&quot;
#include &quot;task.h&quot;

void timer_init(void);

#endif
</code></pre>
<p>timer.c</p>
<pre><code>#include &quot;timer.h&quot;

/**
* @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 &quot;sys_init.h&quot;
//#include &quot;sys_config.h&quot;
#include &quot;task.h&quot;

void main()
{
    SYS_Init();
    while(1)
    {
      Task_Pro_Handler_Callback();
    }
}
</code></pre>
<h3>实现效果如图</h3>
<video controls="controls" src="forum.php?mod=attachment&amp;aid=78035"></video>
页: 1 [2]
查看完整版本: 《8051U深度入门到32位51大型实战视频》学习打卡 | 已送